Skip to content

Commit 78d2536

Browse files
authored
Merge pull request #862 from LebedevRI/panasonic-v8-fuzz
Panasonic v8: a few more fuzz fixes
2 parents 88feeaf + 44b5ae9 commit 78d2536

File tree

4 files changed

+31
-25
lines changed

4 files changed

+31
-25
lines changed

fuzz/librawspeed/decompressors/PanasonicV8Decompressor.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
8686
auto stripHeightsInput = bs.getStream(numStripHeights, sizeof(uint16_t));
8787
auto defineCodes = bs.getStream(numDefineCodesSize);
8888
const auto initialPrediction = bs.getArray<uint16_t, 4>();
89+
const auto imgDim = bs.getArray<int, 2>();
8990

9091
// The rest of the bs are the input strips.
9192

@@ -112,10 +113,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
112113
auto stripHeights = stripHeightsInput.getVector<uint16_t>(numStripHeights);
113114
stripHeights.reserve(1); // Array1DRef does not like nullptr's.
114115

115-
const auto imgDim = iRectangle2D({0, 0}, mRaw->dim);
116-
117116
PanasonicV8Decompressor::DecompressorParamsBuilder builder(
118-
imgDim, initialPrediction, getAsArray1DRef(strips),
117+
{imgDim[0], imgDim[1]}, initialPrediction, getAsArray1DRef(strips),
119118
getAsArray1DRef(stripLineOffsets), getAsArray1DRef(stripWidths),
120119
getAsArray1DRef(stripHeights), defineCodes);
121120

src/librawspeed/decoders/Rw2Decoder.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,8 @@ RawImage Rw2Decoder::decodeRawV8(const TiffIFD& raw) const {
250250
const std::vector<Array1DRef<const uint8_t>> mStrips =
251251
getInputStrips(mParams, mFile);
252252

253-
const auto imgDim = iRectangle2D({0, 0}, mRaw->dim);
254-
255253
PanasonicV8Decompressor::DecompressorParamsBuilder b(
256-
imgDim, mParams.initialPrediction, getAsArray1DRef(mStrips),
254+
mRaw->dim, mParams.initialPrediction, getAsArray1DRef(mStrips),
257255
getAsArray1DRef(mParams.stripLineOffsets),
258256
getAsArray1DRef(mParams.stripWidths),
259257
getAsArray1DRef(mParams.stripHeights),

src/librawspeed/decompressors/PanasonicV8Decompressor.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,9 @@ evaluateConsecutiveTiles(const iRectangle2D rect, const iRectangle2D nextRect) {
167167
return Invalid;
168168
}
169169

170-
void isValidImageGrid(iRectangle2D imgDim,
171-
Array1DRef<const iRectangle2D> rects) {
172-
auto outPos = imgDim.pos;
173-
invariant(outPos.x == 0 && outPos.y == 0);
170+
void isValidImageGrid(iPoint2D imgSize, Array1DRef<const iRectangle2D> rects) {
171+
auto outPos = iPoint2D(0, 0);
172+
const auto imgDim = iRectangle2D(outPos, imgSize);
174173

175174
iRectangle2D rect = rects(0);
176175
if (rect.pos != outPos)
@@ -296,11 +295,13 @@ PanasonicV8Decompressor::DecompressorParamsBuilder::getDecoderLUT(
296295

297296
std::vector<iRectangle2D>
298297
PanasonicV8Decompressor::DecompressorParamsBuilder::getOutRects(
299-
iRectangle2D imgDim, Array1DRef<const uint32_t> stripLineOffsets,
298+
iPoint2D imgSize, Array1DRef<const uint32_t> stripLineOffsets,
300299
Array1DRef<const uint16_t> stripWidths,
301300
Array1DRef<const uint16_t> stripHeights) {
302-
if (!imgDim.hasPositiveArea())
301+
if (!imgSize.hasPositiveArea())
303302
ThrowRDE("Empty image requested");
303+
if (imgSize.x % 2 != 0 || imgSize.y % 2 != 0)
304+
ThrowRDE("Image size is not multiple of 2");
304305
const int totalStrips = stripLineOffsets.size();
305306
if (stripWidths.size() != totalStrips || stripHeights.size() != totalStrips)
306307
ThrowRDE("Inputs have mismatched length");
@@ -317,16 +318,22 @@ PanasonicV8Decompressor::DecompressorParamsBuilder::getOutRects(
317318

318319
const auto rect = iRectangle2D(iPoint2D(stripOutputX, stripOutputY),
319320
iPoint2D(stripWidth, stripHeight));
321+
const auto imgDim = iRectangle2D({0, 0}, imgSize);
320322

321323
if (!rect.isThisInside(imgDim))
322324
ThrowRDE("Tile isn't fully within the output image");
323325
if (!rect.hasPositiveArea())
324326
ThrowRDE("The tile is empty");
325327

328+
if (rect.pos.x % 2 != 0 || rect.pos.y % 2 != 0)
329+
ThrowRDE("Tile position is not multiple of 2");
330+
if (rect.dim.x % 2 != 0 || rect.dim.y % 2 != 0)
331+
ThrowRDE("Tile size is not multiple of 2");
332+
326333
mOutRects.emplace_back(rect);
327334
}
328335

329-
isValidImageGrid(imgDim, getAsArray1DRef(mOutRects));
336+
isValidImageGrid(imgSize, getAsArray1DRef(mOutRects));
330337
return mOutRects;
331338
}
332339

@@ -340,7 +347,7 @@ PanasonicV8Decompressor::PanasonicV8Decompressor(RawImage outputImg,
340347
mRawOutput->getBpp() != sizeof(uint16_t)) {
341348
ThrowRDE("Unexpected component count / data type");
342349
}
343-
if (!mRawOutput->dim.hasPositiveArea())
350+
if (mRawOutput->dim != mParams.imgSize)
344351
ThrowRDE("Unexpected image dimensions");
345352
const auto maxBpp = maxBitsPerPixelNeeded(mParams.mDecoderLUT);
346353
if (maxBpp > 32) {
@@ -426,7 +433,6 @@ void PanasonicV8Decompressor::decompressStrip(const Array2DRef<uint16_t> out,
426433
for (int i = 0; i != 2; ++i) {
427434
const int32_t diff = decoder.decodeNextDiffValue();
428435
const int32_t decodedValue = pred(i, j) + diff;
429-
invariant(decodedValue > 0);
430436
pred(i, j) = uint16_t(std::clamp(
431437
decodedValue, 0, int32_t(std::numeric_limits<uint16_t>::max())));
432438
outBlock(i, j) = pred(i, j);

src/librawspeed/decompressors/PanasonicV8Decompressor.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class PanasonicV8Decompressor final : public AbstractDecompressor {
6969
struct DecompressorParamsBuilder;
7070

7171
struct DecompressorParams {
72+
iPoint2D imgSize;
7273
const Array1DRef<const Array1DRef<const uint8_t>> mStrips;
7374
const Array1DRef<const iRectangle2D> mOutRect;
7475
const Array1DRef<const DecoderLUTEntry> mDecoderLUT;
@@ -79,15 +80,17 @@ class PanasonicV8Decompressor final : public AbstractDecompressor {
7980
private:
8081
friend struct DecompressorParamsBuilder;
8182

82-
DecompressorParams(Array1DRef<const Array1DRef<const uint8_t>> mStrips_,
83+
DecompressorParams(iPoint2D imgSize_,
84+
Array1DRef<const Array1DRef<const uint8_t>> mStrips_,
8385
Array1DRef<const iRectangle2D> mOutRect_,
8486
Array1DRef<const DecoderLUTEntry> mDecoderLUT_,
8587
Bayer2x2 initialPrediction_)
86-
: mStrips(mStrips_), mOutRect(mOutRect_), mDecoderLUT(mDecoderLUT_),
87-
initialPrediction(initialPrediction_) {}
88+
: imgSize(imgSize_), mStrips(mStrips_), mOutRect(mOutRect_),
89+
mDecoderLUT(mDecoderLUT_), initialPrediction(initialPrediction_) {}
8890
};
8991

9092
struct DecompressorParamsBuilder {
93+
iPoint2D imgSize;
9194
const std::vector<PanasonicV8Decompressor::DecoderLUTEntry> mDecoderLUT;
9295
const Array1DRef<const Array1DRef<const uint8_t>> mStrips;
9396
const Bayer2x2 initialPrediction;
@@ -98,20 +101,20 @@ class PanasonicV8Decompressor final : public AbstractDecompressor {
98101
ByteStream bs);
99102

100103
std::vector<iRectangle2D> static getOutRects(
101-
iRectangle2D imgDim, Array1DRef<const uint32_t> stripLineOffsets,
104+
iPoint2D imgSize, Array1DRef<const uint32_t> stripLineOffsets,
102105
Array1DRef<const uint16_t> stripWidths,
103106
Array1DRef<const uint16_t> stripHeights);
104107

105108
// NOLINTNEXTLINE(readability-function-size)
106109
DecompressorParamsBuilder(
107-
iRectangle2D imgDim, Bayer2x2 initialPrediction_,
110+
iPoint2D imgSize_, Bayer2x2 initialPrediction_,
108111
Array1DRef<const Array1DRef<const uint8_t>> mStrips_,
109112
Array1DRef<const uint32_t> stripLineOffsets,
110113
Array1DRef<const uint16_t> stripWidths,
111114
Array1DRef<const uint16_t> stripHeights, ByteStream defineCodes)
112-
: mDecoderLUT(getDecoderLUT(defineCodes)), mStrips(mStrips_),
113-
initialPrediction(initialPrediction_),
114-
mOutRects(getOutRects(imgDim, stripLineOffsets, stripWidths,
115+
: imgSize(imgSize_), mDecoderLUT(getDecoderLUT(defineCodes)),
116+
mStrips(mStrips_), initialPrediction(initialPrediction_),
117+
mOutRects(getOutRects(imgSize, stripLineOffsets, stripWidths,
115118
stripHeights)) {
116119
if (mStrips.size() != implicit_cast<int>(mOutRects.size()))
117120
ThrowRDE("Got different number of input strips vs output tiles");
@@ -122,8 +125,8 @@ class PanasonicV8Decompressor final : public AbstractDecompressor {
122125
}
123126

124127
[[nodiscard]] DecompressorParams getDecompressorParams() const {
125-
return {mStrips, getAsArray1DRef(mOutRects), getAsArray1DRef(mDecoderLUT),
126-
initialPrediction};
128+
return {imgSize, mStrips, getAsArray1DRef(mOutRects),
129+
getAsArray1DRef(mDecoderLUT), initialPrediction};
127130
}
128131
};
129132

0 commit comments

Comments
 (0)