Skip to content

Conversation

@THE-Amrit-mahto-05
Copy link
Contributor

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

  • I have read and understood the contributors guide.
  • I have checked that another pull request for this purpose does not exist.
  • I have considered, and confirmed that this submission will be valuable to others.
  • I accept that this submission may not be used, and the pull request closed at the will of the maintainer.
  • I give this submission freely, and claim no ownership to its content.
  • I have mentioned this change in the changelog.

My familiarity with the project is as follows (check one):

  • I have never used CCExtractor.
  • I have used CCExtractor just a couple of times.
  • I absolutely love CCExtractor, but have not contributed previously.
  • I am an active contributor to CCExtractor.

Description

fixes multiple panic scenarios in parser.rs caused by malformed or unexpected
command-line arguments.

Issues fixed

  • Prevents buffer overflow when parsing --usercolor
  • Removes unwrap() panics when parsing numeric CLI values
  • Safely handles invalid buffer size arguments
  • Replaces timestamp parsing panics with proper fatal!(MalformedParameter) errors

Impact

  • no longer panics on invalid user input
  • Invalid arguments now produce clear error messages and exit cleanly

Changes made

  • Added bounds checking for fixed-size buffers
  • Replaced unwrap() calls with safe error handling
  • Preserved existing CLI behavior while improving robustness

Verification

  • Manually tested with malformed and invalid CLI arguments
  • Confirmed no Rust panics occur

Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: ✅ Approved

Fixes multiple panic scenarios in the CLI argument parser.

Changes:

  1. --usercolor: Added bounds check to prevent buffer overflow (takes first 7 chars)
  2. atol(): Replaced unwrap() with proper error handling for buffer size parsing
  3. Timestamp options: --startat, --endat, --startcredits*, --endcredits* now handle invalid input gracefully
  4. Service parsing: CEA-708 service numbers handle parse errors

Testing:

$ ./ccextractor --startat "invalid" /dev/null
Error: Malformed parameter: --startat 'invalid' is invalid.

$ ./ccextractor --buffersize "abc" /dev/null  
Error: Malformed parameter: Invalid buffer size number 'ab'.

$ ./ccextractor --buffersize "" /dev/null
Error: Malformed parameter: empty buffer size.

All tests produce clean error messages instead of Rust panics.

Verdict: Ready to merge. Good defensive coding!

@cfsmp3 cfsmp3 self-requested a review January 10, 2026 00:00
Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't think this is very rustic. We don't want unwraps(), but I think it's possible for clap to reject bad args and provide good feedback.

There's no need to fatal() here

@THE-Amrit-mahto-05
Copy link
Contributor Author

Hi @cfsmp3,

Thanks for your feedback,I have updated the code to replace fatal!() with panic!()/expect() for inputs already validated by clap. The idea was to avoid abrupt crashes while keeping clear messages, but now all inputs that clap validates will never reach these panics, so they act as a safeguard rather than normal execution paths

@cfsmp3
Copy link
Contributor

cfsmp3 commented Jan 10, 2026

Hi @cfsmp3,

Thanks for your feedback,I have updated the code to replace fatal!() with panic!()/expect() for inputs already validated by clap. The idea was to avoid abrupt crashes while keeping clear messages, but now all inputs that clap validates will never reach these panics, so they act as a safeguard rather than normal execution paths

What I mean is that you can pass a function to clap to do the validation (and return true or false). Take a look at value_parser.

It's really important that the code quality and the user experience goes up with each PR. fatal, unwrap, expect, none of those are good things are should be prevented.

Also, recommendation: Focus on the CCExtractor logic and what it does. That what matters - focusing on fixing generic bugs without really understand the core of the program is not a good strategy for GSoC, for example.

Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Changes Requested

Thanks for working on this, but the current approach isn't quite right. The issue isn't how we report errors in parser.rs - it's that validation should happen in clap, not after parsing.

The Problem

Replacing fatal!() with panic!() actually makes things worse:

  • fatal!() gives users a clean error message and exits gracefully
  • panic!() dumps a stack trace and crashes with "core dumped"

I tested with invalid inputs:

# Master (with fatal!)
$ ./ccextractor /dev/null --quant 5
Error: Invalid quant value
Issues? Open a ticket here
https://github.com/CCExtractor/ccextractor/issues

# PR (with panic!)
$ ./ccextractor /dev/null --quant 5
thread '<unnamed>' panicked at src/parser.rs:760:17:
Invalid quant value (validated by clap)
fatal runtime error: failed to initiate panic, error 5, aborting
Aborted (core dumped)

Also, the comment "(validated by clap)" isn't accurate - clap doesn't validate these constraints currently.

The Solution: Validate in args.rs using clap

The validation should happen in clap itself. Here's how:

1. Numeric ranges (--quant, --oem, --psm)

Use value_parser with .range():

// In args.rs - current:
#[arg(long, value_name="mode")]
pub quant: Option<u8>,

// Should be:
#[arg(long, value_name="mode", value_parser = clap::value_parser!(u8).range(0..=2))]
pub quant: Option<u8>,

// Same for --oem (0-2) and --psm (0-13):
#[arg(long, value_parser = clap::value_parser!(u8).range(0..=2))]
pub oem: Option<u8>,

#[arg(long, value_parser = clap::value_parser!(u8).range(0..=13))]
pub psm: Option<u8>,

This gives users a clean error from clap:

$ ./ccextractor /dev/null --quant 5
error: invalid value '5' for '--quant <mode>': 5 is not in 0..=2

2. Custom format validation (--defaultcolor, --startat, --buffersize)

Define validation functions and use them with value_parser:

// Color validation (#RRGGBB format)
fn parse_color(s: &str) -> Result<String, String> {
    if s.len() == 7 
        && s.starts_with('#') 
        && s[1..].chars().all(|c| c.is_ascii_hexdigit()) 
    {
        Ok(s.to_string())
    } else {
        Err(format!(
            "invalid color '{}': expected #RRGGBB format (e.g., #FF0000)", 
            s
        ))
    }
}

#[arg(long, value_parser = parse_color)]
pub defaultcolor: Option<String>,
// Time validation (seconds, MM:SS, or HH:MM:SS)
fn parse_time(s: &str) -> Result<String, String> {
    // Reuse the existing stringztoms logic
    if crate::parser::stringztoms(s).is_some() {
        Ok(s.to_string())
    } else {
        Err(format!(
            "invalid time '{}': expected seconds, MM:SS, or HH:MM:SS", 
            s
        ))
    }
}

#[arg(long, value_parser = parse_time)]
pub startat: Option<String>,

#[arg(long, value_parser = parse_time)]
pub endat: Option<String>,

// Same for --startcreditsnotbefore, --startcreditsnotafter, etc.
// Buffer size validation (e.g., "16M", "512K")
fn parse_buffersize(s: &str) -> Result<String, String> {
    if s.is_empty() {
        return Err("buffer size cannot be empty".to_string());
    }
    let suffix = s.chars().last().unwrap().to_ascii_uppercase();
    if !['K', 'M', 'G'].contains(&suffix) && !suffix.is_ascii_digit() {
        return Err(format!(
            "invalid buffer size '{}': expected number with K/M/G suffix (e.g., 16M)", 
            s
        ));
    }
    let num_part = if suffix.is_ascii_digit() { s } else { &s[..s.len()-1] };
    if num_part.parse::<i32>().is_err() {
        return Err(format!("invalid buffer size '{}': not a valid number", s));
    }
    Ok(s.to_string())
}

#[arg(long, value_parser = parse_buffersize)]
pub buffersize: Option<String>,

3. After adding clap validation

Once clap validates these inputs, the checks in parser.rs become truly unreachable. You can either:

  • Remove them entirely (preferred - less code)
  • Replace with unreachable!("validated by clap") if you want to be defensive

Summary

The changes should be in args.rs, not parser.rs. Add proper value_parser constraints so that:

  1. Invalid input is rejected by clap with clean error messages
  2. The code in parser.rs never sees invalid values
  3. No panic!(), no fatal!(), no unwrap() needed

This is the idiomatic Rust/clap approach and gives users the best experience.

@THE-Amrit-mahto-05
Copy link
Contributor Author

@cfsmp3

Thank you! I have updated the code to move CLI validation into clap using value_parser for numeric ranges, colors, times, and buffer sizes.

I also removed panic!()/fatal!() in parser.rs for inputs now validated by clap

I’m still learning ,so I’d appreciate any feedback on improvements

@ccextractor-bot
Copy link
Collaborator

CCExtractor CI platform finished running the test files on linux. Below is a summary of the test results, when compared to test for commit b39f923...:
Report Name Tests Passed
Broken 13/13
CEA-708 14/14
DVB 7/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 80/86
Teletext 21/21
WTV 13/13
XDS 34/34

Your PR breaks these cases:

  • ccextractor --autoprogram --out=ttxt --latin1 --ucla dab1c1bd65...
  • ccextractor --out=srt --latin1 --autoprogram 29e5ffd34b...
  • ccextractor --608 --out=srt c83f765c66...
  • ccextractor --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotbefore 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotafter 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatleast 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatmost 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...

Congratulations: Merging this PR would fix the following tests:

  • ccextractor --autoprogram --out=srt --latin1 --quant 0 85271be4d2..., Last passed: Never
  • ccextractor --out=spupng c83f765c66..., Last passed: Never

It seems that not all tests were passed completely. This is an indication that the output of some files is not as expected (but might be according to you).

Check the result page for more info.

@ccextractor-bot
Copy link
Collaborator

CCExtractor CI platform finished running the test files on windows. Below is a summary of the test results, when compared to test for commit 0228fbc...:
Report Name Tests Passed
Broken 13/13
CEA-708 14/14
DVB 6/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 80/86
Teletext 21/21
WTV 13/13
XDS 34/34

Your PR breaks these cases:

NOTE: The following tests have been failing on the master branch as well as the PR:

  • ccextractor --autoprogram --out=srt --latin1 --quant 0 85271be4d2..., Last passed:

    Test 7773

  • ccextractor --autoprogram --out=ttxt --latin1 --ucla dab1c1bd65..., Last passed:

    Test 7773

  • ccextractor --out=srt --latin1 --autoprogram 29e5ffd34b..., Last passed:

    Test 7773

  • ccextractor --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed:

    Test 7773

  • ccextractor --startcreditsnotbefore 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed:

    Test 7773

  • ccextractor --startcreditsnotafter 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed:

    Test 7773

  • ccextractor --startcreditsforatleast 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed:

    Test 7773

  • ccextractor --startcreditsforatmost 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed:

    Test 7773


It seems that not all tests were passed completely. This is an indication that the output of some files is not as expected (but might be according to you).

Check the result page for more info.

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.

3 participants