Skip to content

[FIX] Widen avc cc_count to uint16_t/u16 to prevent overflow on multi-SEI frames - #2380

Open
muntasir-396 wants to merge 1 commit into
CCExtractor:masterfrom
muntasir-396:fix-avc-cc-count-wrap
Open

muntasir-396 wants to merge 1 commit into
CCExtractor:masterfrom
muntasir-396:fix-avc-cc-count-wrap

Conversation

@muntasir-396

Copy link
Copy Markdown

In raising this pull request, I confirm the following (please check boxes):

Reason for this PR:

  • This PR adds new functionality.
  • This PR fixes a bug that I have personally experienced or that a real user has reported and for which a sample exists.
  • This PR is porting code from C to Rust.

Sanity check:

  • I have read and understood the contributors guide.
  • I have checked that another pull request for this purpose does not exist.
  • If the PR adds new functionality, I've added it to the changelog. If it's just a bug fix, I have NOT added it to the changelog.
  • I am NOT adding new C code unless it's to fix an existing, reproducible bug.

Summary

In commit c1043ca7 (#2359), MAX_CC_COUNT and HDCC_MAX_TRIPLETS_PER_SLOT were increased from 31 to 310 to allow H.264 access units with multiple SEI messages to buffer their caption triplets.

However, avc_ctx->cc_count remained typed as unsigned char in C (avc_functions.h:6) and u8 in Rust (common_types.rs:7). Because an 8-bit unsigned integer caps at 255:

  1. When an access unit accumulates multiple SEIs totaling over 255 triplets (e.g., 240 + 20 = 260 triplets), ctx->cc_count += new_cc_count wraps modulo 256 (260 % 256 = 4), corrupting the buffer index, overwriting the start of the buffer, and silently losing 256 triplets.
  2. In Rust (core.rs:445), ctx.cc_count += new_cc_count as u8 panics in debug builds due to overflow and wraps in release mode.

Changes

  • src/lib_ccx/avc_functions.h: widen cc_count in struct avc_ctx from unsigned char to uint16_t.
  • src/rust/src/avc/common_types.rs: widen cc_count in AvcContextRust from u8 to u16.
  • src/rust/src/avc/core.rs: update copy_ccdata_to_buffer() with safe u16 addition and add unit test test_copy_ccdata_to_buffer_beyond_u8_max().

@muntasir-396
muntasir-396 force-pushed the fix-avc-cc-count-wrap branch from 043a1ba to c347428 Compare October 16, 2026 16:16
…-SEI frames (CCExtractor#2379)

In commit c1043ca (CCExtractor#2359), MAX_CC_COUNT and HDCC_MAX_TRIPLETS_PER_SLOT
were raised from 31 to 310 to allow H.264 access units with multiple SEI
messages to buffer their caption triplets. However, avc_ctx->cc_count
was stored as an unsigned char in C and u8 in Rust. When an access unit
accumulates multiple SEIs crossing 255 triplets, ctx->cc_count wrapped
around in C (causing buffer corruption and lost triplets) and panicked
in debug mode in Rust.

- src/lib_ccx/avc_functions.h: widen avc_ctx.cc_count from unsigned char to uint16_t.
- src/lib_ccx/avc_functions.c: guard ctx->cc_count addition against overflow in copy_ccdata_to_buffer().
- src/rust/src/avc/common_types.rs: widen AvcContextRust.cc_count from u8 to u16.
- src/rust/src/avc/core.rs: update copy_ccdata_to_buffer() with bounded u16 arithmetic and add unit test.
@muntasir-396
muntasir-396 force-pushed the fix-avc-cc-count-wrap branch from c347428 to b5fe1ae Compare October 16, 2026 17:17
@ccextractor-bot

Copy link
Copy Markdown
Collaborator
CCExtractor CI platform finished running the test files on linux. 171/237 tests matched the approved output:
Report Name Tests Passed
Broken 9/13
CEA-708 2/14
DVB 0/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 69/86
Teletext 0/21
WTV 12/13
XDS 32/34

66 tests do not match the approved output. That is the pass/fail verdict. Whether this branch caused it is a separate question, answered below.


Compared with the tip of master — test 9642, commit 97a0d24:

  • 0 pass there and fail here
  • 0 fail there and pass here
  • 0 fail on both, with different output
  • 66 fail on both, byte for byte the same

Compared with the commit this branch was cut from: the same run as the tip of master (test 9642), so the comparison above already covers it.


No test changes behaviour relative to the tip of master: every failure above fails there too, byte for byte. The approved output for those tests is out of date, which is a baseline to review rather than a regression in this branch.

@ccextractor-bot

Copy link
Copy Markdown
Collaborator
CCExtractor CI platform finished running the test files on windows. 171/237 tests matched the approved output:
Report Name Tests Passed
Broken 9/13
CEA-708 2/14
DVB 0/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 69/86
Teletext 0/21
WTV 12/13
XDS 32/34

66 tests do not match the approved output. That is the pass/fail verdict. Whether this branch caused it is a separate question, answered below.


Compared with the tip of master — test 9643, commit 97a0d24:

  • 0 pass there and fail here
  • 0 fail there and pass here
  • 0 fail on both, with different output
  • 66 fail on both, byte for byte the same

Compared with the commit this branch was cut from: the same run as the tip of master (test 9643), so the comparison above already covers it.


No test changes behaviour relative to the tip of master: every failure above fails there too, byte for byte. The approved output for those tests is out of date, which is a baseline to review rather than a regression in this branch.

@muntasir-396

Copy link
Copy Markdown
Author

CI Status Note

Ready for maintainer review whenever convenient!

@muntasir-396

Copy link
Copy Markdown
Author

Fixes #2379

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants