Skip to content

Panics in solver.rs: unwrap on env-var parse and on timeout when no timeout is set #113

Description

@coord-e

Summary

Two unwrap() calls in src/chc/solver.rs can cause a process panic under reachable conditions.


Bug 1 — load_timeout panics on non-numeric env var (src/chc/solver.rs:39)

fnload_timeout(&mutself,env:&str){ifletOk(timeout) = std::env::var(env){let timeout_secs = timeout.parse().unwrap();// panics if the value is not a valid u64
...}}

Reproduction: set THRUST_SOLVER_TIMEOUT_SECS=abc (or any non-numeric value) and run thrust.

Effect: the process aborts with a called Option::unwrap() on a None value / ParseIntError panic before any analysis runs.

Fix: replace the unwrap() with proper error handling, e.g.:

match timeout.parse(){Ok(secs) => {/* set timeout */}Err(e) => tracing::warn!("ignoring invalid {env} value {timeout:?}: {e}"),}

Bug 2 — wait_child panics with self.timeout.unwrap() when timeout is None (src/chc/solver.rs:61)

let output = match child.wait()? {None => returnErr(CheckSatError::Timeout(self.timeout.unwrap())),// panics if timeout is NoneSome(output) => output,};

self.timeout is None when no timeout is configured (either the default was overridden or THRUST_SOLVER_TIMEOUT_SECS=0 was set). Currently time_limit() is only called when self.timeout is Some, so in practice wait() would not return None in that branch — but that invariant is not enforced by the type system and is one refactor away from silently breaking.

Fix: encode the connection explicitly so the compiler enforces it:

None => {let timeout = self.timeout.expect("process timed out but no timeout was configured");returnErr(CheckSatError::Timeout(timeout));}

or, better, restructure so the Duration is taken directly from the same binding used to call time_limit():

letmut child = child.controlled_with_output().terminate_for_timeout();let timeout_duration = ifletSome(timeout) = self.timeout{
child = child.time_limit(timeout);Some(timeout)}else{None};let output = match child.wait()? {None => {let d = timeout_duration.expect("timed out without a time limit set");returnErr(CheckSatError::Timeout(d));}Some(output) => output,};

Environment

  • Rust (nightly), process-control crate
  • Affects both THRUST_SOLVER_TIMEOUT_SECS and THRUST_PREPROCESSOR_TIMEOUT_SECS paths

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions