Skip to content

Commit

Permalink
Fix handling for corrupt number of DC components (#1484)
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 authored Jul 23, 2023
1 parent 83c57cb commit 54dd041
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 54dd041

Please sign in to comment.