diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2025-08-06 10:08:14 +0200 |
---|---|---|
committer | michaelni <michael@niedermayer.cc> | 2025-08-07 14:47:35 +0000 |
commit | 0d9c003d76383e82b57b6d5aa33776709d0cda2c (patch) | |
tree | 7acabbe50142f210a6da22a36fda7f3dfb0d2b29 /libavcodec/exr.c | |
parent | 8173ae547ac7710faf2d59f97d76f5aa5c33c51a (diff) | |
download | ffmpeg-0d9c003d76383e82b57b6d5aa33776709d0cda2c.tar.gz |
avcodec/exr: Check rle_raw_data and surroundings
Fixes: out of array read
Fixes: BIGSLEEP-436510153/dwa_uncompress_read.exr
Found-by: Google Big Sleep
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavcodec/exr.c')
-rw-r--r-- | libavcodec/exr.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 0a6aab662e..504fea0aac 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -996,6 +996,7 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse const int dc_h = td->ysize >> 3; GetByteContext gb, agb; int skip, ret; + int have_rle = 0; if (compressed_size <= 88) return AVERROR_INVALIDDATA; @@ -1020,6 +1021,11 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse ) return AVERROR_INVALIDDATA; + if ((uint64_t)rle_raw_size > INT_MAX) { + avpriv_request_sample(s->avctx, "Too big rle_raw_size"); + return AVERROR_INVALIDDATA; + } + bytestream2_init(&gb, src + 88, compressed_size - 88); skip = bytestream2_get_le16(&gb); if (skip < 2) @@ -1090,6 +1096,9 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse if (rle_raw_size > 0 && rle_csize > 0 && rle_usize > 0) { unsigned long dest_len = rle_usize; + if (2LL * td->xsize * td->ysize > rle_raw_size) + return AVERROR_INVALIDDATA; + av_fast_padded_malloc(&td->rle_data, &td->rle_size, rle_usize); if (!td->rle_data) return AVERROR(ENOMEM); @@ -1106,6 +1115,8 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse if (ret < 0) return ret; bytestream2_skip(&gb, rle_csize); + + have_rle = 1; } bytestream2_init(&agb, td->ac_data, ac_count * 2); @@ -1187,7 +1198,7 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse return 0; if (s->pixel_type == EXR_HALF) { - for (int y = 0; y < td->ysize && td->rle_raw_data; y++) { + for (int y = 0; y < td->ysize && have_rle; y++) { uint16_t *ao = ((uint16_t *)td->uncompressed_data) + y * td->xsize * s->nb_channels; uint8_t *ai0 = td->rle_raw_data + y * td->xsize; uint8_t *ai1 = td->rle_raw_data + y * td->xsize + rle_raw_size / 2; @@ -1196,7 +1207,7 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse ao[x] = ai0[x] | (ai1[x] << 8); } } else { - for (int y = 0; y < td->ysize && td->rle_raw_data; y++) { + for (int y = 0; y < td->ysize && have_rle; y++) { uint32_t *ao = ((uint32_t *)td->uncompressed_data) + y * td->xsize * s->nb_channels; uint8_t *ai0 = td->rle_raw_data + y * td->xsize; uint8_t *ai1 = td->rle_raw_data + y * td->xsize + rle_raw_size / 2; |