From d7cdad29c6e47532ac2c5832388399888e07d192 Mon Sep 17 00:00:00 2001 From: Reacher <155128248+0xxreacher@users.noreply.github.com> Date: Thu, 1 Oct 2026 16:54:16 +0530 Subject: [PATCH] refactor(main): avoid per-IP script list clones and safer ulimit fallback (#905) Small cleanups in main.rs: - Iterate over the parsed scripts by reference and clone only the script being run, instead of cloning the whole list for every IP. - Use `or_default()` for the per-IP port map. - If the soft file-descriptor limit does not fit in a `usize` (32-bit targets), fall back to `DEFAULT_FILE_DESCRIPTORS_LIMIT` instead of `usize::MAX`, which bypassed all batch-size adjustments. - Fix a typo. The effective-batch-size warning fix originally proposed here landed via #921. Co-authored-by: Autumn Skerritt --- src/main.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5a3135f..743de46 100644 --- a/src/main.rs +++ b/src/main.rs @@ -112,7 +112,7 @@ fn main() { portscan_bench.end(); benchmarks.push(portscan_bench); - let mut ports_per_ip = HashMap::new(); + let mut ports_per_ip: HashMap> = HashMap::new(); let mut closed_ports_per_ip: HashMap> = HashMap::new(); for status in scan_result { @@ -120,9 +120,7 @@ fn main() { PortStatus::Open(socket) => (&mut ports_per_ip, socket), PortStatus::Closed(socket) => (&mut closed_ports_per_ip, socket), }; - map.entry(socket.ip()) - .or_insert_with(Vec::new) - .push(socket.port()); + map.entry(socket.ip()).or_default().push(socket.port()); } for ip in ips { @@ -157,7 +155,9 @@ fn main() { detail!("Starting Script(s)", opts.greppable, opts.accessible); // Run all the scripts we found and parsed based on the script config file tags field. - for mut script_f in scripts_to_run.clone() { + for script_f in &scripts_to_run { + // Clone only the script being run instead of the whole list per IP. + let mut script_f = script_f.clone(); // This part allows us to add commandline arguments to the Script call_format, appending them to the end of the command. if !opts.command.is_empty() { let user_extra_args = &opts.command.join(" "); @@ -300,7 +300,10 @@ fn adjust_ulimit_size(opts: &Opts) -> usize { } let (soft, _) = Resource::NOFILE.get().unwrap(); - soft.try_into().unwrap_or(usize::MAX) + // On 32-bit targets the soft limit (e.g. RLIM_INFINITY) may not fit in a + // usize. Fall back to the conservative default rather than usize::MAX, + // which would skip every batch-size adjustment in infer_batch_size. + soft.try_into().unwrap_or(DEFAULT_FILE_DESCRIPTORS_LIMIT) } #[cfg(unix)] @@ -317,7 +320,7 @@ fn infer_batch_size(opts: &Opts, ulimit: usize) -> usize { // selected a batch size higher than this we should reduce it to // a lower number. if ulimit < AVERAGE_BATCH_SIZE { - // ulimit is smaller than aveage batch size + // ulimit is smaller than average batch size // user must have very small ulimit // decrease batch size to half of ulimit warning!("Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. ", opts.greppable, opts.accessible);