@@ -55,10 +55,11 @@ struct huffman_tree { struct huffman_tree *leafs[2]; uint16_t value; }; +static const uint_fast8_t numDistanceCodes = 30; static const uint8_t lengthCodes[29] = { /* indices are -257, values -3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 255 }; @@ -274,10 +275,16 @@ { self = [super init]; _stream = [stream retain]; _bitIndex = 8; /* 0-7 address the bit, 8 means fetch next byte */ + _slidingWindowMask = 0x7FFF; + _codes.numDistanceCodes = numDistanceCodes; + _codes.lengthCodes = lengthCodes; + _codes.lengthExtraBits = lengthExtraBits; + _codes.distanceCodes = distanceCodes; + _codes.distanceExtraBits = distanceExtraBits; return self; } - (void)dealloc @@ -292,11 +299,11 @@ { uint8_t *buffer = buffer_; uint_fast16_t bits; uint16_t value; size_t i, tmp, bytesWritten = 0; - char *slidingWindow; + uint8_t *slidingWindow; uint_fast16_t slidingWindowIndex; if (_atEndOfStream) @throw [OFReadFailedException exceptionWithStream: self requestedLength: length]; @@ -386,21 +393,23 @@ tmp = [_stream readIntoBuffer: buffer + bytesWritten length: tmp]; if OF_UNLIKELY (_slidingWindow == NULL) { - _slidingWindow = [self allocMemoryWithSize: 0x8000]; + _slidingWindow = + [self allocMemoryWithSize: _slidingWindowMask + 1]; /* Avoid leaking data */ - memset(_slidingWindow, 0, 0x8000); + memset(_slidingWindow, 0, _slidingWindowMask + 1); } slidingWindow = _slidingWindow; slidingWindowIndex = _slidingWindowIndex; for (i = 0; i < tmp; i++) { slidingWindow[slidingWindowIndex] = buffer[bytesWritten + i]; - slidingWindowIndex = (slidingWindowIndex + 1) & 0x7FFF; + slidingWindowIndex = (slidingWindowIndex + 1) & + _slidingWindowMask; } _slidingWindowIndex = slidingWindowIndex; length -= tmp; bytesWritten += tmp; @@ -572,18 +581,21 @@ buffer[bytesWritten++] = CTX.value; length--; if (_slidingWindow == NULL) { _slidingWindow = [self - allocMemoryWithSize: 0x8000]; + allocMemoryWithSize: + _slidingWindowMask + 1]; /* Avoid leaking data */ - memset(_slidingWindow, 0, 0x8000); + memset(_slidingWindow, 0, + _slidingWindowMask + 1); } _slidingWindow[_slidingWindowIndex] = CTX.value; _slidingWindowIndex = - (_slidingWindowIndex + 1) & 0x7FFF; + (_slidingWindowIndex + 1) & + _slidingWindowMask; CTX.state = AWAIT_CODE; CTX.treeIter = CTX.litLenTree; } @@ -602,16 +614,17 @@ if (CTX.state == AWAIT_DISTANCE) { if OF_UNLIKELY (!walkTree(self, &CTX.treeIter, &value)) return bytesWritten; - if OF_UNLIKELY (value > 29) + if OF_UNLIKELY (value >= + _codes.numDistanceCodes) @throw [OFInvalidFormatException exception]; - CTX.distance = distanceCodes[value]; - extraBits = distanceExtraBits[value]; + CTX.distance = _codes.distanceCodes[value]; + extraBits = _codes.distanceExtraBits[value]; if (extraBits > 0) { if OF_UNLIKELY (!tryReadBits(self, &bits, extraBits)) { CTX.state = @@ -649,20 +662,21 @@ CTX.length -= j; return bytesWritten; } index = (_slidingWindowIndex - - CTX.distance) & 0x7FFF; + CTX.distance) & _slidingWindowMask; value = _slidingWindow[index]; buffer[bytesWritten++] = value; length--; _slidingWindow[_slidingWindowIndex] = value; _slidingWindowIndex = - (_slidingWindowIndex + 1) & 0x7FFF; + (_slidingWindowIndex + 1) & + _slidingWindowMask; } CTX.state = AWAIT_CODE; CTX.treeIter = CTX.litLenTree; } @@ -692,18 +706,21 @@ buffer[bytesWritten++] = value; length--; if (_slidingWindow == NULL) { _slidingWindow = [self - allocMemoryWithSize: 0x8000]; + allocMemoryWithSize: + _slidingWindowMask + 1]; /* Avoid leaking data */ - memset(_slidingWindow, 0, 0x8000); + memset(_slidingWindow, 0, + _slidingWindowMask + 1); } _slidingWindow[_slidingWindowIndex] = value; _slidingWindowIndex = - (_slidingWindowIndex + 1) & 0x7FFF; + (_slidingWindowIndex + 1) & + _slidingWindowMask; CTX.treeIter = CTX.litLenTree; continue; } @@ -710,12 +727,12 @@ if OF_UNLIKELY (value > 285) @throw [OFInvalidFormatException exception]; /* Length of length distance pair */ lengthCodeIndex = value - 257; - CTX.length = lengthCodes[lengthCodeIndex] + 3; - extraBits = lengthExtraBits[lengthCodeIndex]; + CTX.length = _codes.lengthCodes[lengthCodeIndex] + 3; + extraBits = _codes.lengthExtraBits[lengthCodeIndex]; if (extraBits > 0) { if OF_UNLIKELY (!tryReadBits(self, &bits, extraBits)) { CTX.extraBits = extraBits;