Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,16 @@ jobs:
# and MSRV is read from rust-version. Anything that needed configuring would be
# a behaviour change smuggled in by an adoption PR, so there is nothing here.
ci:
uses: SecurityRonin/fleet-ci/.github/workflows/rust-ci.yml@a62ab10603151071744cec0b4e3638aa6406d4e4
uses: SecurityRonin/fleet-ci/.github/workflows/rust-ci.yml@e4bee453e6975d5c6ddf3d5120101364ebeaf7d6
with:
# CARRIED ACROSS. The replaced gate excluded main.rs explicitly — its own
# comment reads "main.rs (the Humble CLI shell) is excluded by the script".
# Adoption dropped that, so the strict gate began demanding 100% line
# coverage of a CLI shell this repo has never gated, and main went red on
# 10 lines that were never in scope.
#
# Also worth recording: the old gate enforced 100% LINE *and FUNCTION*
# coverage. The shared workflow has no function-coverage input, so that
# half is dropped. A real reduction, stated here rather than left to be
# found in a coverage report later.
coverage-ignore-regex: '(^|/)src/main\.rs'
14 changes: 7 additions & 7 deletions src/identify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,11 +417,11 @@ fn detect_utf16le(bytes: &[u8]) -> Option<Candidate> {
.map(|c| u16::from_le_bytes([c[0], c[1]]))
.collect();
if units.is_empty() {
// cov:unreachable: the guard above establishes bytes.len() >= 4 and even, and
// `body` is either `bytes` or `bytes[2..]` (BOM), so body.len() >= 2 and
// The guard above establishes bytes.len() >= 4 and even, and `body` is
// either `bytes` or `bytes[2..]` (BOM), so body.len() >= 2 and
// chunks_exact(2) always yields at least one unit. Kept as a defensive
// backstop in case the length guard above is ever relaxed.
return None;
return None; // cov:unreachable: body.len() >= 2, so chunks_exact(2) yields >= 1 unit
}
let text = String::from_utf16(&units).ok()?;
if !mostly_printable(&text) {
Expand Down Expand Up @@ -620,11 +620,11 @@ fn describe_plist(v: &plist::Value) -> String {
plist::Value::Integer(_) => "integer".to_owned(),
plist::Value::String(_) => "string".to_owned(),
plist::Value::Uid(_) => "uid".to_owned(),
// cov:unreachable: `plist::Value` (plist 1.9.0) has exactly the nine variants
// matched above — Array, Dictionary, Boolean, Data, Date, Real, Integer,
// String, Uid. The enum is `#[non_exhaustive]`, so this arm exists only so a
// `plist::Value` (plist 1.9.0) has exactly the nine variants matched
// above — Array, Dictionary, Boolean, Data, Date, Real, Integer, String,
// Uid. The enum is `#[non_exhaustive]`, so this arm exists only so a
// future plist release that adds a variant still compiles here.
_ => "value".to_owned(),
_ => "value".to_owned(), // cov:unreachable: plist 1.9.0 has only the nine variants above
}
}

Expand Down
45 changes: 20 additions & 25 deletions src/v8_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -774,19 +774,14 @@ impl<'a> Reader<'a> {
cap: self.limits.max_nodes,
});
}
// The guard above already rejected len > cap (max_nodes, 4_000_000), so len
// fits usize on every supported target; this map_err is a defense-in-depth
// backstop no input can reach.
// cov:unreachable: len <= cap after the guard makes usize::try_from infallible.
usize::try_from(len).map_err(|_| {
// cov:unreachable: the `len > cap` guard above already returned, so
// len <= cap == max_nodes as u64. Since max_nodes is a usize, any value
// <= it fits usize on every target — this closure body is dead.
V8Error::LengthCap {
offset: self.pos,
len,
cap: self.limits.max_nodes,
}
// The guard above already rejected len > cap (max_nodes, 4_000_000), so
// len <= cap == max_nodes as u64. max_nodes is a usize, so any value <= it
// fits usize on every supported target and this map_err closure is a
// defense-in-depth backstop no input can reach.
usize::try_from(len).map_err(|_| V8Error::LengthCap {
offset: self.pos, // cov:unreachable: len <= cap makes try_from infallible
len, // cov:unreachable: len <= cap makes try_from infallible
cap: self.limits.max_nodes, // cov:unreachable: len <= cap makes try_from infallible
})
}
}
Expand Down Expand Up @@ -825,19 +820,19 @@ fn le_bytes_to_decimal(bytes: &[u8]) -> String {
}
}
// Strip leading zeros (most-significant end), then render most-significant first.
//
// The schoolbook loop above never leaves a zero in the most-significant slot.
// Induction: `decimal` starts `[0]` (len 1). A digit is appended only by
// `while carry > 0`, whose final push is `carry` itself with 0 < carry < 10, so
// a pushed top digit is non-zero. Otherwise the top digit becomes
// `v = d_top * 256 + carry_in` with v < 10, which is 0 only when d_top == 0 and
// carry_in == 0 — and d_top == 0 implies len == 1 by the same induction, which
// this loop's own `len > 1` guard excludes. Verified by exhaustive replay of all
// magnitudes up to 3 bytes (16,843,009 cases) plus 200k random magnitudes up to
// 12 bytes: the loop never fires. Kept as a defensive normalizer so a future
// change to the carry loop cannot emit a leading-zero decimal.
while decimal.len() > 1 && *decimal.last().unwrap_or(&0) == 0 {
// cov:unreachable: the schoolbook loop above never leaves a zero in the
// most-significant slot. Induction: `decimal` starts `[0]` (len 1). A digit is
// appended only by `while carry > 0`, whose final push is `carry` itself with
// 0 < carry < 10, so a pushed top digit is non-zero. Otherwise the top digit
// becomes `v = d_top * 256 + carry_in` with v < 10, which is 0 only when
// d_top == 0 and carry_in == 0 — and d_top == 0 implies len == 1 by the same
// induction, which this loop's own `len > 1` guard excludes. Verified by
// exhaustive replay of all magnitudes up to 3 bytes (16,843,009 cases) plus
// 200k random magnitudes up to 12 bytes: the loop never fires. Kept as a
// defensive normalizer so a future change to the carry loop cannot emit a
// leading-zero decimal.
decimal.pop();
decimal.pop(); // cov:unreachable: the carry loop never leaves a zero on top
}
decimal.iter().rev().map(|d| (b'0' + d) as char).collect()
}
Loading