Skip to content

Commit

Permalink
Fix handling for corrupt number of DC components
Browse files Browse the repository at this point in the history
When the number of DC components has been incorrectly stored in the dwa
subheader, this causes a cascade of errors, resulting in out of bounds
access. Instead, track how many we've read and detect when we're out as
soon as possible

Fixes OSS-Fuzz #59457

Signed-off-by: Kimball Thurston <kdt3rd@gmail.com>
  • Loading branch information
kdt3rd committed Jul 10, 2023
1 parent 811c941 commit 0a3c5d0
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
4 changes: 4 additions & 0 deletions src/lib/OpenEXRCore/internal_dwa_compressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,7 @@ DwaCompressor_uncompress (
packedAcBufferEnd,
packedAcBufferEnd + totalAcUncompressedCount * sizeof (uint16_t),
packedDcBufferEnd,
totalDcUncompressedCount,
dwaCompressorToLinear,
me->_channelData[rChan].chan->width,
me->_channelData[rChan].chan->height);
Expand All @@ -1090,6 +1091,7 @@ DwaCompressor_uncompress (
packedAcBufferEnd += decoder._packedAcCount * sizeof (uint16_t);

packedDcBufferEnd += decoder._packedDcCount * sizeof (uint16_t);
totalDcUncompressedCount -= decoder._packedDcCount;

me->_channelData[rChan].processed = 1;
me->_channelData[gChan].processed = 1;
Expand Down Expand Up @@ -1133,6 +1135,7 @@ DwaCompressor_uncompress (
packedAcBufferEnd +
totalAcUncompressedCount * sizeof (uint16_t),
packedDcBufferEnd,
totalDcUncompressedCount,
linearLut,
chan->width,
chan->height);
Expand All @@ -1147,6 +1150,7 @@ DwaCompressor_uncompress (
packedDcBufferEnd +=
(size_t) decoder._packedDcCount * sizeof (uint16_t);

totalDcUncompressedCount -= decoder._packedDcCount;
if (rv != EXR_ERR_SUCCESS) { return rv; }
}

Expand Down
24 changes: 19 additions & 5 deletions src/lib/OpenEXRCore/internal_dwa_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ typedef struct _LossyDctDecoder
uint8_t* _packedAcEnd;
uint8_t* _packedDc;

uint64_t _remDcCount;

//
// half -> half LUT to transform from nonlinear to linear
//
Expand All @@ -57,6 +59,7 @@ static exr_result_t LossyDctDecoder_base_construct (
uint8_t* packedAc,
uint8_t* packedAcEnd,
uint8_t* packedDc,
uint64_t remDcCount,
const uint16_t* toLinear,
int width,
int height);
Expand All @@ -67,6 +70,7 @@ static exr_result_t LossyDctDecoder_construct (
uint8_t* packedAc,
uint8_t* packedAcEnd,
uint8_t* packedDc,
uint64_t remDcCount,
const uint16_t* toLinear,
int width,
int height);
Expand All @@ -79,6 +83,7 @@ static exr_result_t LossyDctDecoderCsc_construct (
uint8_t* packedAc,
uint8_t* packedAcEnd,
uint8_t* packedDc,
uint64_t remDcCount,
const uint16_t* toLinear,
int width,
int height);
Expand Down Expand Up @@ -115,6 +120,7 @@ LossyDctDecoder_construct (
uint8_t* packedAc,
uint8_t* packedAcEnd,
uint8_t* packedDc,
uint64_t remDcCount,
const uint16_t* toLinear,
int width,
int height)
Expand All @@ -127,7 +133,7 @@ LossyDctDecoder_construct (
//

rv = LossyDctDecoder_base_construct (
d, packedAc, packedAcEnd, packedDc, toLinear, width, height);
d, packedAc, packedAcEnd, packedDc, remDcCount, toLinear, width, height);

d->_channel_decode_data[0] = rowPtrs;
d->_channel_decode_data_count = 1;
Expand Down Expand Up @@ -155,13 +161,14 @@ LossyDctDecoderCsc_construct (
uint8_t* packedAc,
uint8_t* packedAcEnd,
uint8_t* packedDc,
uint64_t remDcCount,
const uint16_t* toLinear,
int width,
int height)
{
exr_result_t rv;
rv = LossyDctDecoder_base_construct (
d, packedAc, packedAcEnd, packedDc, toLinear, width, height);
d, packedAc, packedAcEnd, packedDc, remDcCount, toLinear, width, height);
if (rv != EXR_ERR_SUCCESS) return rv;

d->_channel_decode_data[0] = rowPtrsR;
Expand All @@ -180,6 +187,7 @@ LossyDctDecoder_base_construct (
uint8_t* packedAc,
uint8_t* packedAcEnd,
uint8_t* packedDc,
uint64_t remDcCount,
const uint16_t* toLinear,
int width,
int height)
Expand All @@ -189,6 +197,7 @@ LossyDctDecoder_base_construct (
d->_packedAc = packedAc;
d->_packedAcEnd = packedAcEnd;
d->_packedDc = packedDc;
d->_remDcCount = remDcCount;
d->_toLinear = toLinear;
d->_width = width;
d->_height = height;
Expand All @@ -214,19 +223,24 @@ LossyDctDecoder_execute (
int numComp = d->_channel_decode_data_count;
DctCoderChannelData* chanData[3];
int lastNonZero = 0;
int numBlocksX = (int) (ceilf ((float) d->_width / 8.0f));
int numBlocksY = (int) (ceilf ((float) d->_height / 8.0f));
int numBlocksX = (d->_width + 7) / 8;
int numBlocksY = (d->_height + 7) / 8;
int leftoverX = d->_width - (numBlocksX - 1) * 8;
int leftoverY = d->_height - (numBlocksY - 1) * 8;

int numFullBlocksX = (int) (floorf ((float) d->_width / 8.0f));
int numFullBlocksX = d->_width / 8;

uint16_t* currAcComp = (uint16_t*) (d->_packedAc);
uint16_t* acCompEnd = (uint16_t*) (d->_packedAcEnd);
uint16_t* currDcComp[3];
uint8_t* rowBlockHandle;
uint16_t* rowBlock[3];

if (d->_remDcCount < ((uint64_t)numComp * (uint64_t)numBlocksX * (uint64_t)numBlocksY))
{
return EXR_ERR_CORRUPT_CHUNK;
}

for (int chan = 0; chan < numComp; ++chan)
{
chanData[chan] = d->_channel_decode_data[chan];
Expand Down

0 comments on commit 0a3c5d0

Please sign in to comment.