[BUG] Heap buffer overflow in parse_PMT with C0/C1 section length
メンテナーはふだん 1 日以内に返信
評価
調査の方向性
src/lib_ccx/ts_tables.c の parse_PMT から始めます。issue では、C0/C1 セクション長の処理と安全でない memmove が指摘されています。PSI バッファの長さがどのように追跡されているかを確認し、添付の pmt_c0.py と issue に記載された AddressSanitizer ビルドコマンドを使って再現します。バッファに格納されたデータより長いセクションを拒否し、報告されたオーバーフローを回避できれば完了です。issue によると、最小限のパッチが用意されています。
索引モデルが issue の本文から書いたものです。
説明
CCExtractor version: 0.96.5 (master d7eb132)
Necessary information
- Is this a regression (i.e. did it work before)? NO The
0xC1path dates to 2016 and the0xC0memmoveto 2020; neither has changed since. - What platform did you use? Linux
- What were the used arguments?
pmt_c0.ts --ts
Video links
Not a video. The reproducer generator is attached: pmt_c0.py.
It writes pmt_c0.ts (376 bytes).
Additional information
parse_PMT() handles the SCTE 57 Program Information and Program Name tables (table_id 0xC0/0xC1) by stripping them from the front of the PSI buffer before parsing the PMT that follows. The 12-bit section length is read directly from the input and used without checking it against the number of bytes actually buffered:
unsigned c0length = (buf[1] << 8 | buf[2]) & 0xFFF;
memmove(buf, buf + c0length + 3, len - c0length - 3);
If c0length + 3 is larger than len, the size expression wraps to a value near 2^32 and memmove() reads and writes far outside the 184-byte PSI buffer. This is not limited to deliberately malformed input: a valid C0/C1 section that spans multiple TS packets also hits it, because the memmove() runs before the code checks whether the whole section has been buffered.
Reproduce
-
Run the attached
pmt_c0.py; it createspmt_c0.ts. -
Build with AddressSanitizer. GPAC is required (
libgpac-devon Debian/Ubuntu):
cmake -S src -B build-asan -G Ninja \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g -O1" \
-DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer -g -O1" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address"
cmake --build build-asan -j"$(nproc)"
- Run:
ASAN_OPTIONS=detect_leaks=0 ./build-asan/ccextractor pmt_c0.ts --ts
The generated file contains a PAT mapping program 1 to PID 0x100, followed by a PMT packet with table_id = 0xC0 and section_length = 0xFFF.
ASan report (addresses and build IDs vary between builds)
=================================================================
==163035==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7c26841e9b43 at pc 0x559fcb8def54 bp 0x7ffff843f7d0 sp 0x7ffff843ef90
READ of size 4294963381 at 0x7c26841e9b43 thread T0
#0 0x559fcb8def53 in __asan_memmove (/tmp/ccextractor-parent/build-asan/ccextractor+0x225f53) (BuildId: e6eef4c3fe76d03bb70bfcaa782da599722b0bb6)
#1 0x559fcbba5ffb in parse_PMT /tmp/ccextractor-parent/src/lib_ccx/ts_tables.c
#2 0x559fcbba2614 in ts_readstream /tmp/ccextractor-parent/src/lib_ccx/ts_functions.c:847:9
#3 0x559fcbba3e74 in ts_get_more_data /tmp/ccextractor-parent/src/lib_ccx/ts_functions.c:1098:9
#4 0x559fcbb71013 in general_loop /tmp/ccextractor-parent/src/lib_ccx/general_loop.c:1443:9
#5 0x559fcb9c8f13 in start_ccx /tmp/ccextractor-parent/src/ccextractor.c:199:11
#6 0x7f269b227780 in __libc_start_call_main (/usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16)
#7 0x7f269b2278b8 in __libc_start_main (/usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:372:3)
#8 0x559fcb82dfc4 in _start (/tmp/ccextractor-parent/build-asan/ccextractor+0x174fc4) (BuildId: e6eef4c3fe76d03bb70bfcaa782da599722b0bb6)
0x7c26841e9b43 is located 3915 bytes after 184-byte region [0x7c26841e8b40,0x7c26841e8bf8)
allocated by thread T0 here:
#0 0x559fcb8e1394 in malloc (/tmp/ccextractor-parent/build-asan/ccextractor+0x228394) (BuildId: e6eef4c3fe76d03bb70bfcaa782da599722b0bb6)
#1 0x559fcbba8814 in ts_buffer_psi_packet /tmp/ccextractor-parent/src/lib_ccx/ts_tables.c:590:46
#2 0x559fcbba257e in ts_readstream /tmp/ccextractor-parent/src/lib_ccx/ts_functions.c:845:4
#3 0x559fcbba3e74 in ts_get_more_data /tmp/ccextractor-parent/src/lib_ccx/ts_functions.c:1098:9
#4 0x559fcbb71013 in general_loop /tmp/ccextractor-parent/src/lib_ccx/general_loop.c:1443:9
#5 0x559fcb9c8f13 in start_ccx /tmp/ccextractor-parent/src/ccextractor.c:199:11
#6 0x7f269b227780 in __libc_start_call_main (/usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:59:16)
#7 0x7f269b2278b8 in __libc_start_main (/usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:372:3)
#8 0x559fcb82dfc4 in _start (/tmp/ccextractor-parent/build-asan/ccextractor+0x174fc4) (BuildId: e6eef4c3fe76d03bb70bfcaa782da599722b0bb6)
SUMMARY: AddressSanitizer: heap-buffer-overflow (/tmp/ccextractor-parent/build-asan/ccextractor+0x225f53) (BuildId: e6eef4c3fe76d03bb70bfcaa782da599722b0bb6) in __asan_memmove
Shadow bytes around the buggy address:
0x7c26841e9880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x7c26841e9b00: fa fa fa fa fa fa fa fa[fa]fa fa fa fa fa fa fa
0x7c26841e9b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c26841e9d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==163035==ABORTING
The section should be rejected when c0length + 3 > len, and len should be reduced by c0length + 3 after the move. I have a minimal patch that does both and can open a PR.
- 主要言語
- C
- スター
- 912
- フォーク
- 598
- 平均マージ
- 2日 17時間
- マージ済み PR(30日)
- 30
環境構築
- 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 が 3 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
CCExtractor/ccextractor#2425 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] Filename sequence expansion (`+`) panics on numeric values exceeding `i32::MAX`対応中かも @muntasir-396 が 9 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
CCExtractor/ccextractor#2402 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] ISDB decoder ignores the payload length: heap-buffer-overflow in parse_statement, plus a one-byte overflow in get_text対応中かも @pranayr710 が今日担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
CCExtractor/ccextractor#2434 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] WTV read_header(): unchecked len and text_len from the file crash the parser (SEGV, 4 KB reproducer)対応中かも @pranayr710 が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 35/100
CCExtractor/ccextractor#2433 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] SIGSEGV in tlt_read_rcwt(): rcwt_loop re-checks parsebuf[6..7] after it was overwritten with caption data (608-mode RCWT)対応中かも @VishnuSrivatsava が 1 日前に担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 72/100
CCExtractor/ccextractor#2429 ·
メンテナーはふだん 1 日以内に返信
CCExtractor/ccextractor の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
メンテナーはふだん 1 日以内に返信
-
update-request
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
msys2/MINGW-packages#33004 ·
メンテナーはふだん 1 日以内に返信
-
area:buffer good first issue type:documentation
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
sudo-project/sudo#586 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
OpenPrinting/cups#1795 ·
メンテナーはふだん 1 日以内に返信