[BUG] MXF: update_tid_lut() writes past tracks[32] onto nb_tracks, turning a file-supplied track id into the write offset
I maintainer di solito rispondono entro 7 giorni
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 65/100
Direzione di ricerca
Inizia in src/lib_ccx/ccx_demuxer_mxf.c, in corrispondenza di update_tid_lut(), e verifica come viene gestito un array tracks pieno prima di indicizzarlo. Leggi i chiamanti e i cicli sul numero di track per confermare il comportamento al limite, poi crea e prova un file MXF che dichiari più di 32 track. Il lavoro è concluso quando le track in eccesso vengono ignorate in modo sicuro e il conteggio delle track e i campi adiacenti rimangono intatti.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
update_tid_lut() in src/lib_ccx/ccx_demuxer_mxf.c appends to a fixed
MXFTrack tracks[32] without checking nb_tracks first. nb_tracks is the
struct field directly behind that array, so the 33rd track a file declares
overwrites the bound itself with a 32-bit value taken from the file — and the
very next statement re-reads that bound to choose where to write.
The overlap is exact
typedef struct MXFContext
{
enum MXFCaptionType type; /* byte 0 */
int cap_track_id; /* byte 4 */
UID cap_essence_key; /* byte 8 */
MXFTrack tracks[32]; /* byte 24 .. 279 */
int nb_tracks; /* byte 280 */
int cap_count; /* byte 284 */
struct ccx_rational edit_rate; /* byte 288 */
} MXFContext; /* 296 bytes, heap allocated in ccx_mxf_init() */
sizeof(MXFTrack) is 8, so tracks[32] begins at 24 + 32*8 = 280 — the
same address as nb_tracks.
What happens on the 33rd track
ctx->tracks[ctx->nb_tracks].track_id = track_id;
memcpy(ctx->tracks[ctx->nb_tracks].track_number, track_number, 4);
ctx->edit_rate = edit_rate;
ctx->nb_tracks++;
- statement 1 writes
track_idat byte 280, i.e. intonb_tracks; - statement 2 re-evaluates
ctx->tracks[ctx->nb_tracks]using the value just
written, so its destination is24 + 8*track_id + 4.
track_id is read straight from the file in mxf_read_timeline_track_metadata():
case MXF_TAG_TRACK_ID:
track_id = buffered_get_be32(demux);
With track_id = 0x7FFFFFF0 the memcpy targets byte 17179869084 of a 296
byte allocation — about 16 GB past it. Smaller ids give smaller, more usable
offsets; the write is at 8 * track_id bytes from the block, with four bytes of
file-supplied content.
Everything afterwards is affected too: every for (i = 0; i < ctx->nb_tracks;
i++) over tracks[] (here and in update_cap_essence_key()) becomes an
unbounded read, and cap_count at byte 284 is overwritten by track_number.
Reachability
ccx_probe_mxf() scans the first bytes for the 14-byte header partition pack
key and nothing else, so any file carrying that key is handed to this demuxer.
Each Timeline Track set in the header metadata calls update_tid_lut() once —
33 of them is enough. The C path is live; the Rust side only re-exports
ccx_probe_mxf / ccx_mxf_init ("shall be removed after mxf" in
src/rust/build.rs).
Demonstrating the mechanism
To be clear about what this evidence is and is not: the run below is a
standalone program that reproduces MXFContext and update_tid_lut()
verbatim, with no other CCExtractor code. It demonstrates the pointer
arithmetic and the crash; it is not CCExtractor itself crashing. My sanitizer
build is unavailable at the moment, so I have not yet put the crafted .mxf
files through the real binary end to end — I will add that as a comment rather
than claim it now. The struct offsets below are computed from the real
declaration, and the reachability argument is from the source.
Reproducing the exact struct and function (no other CCExtractor code):
MASTER build
after 32 tracks: nb_tracks = 32
adding 33rd track, track_id = 0x7FFFFFF0 ...
Segmentation fault
FIXED build
after 32 tracks: nb_tracks = 32
adding 33rd track, track_id = 0x7FFFFFF0 ...
[guard] table full at 32, ignoring track 0x7FFFFFF0
survived: nb_tracks = 32, cap_count = 0x00000000
and the intermediate state, printed between the two statements:
nb_tracks before = 32
nb_tracks after stmt 1 = 0x7FFFFFF0 <-- clobbered by the file's track_id
statement 2 will memcpy to tracks[2147483632].track_number = byte 17179869084 of a 296 byte block
Suggested fix
Refuse to append once the table is full:
if (ctx->nb_tracks >= (int)(sizeof(ctx->tracks) / sizeof(ctx->tracks[0])))
{
mprint("MXF: more than %d tracks, ignoring the rest\n", ...);
return;
}
I have a patch and a generator for the test files, and will open a PR
referencing this issue.
(Analysis and patch prepared with AI assistance; the reproducers are my own.)
- Lingua principale
- C
- Stelle
- 913
- Fork
- 603
- Merge medio
- 6g 8h
- PR unite (30g)
- 33
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di CCExtractor/ccextractor
-
[Security] Heap buffer overflow (OOB read past GPAC sample buffer) in process_avc_sample() at mp4.c:99 when parsing a crafted MP4 fileForse già presa @yasar710 l’ha presa 6 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
CCExtractor/ccextractor#2449 ·
I maintainer di solito rispondono entro 7 giorni
-
[BUG] DVB subtitle decoder: heap-buffer-overflow write in dvbsub_parse_clut_segment via unbounded entry_idForse già presa @Aditya-Saroha l’ha presa 9 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
CCExtractor/ccextractor#2440 ·
I maintainer di solito rispondono entro 7 giorni
-
[BUG] Filename sequence expansion (`+`) panics on numeric values exceeding `i32::MAX`Forse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
CCExtractor/ccextractor#2402 ·
I maintainer di solito rispondono entro 7 giorni
-
[BUG] CEA-708 .srt is written as Latin-1 and ignores --utf8/--latin1/--unicodeForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 65/100
CCExtractor/ccextractor#2450 · 3 commenti ·
I maintainer di solito rispondono entro 7 giorni
-
[Security] NULL pointer dereference (SEGV at address 0x0) in sei_message() when parsing a crafted MP4 fileForse già presa @yasar710 l’ha presa 8 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 50/100
CCExtractor/ccextractor#2444 ·
I maintainer di solito rispondono entro 7 giorni
Tutte le issue di CCExtractor/ccextractor
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
tursodatabase/libsql#2312 ·
I maintainer di solito rispondono entro 11 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
follow-up Prio 📌
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
-
area: test kind: bug preview-effort: small priority: low
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
I maintainer di solito rispondono entro 1 giorno