[BUG] SIGSEGV in tlt_read_rcwt(): rcwt_loop re-checks parsebuf[6..7] after it was overwritten with caption data (608-mode RCWT)
メンテナーはふだん 1 日以内に返信
評価
調査の方向性
Start in src/lib_ccx/general_loop.c at rcwt_loop() and trace where parsebuf is reused after the RCWT header is validated. Reproduce with the 83-byte sample and ccextractor crash.rcwt, then check the 608-mode branch and teletext-mode behavior. Done when the crash is fixed and both modes retain their expected output; the issue reports local validation but does not name test files.
索引モデルが issue の本文から書いたものです。
説明
CCExtractor version: 0.96.5, git master d7eb132e (built from source on 2026-10-27)
In raising this issue, I confirm the following:
- I have read and understood the contributors guide.
- I have checked that the bug I am reporting can be replicated.
- I have checked that this issue isn't already reported in closed issues and in open issues.
- I have checked the pull requests tab for existing solutions/implementations.
- I have verified this on current master built from source.
Necessary information
- Is this a regression? No — the loop code involved dates back to 2015; I found it by code reading and confirmed it with AddressSanitizer.
- What platform did you use? Mac (macOS arm64, Apple clang; the crashing code is platform-independent C).
- What were the used arguments?
ccextractor crash.rcwt
Video links
- Sample (83 bytes): https://gist.github.com/VishnuSrivatsava/79a2d40af506ebabbfe925de9305fb08 — it is base64-encoded (
ghdoes not accept binary gists); decode withbase64 -d crash.rcwt.b64 > crash.rcwtand verify SHA2566565e25b9b773ee1ad2731eb3b07ed7266d8f7dfbf2e3601084cc6347ab8c701.
Additional information
Summary
rcwt_loop() (src/lib_ccx/general_loop.c) decides whether an RCWT input is a teletext file by testing parsebuf[6] == 0 && parsebuf[7] == 2 (the file-format revision bytes of the 11-byte header) at two places:
- Before the processing loop — correct,
parsebufstill holds the file header. - At the top of every loop iteration (line 1792 on master) — incorrect: in 608 mode
parsebufis reused for the 10-byte data header and thenrealloc'd and overwritten with the raw caption-block bytes.
If the caption byte stream contains 00 02 at offsets 6–7, iteration 2 takes the teletext branch even though the file is a 608-mode RCWT. In that mode dec_ctx->private_data is NULL (telxcc_init() only runs in teletext mode), so the branch calls tlt_read_rcwt(NULL, buf, dec_sub), which does memcpy(&(ctx->last_timestamp), &buf[1], sizeof(uint64_t)) (src/lib_ccx/telxcc.c:1327) → SIGSEGV.
00 02 at those offsets does not require a hand-crafted file: in RCWT caption blocks the bytes at positions 6–7 are raw CC data (e.g. a 00 marker byte followed by 02), which ordinary corruption or real caption content can produce.
Reproduction
$ base64 -d crash.rcwt.b64 > crash.rcwt
$ ccextractor crash.rcwt
Plain build on master d7eb132e: exit code 139 (SIGSEGV).
With an AddressSanitizer build:
==...==ERROR: AddressSanitizer: SEGV on unknown address 0x000000007700 (pc ... WRITE of size 8)
#0 tlt_read_rcwt telxcc.c:1327
#1 rcwt_loop general_loop.c:1801
#2 start_ccx ccextractor.c:217
The PoC is a minimal 608-mode RCWT file: valid 11-byte header (CC CC ED, revision 00 01), a data header with cbcount = 3, caption blocks 04 80 80 04 80 80 00 02 80 (bytes 6–7 = 00 02), plus 53 bytes so the hijacked teletext branch actually runs the NULL-context memcpy.
Proposed fix
Decide the mode once, right after the header is validated:
is_teletext = (parsebuf[6] == 0 && parsebuf[7] == 2);
and test is_teletext (not parsebuf[6..7]) inside the loop. I have this implemented and validated locally (PoC exits cleanly; a teletext-mode RCWT produces byte-identical output before/after; a 12-sample TS corpus shows no behavior change). Happy to open a PR with the patch if you agree with the approach.
- 主要言語
- C
- スター
- 912
- フォーク
- 598
- 平均マージ
- 2日 7時間
- マージ済み PR(30日)
- 29
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
CCExtractor/ccextractor のほかの issue
-
Heap OOB read in parse_ad_cdp: cc_count not bounded by packet length対応中かも @Nikhil-jaiswal007 が 5 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
CCExtractor/ccextractor#2425 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] Heap buffer overflow in parse_PMT with C0/C1 section length対応中かも @kun-codes が 8 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
CCExtractor/ccextractor#2419 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] Filename sequence expansion (`+`) panics on numeric values exceeding `i32::MAX`対応中かも @muntasir-396 が 11 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
CCExtractor/ccextractor#2402 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 72/100
CCExtractor/ccextractor#2437 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] ISDB decoder ignores the payload length: heap-buffer-overflow in parse_statement, plus a one-byte overflow in get_text対応中かも @pranayr710 が 3 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
CCExtractor/ccextractor#2434 ·
メンテナーはふだん 1 日以内に返信
CCExtractor/ccextractor の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
メンテナーはふだん 1 日以内に返信
-
area:docs area:stdlib found-by:duet-audit kind:docs-drift
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
InauguralSystems/EigenScript#2251 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
flux-framework/flux-coral2#513 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
ly05010419/MacNativeGames#1420 ·
メンテナーはふだん 1 日以内に返信
-
Isaac workingオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
seedds/nxnative#763 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信