[BUG] WTV read_header(): unchecked len and text_len from the file crash the parser (SEGV, 4 KB reproducer)
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 35/100
Línea de trabajo
Read src/lib_ccx/wtv_functions.c, focusing on read_header() and the existing wtv_len_plausible() checks. Reproduce with the supplied 4 KB generator under AddressSanitizer, then check the length bounds and cleanup paths described in the issue. Done means malformed length fields are rejected without out-of-bounds access or leaks; issue #2435 already has an open pull request.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
read_header() in src/lib_ccx/wtv_functions.c reads two length fields straight
out of the .wtv file and uses them without checking either against the 1024-byte
buffer it parses into. A crafted file crashes CCExtractor; ASan reports a SEGV
inside read_header.
The outer element loop in wtv_get_more_data() was hardened at some point with
wtv_len_plausible() / wtv_resync(), but read_header(), which runs first and
walks the root directory, never got the same treatment.
Where
https://github.com/CCExtractor/ccextractor/blob/master/src/lib_ccx/wtv_functions.c
1. len - 32 underflows the size_t that buffered_read() takes
uint16_t len;
memcpy(&len, parsebuf + 16, 2);
...
if (len > 1024) // only an upper bound
{
mprint("Too large for buffer!\n");
free(parsebuf);
return CCX_EOF;
}
result = buffered_read(ctx, parsebuf, len - 32);
len covers the 32-byte record itself, so a file that declares len < 32 makes
len - 32 negative; buffered_read()'s third parameter is size_t, so it
becomes a value near 2^64. wtv_len_plausible() already rejects raw_len < 32
for the same field elsewhere in this file.
2. text_len is unbounded, and malloc(text_len + 1) wraps
uint32_t text_len;
memcpy(&text_len, parsebuf, 4); // character count, from the file
char *string;
string = (char *)malloc(text_len + 1);
...
string[text_len] = '\0';
for (x = 0; x < text_len; x++)
memcpy(&string[x], parsebuf + 8 + (x * 2), 1);
parsebuf is 1024 bytes and holds at most len - 32 bytes of file data, so
text_len must satisfy 8 + 2 * text_len <= len - 32. Nothing checks it:
- a moderate
text_lenwalksparsebuf + 8 + 2 * text_lenpast the allocation; text_len + 1is computed inuint32_t, sotext_len == UINT32_MAXgives
malloc(0)andstring[text_len] = '\0'then writes roughly 4 GB past a
zero-sized allocation.
3. The .entries. branch reads eight more bytes past the string
memcpy(&value, parsebuf + (text_len * 2) + 8, 4);
memcpy(&flag, parsebuf + (text_len * 2) + 4 + 8, 4);
4. Minor: parsebuf leaks on the "Missing WTV header" path
That branch returns CCX_EOF without the free(parsebuf) every other error
path in the function does.
Reproducing
A .wtv is recognised purely from its first four bytes (B7 D8 00 20,
stream_functions.c), so a 4 KB file is enough. Generator:
import struct
HDR = b"\xB7\xD8\x00\x20\x37\x49\xDA\x11\xA6\x4E\x00\x07\xE9\x5E\xAD\x8D"
h = bytearray(0x42); h[0:16] = HDR
struct.pack_into("<I", h, 0x30, 0x4000) # filelen
struct.pack_into("<I", h, 0x38, 1) # root_dir, in 0x1000 chunks
out = bytearray(h) + b"\x00" * (0x1000 - 0x42)
body = struct.pack("<I", 0xFFFFFFFF) + b"\x00" * 4 # text_len
body += b"".join(bytes([c, 0]) for c in b".entries.") # UTF-16LE name
body += b"\x00" * 64
rec = bytearray(32)
rec[0:16] = b"\x11" * 16 # any non-EOF GUID
struct.pack_into("<H", rec, 16, 32 + len(body)) # len
out += bytes(rec) + body
out += b"\x00" * 32 # WTV_EOF record
open("wtv_textmax.wtv", "wb").write(bytes(out))
$ ccextractor wtv_textmax.wtv -o out.srt
==1==ERROR: AddressSanitizer: SEGV on unknown address 0x6021000048af
SUMMARY: AddressSanitizer: SEGV (/ccx+0xf337d5) in read_header
Built from master (d7eb132) with -fsanitize=address,undefined; reproduced on
3 of 3 runs (one of the three ended in ASan's DEADLYSIGNAL loop rather than a
clean report, but it is the same crash).
Suggested fix
Reject len < 32 the way wtv_len_plausible() already does, keep body_len =
len - 32, and require 8 + 2 * text_len <= body_len before the string is
allocated (and eight bytes more in the .entries. branch). Plus the missing
free().
I have a patch and will open a PR referencing this issue.
(Analysis and patch prepared with AI assistance; the reproducer and the
sanitizer runs are my own.)
- Lenguaje dominante
- C
- Estrellas
- 912
- Forks
- 598
- Merge medio
- 2 d 7 h
- PR fusionados (30 d)
- 29
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de CCExtractor/ccextractor
-
Heap OOB read in parse_ad_cdp: cc_count not bounded by packet lengthPosiblemente ocupada @Nikhil-jaiswal007 la tomó hace 5 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
CCExtractor/ccextractor#2425 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
[BUG] Heap buffer overflow in parse_PMT with C0/C1 section lengthPosiblemente ocupada @kun-codes la tomó hace 8 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
CCExtractor/ccextractor#2419 ·
Los mantenedores suelen responder en 1 día
-
[BUG] Filename sequence expansion (`+`) panics on numeric values exceeding `i32::MAX`Posiblemente ocupada @muntasir-396 la tomó hace 11 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
CCExtractor/ccextractor#2402 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 72/100
CCExtractor/ccextractor#2437 ·
Los mantenedores suelen responder en 1 día
-
[BUG] ISDB decoder ignores the payload length: heap-buffer-overflow in parse_statement, plus a one-byte overflow in get_textPosiblemente ocupada @pranayr710 la tomó hace 3 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
CCExtractor/ccextractor#2434 ·
Los mantenedores suelen responder en 1 día
Todos los issues de CCExtractor/ccextractor
Issues similares
-
GPU-UNLOCK RTX 4070 (2786) Gigabyte 1458:416C: cold boot AND warm reboot unlock, Ubuntu 26.04Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
JustAResearcher/gpu-unlock-ada#124 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
-
inflate: total_in uses plain += on c_ulong (32-bit on Windows), panics in debug for streams > 4 GiBAbierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
trifectatechfoundation/zlib-rs#570 · 1 comentario ·
-
vim.filetype.match() prefixes a URL buffer name with the cwd before passing it to filetype functionsAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
Los mantenedores suelen responder en 1 día
-
compilation errorAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
COVESA/dlt-daemon#925 · 1 reacción ·