Commit c7eefe191a for ffmpeg
commit c7eefe191aa5c391a72a0f5174ebd78ff8934fdc
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Sat Oct 10 04:58:34 2026 +0200
avformat/wtvdec: reject file allocation tables that list a sector more than once
A sub-file holds each of its sectors once, so a table that lists a
sector more than once is rejected when the sub-file is opened.
Out of memory Replicated through API
Fixes: out of memory
Fixes: 472529274/clusterfuzz-testcase-minimized-ffmpeg_dem_WTV_fuzzer-5867226843643904
Fixes: 12e707wVt9Ky
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c
index 873ba72243..71d93936c3 100644
--- a/libavformat/wtvdec.c
+++ b/libavformat/wtvdec.c
@@ -31,6 +31,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/intfloat.h"
#include "libavutil/mem.h"
+#include "libavutil/qsort.h"
#include "avformat.h"
#include "avio_internal.h"
#include "demux.h"
@@ -126,6 +127,11 @@ static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence)
return offset;
}
+static int cmp_sector(const uint32_t *a, const uint32_t *b)
+{
+ return (*a > *b) - (*a < *b);
+}
+
/**
* read non-zero integers (le32) from input stream
* @param pb
@@ -208,6 +214,24 @@ static AVIOContext * wtvfile_open_sector(unsigned first_sector, uint64_t length,
return NULL;
}
+ uint32_t *sorted = av_memdup(wf->sectors, wf->nb_sectors * sizeof(*wf->sectors));
+ uint32_t *tmp = av_malloc_array(wf->nb_sectors, sizeof(*tmp));
+ int i = 0;
+ if (sorted && tmp) {
+ AV_MSORT(sorted, tmp, wf->nb_sectors, uint32_t, cmp_sector);
+ for (i = 1; i < wf->nb_sectors && sorted[i] != sorted[i - 1]; i++)
+ ;
+ if (i < wf->nb_sectors)
+ av_log(s, AV_LOG_ERROR, "file allocation table lists sector %"PRIu32" more than once\n", sorted[i]);
+ }
+ av_free(sorted);
+ av_free(tmp);
+ if (i < wf->nb_sectors) {
+ av_freep(&wf->sectors);
+ av_freep(&wf);
+ return NULL;
+ }
+
size = avio_size(s->pb);
if (size >= 0 && (int64_t)wf->sectors[wf->nb_sectors - 1] << WTV_SECTOR_BITS > size)
av_log(s, AV_LOG_WARNING, "truncated file\n");