You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Feat/12394 v3 Prepare for release 1.1.0-dev (init command, CPU ranges, Suricata spec) - #33
The init command handles failures with panic!("{e}"). When a user runs suriconf init without --force and the file already exists (a very common scenario), they get a full panic message and backtrace with exit code 101 instead of a clean error on stderr and a conventional non-zero exit code. The error string from config_gen::init (including the helpful use --force hint) is better reported via eprintln! and process::exit(1).
find_max_cpu_usage_vec errors are converted to panic! at the call site. Combined with the new CPU validation against num_cpus::get(), any previously working configuration that lists a CPU index >= the visible CPU count (e.g., when running under taskset, in a container, or on a smaller machine than where the config was authored) now aborts the program with a panic instead of being handled gracefully. Consider returning a Result up to main for a clean error message.
self.max_cpu_usage_vec = match result {Ok(cpus) => cpus,Err(msg) => panic!("Unable to parse max cpu usage vector: {msg}"),};
Replace panic with graceful error exit for init command
Using panic! for a user-facing CLI error (e.g., the file already exists without --force) prints an ugly panic message and backtrace, and exits with code 101 instead of a standard error code. Print the error to stderr and exit with status 1 instead.
if let Some(Commands::Init { output, force }) = &args.cmd {
if let Err(e) = init(output, *force) {
- panic!("{e}");+ eprintln!("Error: {e}");+ process::exit(1);
}
process::exit(0);
}
Suggestion importance[1-10]: 6
__
Why: Using panic! for an expected user-facing CLI error (e.g., file exists without --force) produces an ugly backtrace and exit code 101; printing to stderr and exiting with code 1 is the correct CLI behavior. Correct and useful, but a minor UX improvement rather than a critical bug.
Low
Deduplicate CPU list parsing logic via shared helper
The deduplication and expansion loop here duplicates the logic in parse_cpu_list. Extract a shared helper that inserts a single CPU specification (deduplicating via the seen set) and reuse it from both functions, so future fixes apply in one place only.
+ fn insert_cpu(s: &str, seen: &mut HashSet<u64>, cpus: &mut Vec<u64>) -> Result<(), String> {+ for cpu in expand_cpu_range(s)? {+ if seen.insert(cpu) {+ cpus.push(cpu);+ }+ }+ Ok(())+ }++ fn parse_cpu_list(items: &[String]) -> Result<Vec<u64>, String> {+ let mut cpus = Vec::new();+ let mut seen = HashSet::new();+ for item in items {+ insert_cpu(item, &mut seen, &mut cpus)?;+ }+ Ok(cpus)+ }++ // in find_max_cpu_usage_vec:
for item in seq {
let s = match item {
Value::Number(n) => n.to_string(),
Value::String(s) => s.clone(),
- u => return Err(format!("Invalid CPU {:?}.", u))-+ u => return Err(format!("Invalid CPU {:?}.", u)),
};
-- for cpu in expand_cpu_range(&s)? {- if seen.insert(cpu) { - cpus.push(cpu);- }- }-+ insert_cpu(&s, &mut seen, &mut cpus)?;
}
Ok(cpus)
Suggestion importance[1-10]: 4
__
Why: The deduplication/expansion loop is indeed duplicated between find_max_cpu_usage_vec and parse_cpu_list, and the shared insert_cpu helper would improve maintainability. This is a purely stylistic refactor with no functional or correctness impact.
Low
Validate malformed CPU range inputs before parsing
Inputs such as -2 or 0--3 are split by the first hyphen, producing an empty start segment and a confusing error like Invalid CPU .. Validate the input shape (e.g., reject empty parts or a leading hyphen) before splitting so error messages are meaningful.
- Some((start, end)) => {- let start: u64 = start.trim().parse().map_err(|_| format!("Invalid CPU {}.", start))?;+ let s = s.trim();+ if s.is_empty() || s.starts_with('-') || s.contains("--") || s.ends_with('-') {+ return Err(format!("Invalid CPU specification '{}'.", s));+ }+ match s.split_once('-') {
Suggestion importance[1-10]: 4
__
Why: Malformed inputs like -2 do split into an empty start segment producing the confusing message Invalid CPU ., so the observation is accurate. The fix only improves error message quality for invalid user input, a minor robustness enhancement.
Low
Security
Prevent race condition when refusing to overwrite file
Checking output.exists() and then writing has a TOCTOU race: the file could be created between the check and fs::write, silently overwriting it. Use OpenOptions with create_new(true) to make the no-overwrite guarantee atomic, and map the AlreadyExists error to the friendly message.
pub fn init(output: &PathBuf, force: bool) -> io::Result<()> {
- if output.exists() && !force {- return Err(io::Error::new(- io::ErrorKind::AlreadyExists,- format!("refusing to overwrite {:?} (use --force)", output),- ));- }- fs::write(output, DEFAULT_CONFIG)?;+ use std::fs::OpenOptions;+ use std::io::Write;++ let mut file = if force {+ OpenOptions::new()+ .write(true)+ .create(true)+ .truncate(true)+ .open(output)?+ } else {+ OpenOptions::new()+ .write(true)+ .create_new(true)+ .open(output)+ .map_err(|e| {+ if e.kind() == io::ErrorKind::AlreadyExists {+ io::Error::new(+ io::ErrorKind::AlreadyExists,+ format!("refusing to overwrite {:?} (use --force)", output),+ )+ } else {+ e+ }+ })?+ };++ file.write_all(DEFAULT_CONFIG)?;
Ok(())
}
Suggestion importance[1-10]: 6
__
Why: The TOCTOU race between output.exists() and fs::write is real, and using OpenOptions::create_new with error mapping makes the no-overwrite guarantee atomic. The fix is accurate, though the practical impact in a single-user CLI tool is moderate.
Low
Author self-review: I have reviewed the PR code suggestions, and addressed the relevant ones.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Type
Enhancement, Documentation
Description
Add
initcommand generating default config fileSupport CPU ranges in
max_cpu_usage_vecparsingBump version to 1.1.0-dev with docs updates
Specify required Suricata branch and commit
Diagram Walkthrough
File Walkthrough
5 files
Add CPU range expansion with validation and deduplicationAdd Init command and change CPU vec to stringsHandle Init command before main workflowNew module generating default configuration fileRegister config_gen module and embed default config1 files
Simplify delete_pid_file return type via io import1 files
Update version, Suricata spec, and init usage docs1 files
Bump version and update default configuration values1 files
Bump version to 1.1.0-dev, add num_cpus dependency4 files