[Security] Heap buffer overflow (OOB read past GPAC sample buffer) in process_avc_sample() at mp4.c:99 when parsing a crafted MP4 file

Aperta Adatta ai principianti
#2,449 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

@yasar710 ci sta già lavorando.

Dal 4/11/2026.

  • #2453 di @yasar710 — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
74/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
c
Ambito
backend, security

Direzione di ricerca

Inizia in src/lib_ccx/mp4.c, in corrispondenza di process_avc_sample(), vicino ai controlli della lunghezza NAL e alle letture alle righe 99-100; leggi prima il codice circostante di elaborazione dei campioni. Riproduci il problema con il file MP4 malformato allegato usando AddressSanitizer, quindi verifica che le lunghezze non valide vengano rifiutate prima di accedere ai byte del campione o chiamare do_NAL(). Il lavoro è completato quando l'input malformato termina senza una lettura fuori dai limiti e un campione avc1 valido continua a essere elaborato correttamente.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

1. Summary

CCExtractor (master commit d7eb132e15f4d1e2c40f4655349596b2b8f708de, version string 0.96.5) performs an out-of-bounds read while parsing a crafted MP4 file. During GPAC-based MP4 processing of an AVC video track, process_avc_sample() (src/lib_ccx/mp4.c) walks the sample bytes NAL by NAL. The bounds check before using the NAL length is computed in 32-bit unsigned arithmetic (mp4.c:82, "i + nal_length <= previous_index || i + nal_length > s->dataLength"), so a nal_length value close to UINT32_MAX wraps around and passes both comparisons while the index i reaches s->dataLength. Line 99 then reads s->data[i] one byte past the end of the GPAC sample buffer ("s_nalu_stats.type[s->data[i] & 0x1F] += 1;"), and line 100 additionally passes the out-of-range pointer/length pair to do_NAL(). Under AddressSanitizer the process aborts with "heap-buffer-overflow ... READ of size 1 ... 0 bytes to the right of 892-byte region ... in process_avc_sample" at mp4.c:99:22.

2. Affected version / environment

- Project: CCExtractor (https://github.com/CCExtractor/ccextractor)
- Version: version string 0.96.5, master branch commit d7eb132e15f4d1e2c40f4655349596b2b8f708de (source dated 2026-10-17, binary compiled 2026-10-26)
- Environment: Linux x86_64 (Ubuntu container), ccextractor built with AddressSanitizer, statically linked; libGPAC 2.0; default CLI options, output target .srt
- Component: src/lib_ccx/mp4.c:99 (process_avc_sample), reached via process_avc_track (mp4.c:295) and processmp4 (mp4.c:989) through the GPAC MP4 demux path

3. Steps to reproduce

1. Build ccextractor at master commit d7eb132e15f4d1e2c40f4655349596b2b8f708de with AddressSanitizer.
2. Save the attached crash-input.bin (SHA-256 9d42a6cb84ce7989f69e897a7b94d4e694fd90ffecd1ddf5642746ca9dfe64b2, a malformed MP4 file, 85,748 bytes).
3. Run: ccextractor crash-input.bin
   (verification used: env ASAN_OPTIONS=abort_on_error=0:symbolize=1:detect_leaks=0:allocator_may_return_null=1:print_legend=0:malloc_context_size=0 /lh/ccextractor/src/build/ccextractor /lh/tmp/poc-export/ccx-mp4avc/crash-input.bin inside the container)
4. Observe the process abort with an AddressSanitizer heap-buffer-overflow report while "Processing track 1, type=vide subtype=avc1".
5. Negative control: a valid MP4 file with an avc1 track (negative-control.bin, SHA-256 c4e5198b915b07d943983858a3c5f339b9d5aa77151eaca1e028175c0317f4d7) takes the same GPAC path ("Processing track 1, type=vide subtype=avc1") and completes with no sanitizer report, confirming the crash is input-specific.

4. Expected behavior

ccextractor should reject the malformed NAL length (32-bit wrap-around defeat of the bounds check), skip or report the corrupted sample, and exit normally without reading past the end of the GPAC sample buffer.

5. Actual behavior

=================================================================
==2938641==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6180000063fc at pc 0x55a148390d9f bp 0x7ffd5e0f28d0 sp 0x7ffd5e0f28c8
READ of size 1 at 0x6180000063fc thread T0
    #0 0x55a148390d9e in process_avc_sample /lh/ccextractor/src/src/lib_ccx/mp4.c:99:22
    #1 0x55a148390d9e in process_avc_track /lh/ccextractor/src/src/lib_ccx/mp4.c:295:13
    #2 0x55a148390d9e in processmp4 /lh/ccextractor/src/src/lib_ccx/mp4.c:989:9
    #3 0x55a14808c4e0 in start_ccx /lh/ccextractor/src/src/ccextractor.c:252:12
0x6180000063fc is located 0 bytes to the right of 892-byte region [0x618000006080,0x6180000063fc)
allocated by thread T0 here:
    #0 0x55a147efe28b in malloc (/lh/ccextractor/src/build/ccextractor+0x19928b) (BuildId: 7698bf0a2d6a1980221851c4e3b7738245c921f8)
SUMMARY: AddressSanitizer: heap-buffer-overflow /lh/ccextractor/src/src/lib_ccx/mp4.c:99:22 in process_avc_sample

6. Impact

Out-of-bounds read on the heap (CWE-125). The read byte past the GPAC sample buffer is used as an NAL-type statistic index, and the same out-of-range cursor/length pair is then handed to do_NAL() (mp4.c:100), which parses attacker-reachable out-of-bounds memory as NAL content; under AddressSanitizer the process aborts deterministically, and outside the sanitizer the oversized NAL parse walks into unmapped memory and crashes. Automated caption-extraction or transcoding pipelines that accept user media can therefore be crashed by a single crafted file. No write primitive is demonstrated; information disclosure was not observed (the read value only increments an internal counter), and the conservative CVSS impact ratings are documented in the attached report.

7. Suggested fix

Perform the end-of-NAL bounds check in wrap-safe (64-bit) arithmetic, e.g.

    const u32 previous_index = i;
    i += c->nal_unit_size;

[poc.zip](https://github.com/user-attachments/files/34296733/poc.zip)

    if ((uint64_t)i + nal_length <= previous_index || (uint64_t)i + nal_length > s->dataLength)
        return status;

and additionally reject nal_length values that exceed the remaining sample bytes before line 99 reads s->data[i] and before do_NAL() is called at line 100. An equivalent alternative is to validate `nal_length <= s->dataLength - i` explicitly after reading the length field.

8. Additional context (PoC / logs, redacted)

- Attached: crash-input.bin (malformed MP4, ftyp/free/mdat boxes, one avc1 video track; SHA-256 9d42a6cb84ce7989f69e897a7b94d4e694fd90ffecd1ddf5642746ca9dfe64b2)
- Negative control attached: negative-control.bin (valid MP4 with avc1 track, SHA-256 c4e5198b915b07d943983858a3c5f339b9d5aa77151eaca1e028175c0317f4d7) — same code path, runs clean
- Crash discovered by coverage-guided fuzzing of the master build (AFL crash id:000028 of the campaign); full sanitizer transcript archived in the verification environment; terminal screenshots of the live reproduction are available on request.
- Distinct from the NULL pointer dereference in sei_message() (src/lib_ccx/avc_functions.c:395): different function, different source location, different defect class.
- No reproduction was attempted on any other version; affected range is therefore not asserted beyond the tested commit.
Lingua principale
C
Stelle
913
Fork
603
Merge medio
1g 10h
PR unite (30g)
24

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di CCExtractor/ccextractor

Tutte le issue di CCExtractor/ccextractor

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.