Skip to content

Commit 4db68ef

Browse files
committed
Rw2Decoder: populateHuffmanLUT(): add missing error checks
1 parent 3981592 commit 4db68ef

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

src/librawspeed/decoders/Rw2Decoder.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "adt/Array1DRef.h"
2424
#include "adt/Array1DRefExtras.h"
2525
#include "adt/Array2DRef.h"
26+
#include "adt/Bit.h"
27+
#include "adt/Casts.h"
2628
#include "adt/Point.h"
2729
#include "bitstreams/BitStreams.h"
2830
#include "common/BayerPhase.h"
@@ -187,18 +189,38 @@ populateHuffmanLUT(const TiffIFD& ifd) {
187189

188190
ByteStream stream = ifd.getEntry(TiffTag::PANASONIC_V8_HUF_TABLE)->getData();
189191

192+
const auto numSymbols = stream.getU16();
193+
if (numSymbols < 1 || numSymbols > 17)
194+
ThrowRDE("Unexpected number of symbols: %u", numSymbols);
195+
190196
struct HuffEntry {
191-
uint16_t bitcount, symbol, mask;
197+
uint8_t bitcount;
198+
uint16_t symbol, mask;
199+
uint8_t codeValue;
192200
};
193-
std::vector<HuffEntry> huffTable(stream.getU16());
194-
195-
for (HuffEntry& entry : huffTable) {
196-
entry.bitcount = stream.getU16(); // Number of bits in symbol
197-
entry.symbol = uint16_t(stream.getU16() << (16U - entry.bitcount));
201+
std::vector<HuffEntry> huffTable;
202+
huffTable.reserve(numSymbols);
203+
204+
for (unsigned symbolIndex = 0; symbolIndex != numSymbols; ++symbolIndex) {
205+
const auto len = stream.getU16(); // Number of bits in symbol
206+
if (len < 1 || len > 16)
207+
ThrowRDE("Unexpected symbol length");
208+
const auto code = stream.getU16();
209+
if (!isIntN<uint32_t>(code, len))
210+
ThrowRDE("Bad symbol code");
211+
HuffEntry entry;
212+
entry.bitcount = implicit_cast<uint8_t>(len);
213+
entry.symbol = uint16_t(code << (16U - entry.bitcount));
214+
entry.codeValue = implicit_cast<uint8_t>(symbolIndex);
198215
entry.mask = uint16_t(
199216
0xffffU << (16U -
200217
entry.bitcount)); // mask of the bits overlapping symbol
218+
if (entry.bitcount == PanasonicV8Decompressor::HuffmanLUTEntry().bitcount &&
219+
entry.codeValue == PanasonicV8Decompressor::HuffmanLUTEntry().diffCat)
220+
ThrowRDE("Sentinel symbol encountered");
221+
huffTable.emplace_back(entry);
201222
}
223+
assert(table.size() == numSymbols);
202224

203225
// Cache of Huffman table results for all possible 16-bit values.
204226
mHuffmanLUT.resize(1 + UINT16_MAX);
@@ -207,11 +229,11 @@ populateHuffmanLUT(const TiffIFD& ifd) {
207229
// prefix codes recorded in the table.
208230
for (unsigned li = 0; li < mHuffmanLUT.size(); ++li) {
209231
PanasonicV8Decompressor::HuffmanLUTEntry& lutVal = mHuffmanLUT[li];
210-
for (unsigned ti = 0; ti < huffTable.size(); ++ti) {
211-
if ((uint16_t(li) & huffTable[ti].mask) == huffTable[ti].symbol) {
212-
lutVal.bitcount = uint8_t(huffTable[ti].bitcount);
213-
lutVal.diffCat = uint8_t(ti);
214-
break;
232+
for (const auto& ti : huffTable) {
233+
if ((uint16_t(li) & ti.mask) == ti.symbol) {
234+
lutVal.bitcount = ti.bitcount;
235+
lutVal.diffCat = ti.codeValue;
236+
break; // NOTE: not a prefix code!
215237
}
216238
}
217239
}

0 commit comments

Comments
 (0)