PR #23409 opened by iceray
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23409
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23409.patch

# Summary of changes

This PR fixes **two** UBSan-reported undefined behavior issues found by fuzzing 
with
the upstream demuxer fuzz target.

### `libavcodec/cbs_av1.c`:

The AV1 coded bitstream assembler concatenates each unit's bitstream data into
`frag->data`. A fuzzed AV1 input can produce a unit with `data == NULL` and
`data_size == 0`. Calling `memcpy(dst, NULL, 0)` is still undefined behavior
under the C library `nonnull` contract, and UBSan reports it as:

```text
libavcodec/cbs_av1.c:1256:34: runtime error: null pointer passed as argument 2, 
which is declared to never be null
```

The fix validates that positive-sized units have a data pointer before
assembling the fragment, and skips `memcpy()` for zero-sized units.

### `libavformat/sbgdec.c`:

The SBG demuxer parses the `-F` fade time option with `strtod()` and then stores
the converted timestamp in an `int64_t` field. Extremely large values can exceed
the representable range of the destination integer type, which UBSan reports as:

```text
libavformat/sbgdec.c:386:44: runtime error: 1.84467e+22 is outside the range of 
representable values of type 'long'
```

The fix rejects negative, NaN, infinite, and out-of-range `-F` values before the
double-to-integer conversion, using the existing `syntax error for option -F`
error path.

Both fixes are narrowly scoped to the affected functions and make malformed
fuzzer inputs fail parsing/assembly cleanly instead of reaching undefined
behavior.

No new FATE samples are included.


# Local validation

Validated against FFmpeg 8.1 origin build with `tools/target_dem_fuzzer`.

For `libavcodec/cbs_av1.c`:

```text
origin replay exit: 134
origin UBSan: libavcodec/cbs_av1.c:1256:34: null pointer passed as argument 2
fixed replay exit: 0
```

For `libavformat/sbgdec.c`:

```text
origin replay exit: 134
origin UBSan: libavformat/sbgdec.c:386:44: value outside representable range of 
type 'long'
fixed replay exit: 0
```



>From 85bbc84ff6ff3612d47df329972ceebd2996ef76 Mon Sep 17 00:00:00 2001
From: iceray <[email protected]>
Date: Mon, 8 Jun 2026 13:02:26 +0000
Subject: [PATCH 1/2] Update to fix UBSan Bug by iceray

origin:
`runtime error: null pointer passed as argument 2, which is declared to never 
be null`
---
 libavcodec/cbs_av1.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c
index deb73c8ebb..c60bee4225 100644
--- a/libavcodec/cbs_av1.c
+++ b/libavcodec/cbs_av1.c
@@ -1242,8 +1242,11 @@ static int 
cbs_av1_assemble_fragment(CodedBitstreamContext *ctx,
     int i;
 
     size = 0;
-    for (i = 0; i < frag->nb_units; i++)
+    for (i = 0; i < frag->nb_units; i++) {
+        if (frag->units[i].data_size && !frag->units[i].data)
+            return AVERROR_INVALIDDATA;
         size += frag->units[i].data_size;
+    }
 
     frag->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
     if (!frag->data_ref)
@@ -1253,8 +1256,9 @@ static int 
cbs_av1_assemble_fragment(CodedBitstreamContext *ctx,
 
     pos = 0;
     for (i = 0; i < frag->nb_units; i++) {
-        memcpy(frag->data + pos, frag->units[i].data,
-               frag->units[i].data_size);
+        if (frag->units[i].data_size)
+            memcpy(frag->data + pos, frag->units[i].data,
+                  frag->units[i].data_size);
         pos += frag->units[i].data_size;
     }
     av_assert0(pos == size);
-- 
2.52.0


>From c2e701a14770f8dbd69ce17d2766e4a8eb32f57d Mon Sep 17 00:00:00 2001
From: iceray <[email protected]>
Date: Mon, 8 Jun 2026 13:06:16 +0000
Subject: [PATCH 2/2] Update to fix UBSan Bug by iceray in
 libavformat/sbgdec.c:386:44

runtime error: 1.84467e+22 is outside the range of representable values of type 
'long'
---
 libavformat/sbgdec.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libavformat/sbgdec.c b/libavformat/sbgdec.c
index 71cbad2dae..e1f202ffea 100644
--- a/libavformat/sbgdec.c
+++ b/libavformat/sbgdec.c
@@ -384,6 +384,11 @@ static int parse_options(struct sbg_parser *p)
                                  "syntax error for option -F");
                         return AVERROR_INVALIDDATA;
                     }
+                    if (!(v >= 0 && v <= (double)(INT64_MAX / (AV_TIME_BASE / 
1000)))) {
+                        snprintf(p->err_msg, sizeof(p->err_msg),
+                                 "syntax error for option -F");
+                        return AVERROR_INVALIDDATA;
+                    }
                     p->scs.opt_fade_time = v * AV_TIME_BASE / 1000;
                     break;
                 case 'L':
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to