aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michael@niedermayer.cc>2020-08-20 01:05:35 +0200
committerMichael Niedermayer <michael@niedermayer.cc>2021-09-09 13:37:20 +0200
commita4f01dfad9f4294f7393f67b0d7bbb45e9c46f23 (patch)
tree8e7b6915652884e9e4898b84e6b90ba3bec812eb
parent2e9d90680d2ca8911525de59d464ac3796844fb4 (diff)
downloadffmpeg-a4f01dfad9f4294f7393f67b0d7bbb45e9c46f23.tar.gz
avcodec/tiff: Restrict tag order based on specification
"The entries in an IFD must be sorted in ascending order by Tag. Note that this is not the order in which the fields are described in this document." This way various dimensions, sample and bit sizes cannot be changed at arbitrary times which reduces the potential for bugs. The tag reading code also on various places assumes that numerically previous tags have already been parsed, so this needs to be enforced one way or another. If this commit causes problems with real world files which are not easy to fix then some other form of checks are needed to ensure the various dependencies in the tag reading are not violated. Fixes: out of array access Fixes: 24825/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-6326925027704832 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> (cherry picked from commit ad29f9e47cb848e11ee1d358d2bae15cd35ef04b) Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r--libavcodec/tiff.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index a9f93494ed..088584b686 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -64,6 +64,7 @@ typedef struct TiffContext {
int predictor;
int fill_order;
uint32_t res[4];
+ unsigned last_tag;
int strips, rps, sstype;
int sot;
@@ -801,6 +802,12 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame)
if (ret < 0) {
goto end;
}
+ if (tag <= s->last_tag)
+ return AVERROR_INVALIDDATA;
+
+ // We ignore TIFF_STRIP_SIZE as it is sometimes in the logic but wrong order around TIFF_STRIP_OFFS
+ if (tag != TIFF_STRIP_SIZE)
+ s->last_tag = tag;
off = bytestream2_tell(&s->gb);
if (count == 1) {
@@ -1239,6 +1246,7 @@ static int decode_frame(AVCodecContext *avctx,
s->photometric = TIFF_PHOTOMETRIC_NONE;
s->compr = TIFF_RAW;
s->fill_order = 0;
+ s->last_tag = 0;
free_geotags(s);
// Reset these offsets so we can tell if they were set this frame