diff options
-rw-r--r-- | src/huffman/huff.cpp | 50 | ||||
-rw-r--r-- | src/huffman/huff.h | 2 | ||||
-rwxr-xr-x | test/StormTest.cpp | 6 |
3 files changed, 38 insertions, 20 deletions
diff --git a/src/huffman/huff.cpp b/src/huffman/huff.cpp index 1b81017..bbb8118 100644 --- a/src/huffman/huff.cpp +++ b/src/huffman/huff.cpp @@ -22,6 +22,11 @@ #include "huff.h" //----------------------------------------------------------------------------- +// Local defined + +#define HUFF_DECOMPRESS_ERROR 0x1FF + +//----------------------------------------------------------------------------- // Table of byte-to-weight values // Table for (de)compression. Every compression type has 258 entries @@ -270,46 +275,50 @@ TInputStream::TInputStream(void * pvInBuffer, size_t cbInBuffer) } // Gets one bit from input stream -unsigned int TInputStream::Get1Bit() +bool TInputStream::Get1Bit(unsigned int & BitValue) { - unsigned int OneBit = 0; - // Ensure that the input stream is reloaded, if there are no bits left if(BitCount == 0) { + // Buffer overflow check + if(pbInBuffer >= pbInBufferEnd) + return false; + // Refill the bit buffer BitBuffer = *pbInBuffer++; BitCount = 8; } // Copy the bit from bit buffer to the variable - OneBit = (BitBuffer & 0x01); + BitValue = (BitBuffer & 0x01); BitBuffer >>= 1; BitCount--; - - return OneBit; + return true; } // Gets the whole byte from the input stream. -unsigned int TInputStream::Get8Bits() +bool TInputStream::Get8Bits(unsigned int & ByteValue) { unsigned int dwReloadByte = 0; - unsigned int dwOneByte = 0; // If there is not enough bits to get the value, // we have to add 8 more bits from the input buffer if(BitCount < 8) { + // Buffer overflow check + if(pbInBuffer >= pbInBufferEnd) + return false; + dwReloadByte = *pbInBuffer++; BitBuffer |= dwReloadByte << BitCount; BitCount += 8; } // Return the lowest 8 its - dwOneByte = (BitBuffer & 0xFF); + ByteValue = (BitBuffer & 0xFF); BitBuffer >>= 8; BitCount -= 8; - return dwOneByte; + return true; } // Gets 7 bits from the stream. DOES NOT remove the bits from input stream @@ -344,6 +353,10 @@ void TInputStream::SkipBits(unsigned int dwBitsToSkip) // we have to add 8 more bits from the input buffer if(BitCount < dwBitsToSkip) { + // Buffer overflow check + if(pbInBuffer >= pbInBufferEnd) + return; + dwReloadByte = *pbInBuffer++; BitBuffer |= dwReloadByte << BitCount; BitCount += 8; @@ -726,7 +739,7 @@ unsigned int THuffmannTree::DecodeOneByte(TInputStream * is) { // Just a sanity check if(pFirst == LIST_HEAD()) - return 0x1FF; + return HUFF_DECOMPRESS_ERROR; // We don't have the quick-link item, we need to parse the tree from its root pItem = pFirst; @@ -735,9 +748,14 @@ unsigned int THuffmannTree::DecodeOneByte(TInputStream * is) // Step down the tree until we find a terminal item while(pItem->pChildLo != NULL) { + unsigned int BitValue = 0; + // If the next bit in the compressed stream is set, we get the higher-weight // child. Otherwise, get the lower-weight child. - pItem = is->Get1Bit() ? pItem->pChildLo->pPrev : pItem->pChildLo; + if(!is->Get1Bit(BitValue)) + return HUFF_DECOMPRESS_ERROR; + + pItem = BitValue ? pItem->pChildLo->pPrev : pItem->pChildLo; BitCount++; // If the number of loaded bits reached 7, @@ -852,7 +870,8 @@ unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLen return 0; // Get the compression type from the input stream - CompressionType = is->Get8Bits(); + if(!is->Get8Bits(CompressionType)) + return 0; bIsCmp0 = (CompressionType == 0) ? 1 : 0; // Build the Huffman tree @@ -863,14 +882,15 @@ unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLen while((DecompressedValue = DecodeOneByte(is)) != 0x100) { // Did an error occur? - if(DecompressedValue == 0x1FF) // An error occurred + if(DecompressedValue == HUFF_DECOMPRESS_ERROR) return 0; // Huffman tree needs to be modified if(DecompressedValue == 0x101) { // The decompressed byte is stored in the next 8 bits - DecompressedValue = is->Get8Bits(); + if(!is->Get8Bits(DecompressedValue)) + return 0; if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue)) return 0; diff --git a/src/huffman/huff.h b/src/huffman/huff.h index cf1ca4c..e6f9e42 100644 --- a/src/huffman/huff.h +++ b/src/huffman/huff.h @@ -28,7 +28,7 @@ class TInputStream public: TInputStream(void * pvInBuffer, size_t cbInBuffer); - unsigned int Get1Bit(); + bool Get1Bit(unsigned int & BitValue); unsigned int Get8Bits(); bool Peek7Bits(unsigned int & Value); void SkipBits(unsigned int BitCount); diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 31e9981..60e2167 100755 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -3787,15 +3787,13 @@ static DWORD TestReplaceFile(LPCTSTR szMpqPlainName, LPCTSTR szFilePlainName, LP static void Test_PlayingSpace()
{
-/*
HANDLE hMpq = NULL;
- if(SFileOpenArchive(_T("e:\\poc17"), 0, 0, &hMpq))
+ if(SFileOpenArchive(_T("e:\\poc18"), 0, 0, &hMpq))
{
- SFileCompactArchive(hMpq, _T("e:\\Ladik\\Incoming\\poc17"), true);
+ SFileCompactArchive(hMpq, _T("e:\\Ladik\\Incoming\\poc18"), true);
SFileCloseArchive(hMpq);
}
-*/
}
//-----------------------------------------------------------------------------
|