[BUG] WTV read_header(): unchecked len and text_len from the file crash the parser (SEGV, 4 KB reproducer)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 35/100
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.)
- Ngôn ngữ chính
- C
- Star
- 912
- Fork
- 598
- Merge trung bình
- 2 ngày 17 giờ
- Pull request đã merge (30 ngày)
- 30
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của CCExtractor/ccextractor
-
Heap OOB read in parse_ad_cdp: cc_count not bounded by packet lengthCó thể đã có người làm @Nikhil-jaiswal007 đã nhận 4 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
CCExtractor/ccextractor#2425 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[BUG] Heap buffer overflow in parse_PMT with C0/C1 section lengthCó thể đã có người làm @kun-codes đã nhận 7 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
CCExtractor/ccextractor#2419 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[BUG] Filename sequence expansion (`+`) panics on numeric values exceeding `i32::MAX`Có thể đã có người làm @muntasir-396 đã nhận 10 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
CCExtractor/ccextractor#2402 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[BUG] ISDB decoder ignores the payload length: heap-buffer-overflow in parse_statement, plus a one-byte overflow in get_textCó thể đã có người làm @pranayr710 đã nhận 2 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 55/100
CCExtractor/ccextractor#2434 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[BUG] SIGSEGV in tlt_read_rcwt(): rcwt_loop re-checks parsebuf[6..7] after it was overwritten with caption data (608-mode RCWT)Có thể đã có người làm @VishnuSrivatsava đã nhận 2 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
CCExtractor/ccextractor#2429 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của CCExtractor/ccextractor
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 70/100
ly05010419/MacNativeGames#1340 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Maintainer thường phản hồi trong vòng 1 ngày
-
area:stdlib bug found-by:cold-read kind:bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
InauguralSystems/EigenScript#2197 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Hide the cursorĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 63/100
seedds/nxnative#675 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 2 ngày