Fix integer overflow in ccxr_process_cc_data(): cast cc_count to usize before multiply (#2241)

cc_count * 3 used i32 arithmetic with no upper-bound check. For cc_count
> i32::MAX / 3 (~715 million), debug builds panic on overflow detection
and release builds silently wrap around to a negative range, discarding
all CC data for the frame. Both are triggerable from malformed media files.

Fix:
1. Cast cc_count to usize immediately after the existing <= 0 guard,
   before any arithmetic — eliminates the overflow entirely
2. Add MAX_CC_COUNT = 31 upper-bound guard — CEA-708/ATSC A/53 encodes
   cc_count in a 5-bit bitstream field (0x1F mask in avc_functions.c:514),
   making 31 the spec-defined per-frame maximum; this value is also
   independently documented in es/userdata.rs ("Maximum cc_count is 31").
   Returns -1 with a warn!() log for out-of-range values, consistent with
   existing error-handling style in the function.
3. Remove the now-redundant `x as usize` cast in the map closure since
   the range is already usize..usize

Fixes #2234
This commit is contained in:
Abhijeet Kumar
2026-04-04 08:34:24 +05:30
committed by GitHub
parent 92dc785435
commit 65df24e6bc

View File

@@ -403,6 +403,19 @@ extern "C" fn ccxr_process_cc_data(
return -1;
}
// Cast to usize before any arithmetic to prevent i32 overflow.
// CEA-708/ATSC A/53 encodes cc_count in a 5-bit field (max 31); 31 is
// also the value used in es/userdata.rs. Reject anything beyond that.
const MAX_CC_COUNT: usize = 31;
let cc_count_usize = cc_count as usize;
if cc_count_usize > MAX_CC_COUNT {
warn!(
"ccxr_process_cc_data: cc_count {} exceeds maximum {}, discarding frame",
cc_count_usize, MAX_CC_COUNT
);
return -1;
}
let dec_ctx = unsafe { &mut *dec_ctx };
// Check dtvcc_rust pointer before dereferencing (not dtvcc!)
@@ -412,8 +425,8 @@ extern "C" fn ccxr_process_cc_data(
}
let mut ret = -1;
let mut cc_data: Vec<u8> = (0..cc_count * 3)
.map(|x| unsafe { *data.add(x as usize) })
let mut cc_data: Vec<u8> = (0..cc_count_usize * 3)
.map(|x| unsafe { *data.add(x) })
.collect();
// Use the persistent DtvccRust context from dtvcc_rust