cdg: fix typefind error with specific file sizes

Currently, the typefind logic for cdg can cause errors on files
with all conditions below:
- size multiple of NB_WINDOWS * CDG_PACKET_SIZE (8 * 24) = 192
- size less than TYPEFIND_SEARCH_WINDOW (28800)
- extension different than .cdg

With those conditions, the cdg typefind function may be the last one to
execute and cause gsttypefindhelper.c::helper_find_peek to return
GST_FLOW_EOS, and if it's the final call will then be turned to
GST_FLOW_ERROR in typefind.

That is because cdg's typefind will perform a last call to
typefind.peek(len, CDG_PACKET_SIZE) which is outside the range of typefind
(from 0 to len - 1).

Reproducer with file from cdg tests:
```
head -n 28608 BrotherJohn.cdg > BrotherJohn_short.bit
gst-play-1.0 BrotherJohn_short.bit
```

Fix this by correcting the loop bounds in the cdg typefind
logic. Perhaps the typefind helper logic should be rewritten to avoid
such cases too.

Then the example above works and unrelated files aren't affected by this
in typefind anymore.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2056>
This commit is contained in:
Carlos Bentzen 2025-01-30 21:49:41 +01:00 committed by GStreamer Marge Bot
parent ef4fd6059d
commit 7e2a4cf61c

View file

@ -24,8 +24,8 @@ fn cdg_packets_ratio(typefind: &mut TypeFind, start: i64, len: i64) -> i64 {
let mut count = 0;
let total = len / CDG_PACKET_SIZE as i64;
for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) {
match typefind.peek(start + offset, CDG_PACKET_SIZE as u32) {
for offset in (start..len).step_by(CDG_PACKET_SIZE as usize) {
match typefind.peek(offset, CDG_PACKET_SIZE as u32) {
Some(data) => {
if data[0] & CDG_MASK == CDG_COMMAND {
count += 1;
@ -50,6 +50,7 @@ fn compute_probability(typefind: &mut TypeFind) -> TypeFindProbability {
.length()
.unwrap_or(TYPEFIND_SEARCH_WINDOW as u64 * NB_WINDOWS);
let step = len / NB_WINDOWS;
let search_window = cmp::min(len as i64, TYPEFIND_SEARCH_WINDOW);
// Too short file
if step == 0 {
@ -57,7 +58,7 @@ fn compute_probability(typefind: &mut TypeFind) -> TypeFindProbability {
}
for offset in (0..len).step_by(step as usize) {
let proba = match cdg_packets_ratio(typefind, offset as i64, TYPEFIND_SEARCH_WINDOW) {
let proba = match cdg_packets_ratio(typefind, offset as i64, search_window) {
0..=5 => TypeFindProbability::None,
6..=10 => TypeFindProbability::Possible,
_ => TypeFindProbability::Likely,