Index: src/OFTarArchive.m ================================================================== --- src/OFTarArchive.m +++ src/OFTarArchive.m @@ -351,10 +351,13 @@ @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; + if (length > UINT64_MAX) + @throw [OFOutOfRangeException exception]; + if ((uint64_t)length > _toRead) length = (size_t)_toRead; ret = [_stream readIntoBuffer: buffer length: length]; Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -75,19 +75,18 @@ @end @interface OFZIPArchive_FileReadStream: OFStream { OFStream *_stream, *_decompressedStream; - OFZIPArchive_LocalFileHeader *_localFileHeader; - bool _hasDataDescriptor; - uint64_t _size; + OFZIPArchiveEntry *_entry; + uint64_t _toRead; uint32_t _CRC32; bool _atEndOfStream; } - initWithStream: (OFStream *)stream - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader; + entry: (OFZIPArchiveEntry *)entry; @end @interface OFZIPArchive_FileWriteStream: OFStream { OFStream *_stream; @@ -456,11 +455,11 @@ exceptionWithVersion: version]; } _lastReturnedStream = [[OFZIPArchive_FileReadStream alloc] initWithStream: _stream - localFileHeader: localFileHeader]; + entry: entry]; objc_autoreleasePoolPop(pool); return [[_lastReturnedStream retain] autorelease]; } @@ -681,18 +680,18 @@ } @end @implementation OFZIPArchive_FileReadStream - initWithStream: (OFStream *)stream - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader + entry: (OFZIPArchiveEntry *)entry { self = [super init]; @try { _stream = [stream retain]; - switch (localFileHeader->_compressionMethod) { + switch ([entry compressionMethod]) { case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE: _decompressedStream = [stream retain]; break; case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE: _decompressedStream = [[OFInflateStream alloc] @@ -706,14 +705,12 @@ @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; } - _localFileHeader = [localFileHeader retain]; - _hasDataDescriptor = (localFileHeader->_generalPurposeBitFlag & - (1 << 3)); - _size = localFileHeader->_uncompressedSize; + _entry = [entry copy]; + _toRead = [entry uncompressedSize]; _CRC32 = ~0; } @catch (id e) { [self release]; @throw e; } @@ -723,12 +720,13 @@ - (void)dealloc { [self close]; + [_stream release]; [_decompressedStream release]; - [_localFileHeader release]; + [_entry release]; [super dealloc]; } - (bool)lowlevelIsAtEndOfStream @@ -737,59 +735,37 @@ } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { - size_t min, ret; + size_t ret; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; - if (_hasDataDescriptor) { - if ([_decompressedStream isAtEndOfStream]) { - uint32_t CRC32; - - _atEndOfStream = true; - - CRC32 = [_stream readLittleEndianInt32]; - if (CRC32 == 0x08074B50) - CRC32 = [_stream readLittleEndianInt32]; - - if (~_CRC32 != CRC32) - @throw [OFChecksumFailedException exception]; - - /* - * FIXME: Check (un)compressed length! - * (Note: Both are 64 bit if the entry uses ZIP64!) - */ - - return 0; - } - - ret = [_decompressedStream readIntoBuffer: buffer - length: length]; - } else { - if (_size == 0) { - _atEndOfStream = true; - - if (~_CRC32 != _localFileHeader->_CRC32) - @throw [OFChecksumFailedException exception]; - - return 0; - } - - min = (length < _size ? length : (size_t)_size); - ret = [_decompressedStream readIntoBuffer: buffer - length: min]; - _size -= ret; - } - + if (length > UINT64_MAX) + @throw [OFOutOfRangeException exception]; + + if ((uint64_t)length > _toRead) + length = (size_t)_toRead; + + ret = [_decompressedStream readIntoBuffer: buffer + length: length]; + + if (ret == 0) + _atEndOfStream = true; + + _toRead -= ret; _CRC32 = of_crc32(_CRC32, buffer, ret); + if (_toRead == 0) + if (~_CRC32 != [_entry CRC32]) + @throw [OFChecksumFailedException exception]; + return ret; } - (void)close {