diff --git a/crates/unsafe-review-core/src/analysis/scanner.rs b/crates/unsafe-review-core/src/analysis/scanner.rs index 21e938801..493162bc1 100644 --- a/crates/unsafe-review-core/src/analysis/scanner.rs +++ b/crates/unsafe-review-core/src/analysis/scanner.rs @@ -737,6 +737,9 @@ fn is_public_api_surface(kind: &UnsafeSiteKind, snippet: &str) -> bool { fn find_owner(lines: &[&str], idx: usize) -> Option { for raw in lines[..=idx].iter().rev().take(80) { let line = raw.trim(); + if is_comment_line(line) { + continue; + } if let Some(name) = parse_impl_owner(line) { return Some(name); } @@ -765,6 +768,9 @@ fn find_owner_declaration_index(lines: &[&str], idx: usize) -> Option { let limit = idx.min(lines.len().saturating_sub(1)); for (line_idx, raw) in lines[..=limit].iter().enumerate().rev().take(120) { let line = raw.trim(); + if is_comment_line(line) { + continue; + } if parse_impl_owner(line).is_some() || parse_trait_name(line).is_some() || parse_fn_name(line).is_some() @@ -775,6 +781,10 @@ fn find_owner_declaration_index(lines: &[&str], idx: usize) -> Option { None } +fn is_comment_line(line: &str) -> bool { + line.starts_with("//") || line.starts_with("/*") || line.starts_with('*') +} + fn owner_doc_start(lines: &[&str], decl_idx: usize) -> usize { let mut start = decl_idx; let mut idx = decl_idx; @@ -918,6 +928,20 @@ mod tests { ); } + #[test] + fn owner_inference_ignores_comment_text_when_scanning_backwards() { + let lines = [ + "fn keep_rest(&mut self) {", + " unsafe {", + " // Normally `Drop` impl would drop [tail].", + " let src = ptr.add(this.idx);", + " }", + "}", + ]; + + assert_eq!(find_owner(&lines, 3), Some("keep_rest".to_string())); + } + #[test] fn text_detection_does_not_classify_deref_assignments_as_writes() { assert_eq!(detect_site("*ptr = value;"), None); diff --git a/docs/handoffs/2026-05-18-real-crate-dogfood-v0.6.md b/docs/handoffs/2026-05-18-real-crate-dogfood-v0.6.md index a2fa00261..e9060c1f1 100644 --- a/docs/handoffs/2026-05-18-real-crate-dogfood-v0.6.md +++ b/docs/handoffs/2026-05-18-real-crate-dogfood-v0.6.md @@ -67,6 +67,17 @@ evidence-quality gap: Regression proof was added with a repo-mode analyzer test for pointer arithmetic inside a documented unsafe function. +A real PR-diff dogfood pass on `servo/rust-smallvec#407` exposed and fixed an +owner-inference gap: + +- owner inference now ignores comment lines while scanning backward +- comment prose such as `` `Drop` impl would drop `` is no longer parsed as an + `impl would` owner +- witness commands now use the real owner when one is available + +Regression proof was added with a scanner unit test for comment text during +owner inference. + ## Dogfood observations The before/after numbers below are top-50 capped repo inventory snapshots, not @@ -208,6 +219,45 @@ The pointer arithmetic card now recognizes the enclosing `# Safety` contract and local guard evidence, then routes the remaining gap to Miri/cargo-careful as a witness need. +### `rust-smallvec#407` + +PR: `https://github.com/servo/rust-smallvec/pull/407` + +The PR fixes a use-after-free in `DrainFilter::keep_rest` for zero-capacity +`SmallVec`s by changing the ZST guard and adding a Miri-targeted regression +test. + +Before comment-aware owner inference: + +```text +elapsed_seconds: 33.48 +changed_rust_files: 2 +cards: 1 +contract_missing: 1 +owner: would +verify: cargo +nightly miri test would +``` + +The owner was inferred from comment prose: + +```text +// Normally `Drop` impl would drop [tail] ... +``` + +After comment-aware owner inference: + +```text +elapsed_seconds: 34.8 +changed_rust_files: 2 +cards: 1 +contract_missing: 1 +owner: keep_rest +verify: cargo +nightly miri test keep_rest +``` + +The card class did not change. The improvement is that the card now points the +reviewer and witness route at the real owner instead of prose. + ## Proof Targeted local validation: @@ -229,6 +279,7 @@ rtk cargo run --locked -p unsafe-review -- repo --root target/dogfood-work/small rtk cargo run --locked -p unsafe-review -- repo --root target/dogfood-work/arrayvec --format json --max-cards 50 --out target/dogfood-work/arrayvec.unsafe-review.after.json rtk cargo run --locked -p unsafe-review -- repo --root target/dogfood-work/memchr --format json --max-cards 50 --out target/dogfood-work/memchr.unsafe-review.after-cap-targetfeature.json rtk cargo run --locked -p unsafe-review -- check --root target/dogfood-work/memchr --diff target/dogfood-work/memchr-pr215.raw.diff --format json --max-cards 20 --out target/dogfood-work/memchr-pr215.owner-contract.json +rtk cargo run --locked -p unsafe-review -- check --root target/dogfood-work/smallvec --diff target/dogfood-work/smallvec-pr407.raw.diff --format json --max-cards 20 --out target/dogfood-work/smallvec-pr407.owner-fix.json ``` The dogfood reruns used a temporary `CARGO_TARGET_DIR` to avoid a Windows file @@ -242,11 +293,13 @@ The repo may claim: - the first real-crate dogfood slice was run on `rust-smallvec` and `arrayvec` - a capped `memchr` dogfood snapshot now completes -- a real PR-diff dogfood run on `memchr#215` produces card output +- real PR-diff dogfood runs on `memchr#215` and `rust-smallvec#407` produce card + output - dogfood found and fixed import/declaration and `cfg(target_feature)` false positives - capped repo scans stop after the requested card cap - operation cards can inherit enclosing unsafe function `# Safety` docs +- owner inference ignores comments while scanning backward - false-positive regression coverage exists in fixtures and calibration - dogfood output remains advisory static review evidence @@ -256,7 +309,7 @@ The repo must not claim: - usable-alpha support-tier promotion - full-repository coverage from top-50 capped snapshots - uncapped repo-scan performance -- general PR-diff usefulness from one PR +- general PR-diff usefulness from two PRs - memory-safety proof - UB-free status - witness execution @@ -266,7 +319,7 @@ The repo must not claim: - Only three real crates completed in this slice. - The successful dogfood snapshots were capped at 50 cards. -- Only one real PR diff was measured. +- Only two real PR diffs were measured. - `memchr` completion depends on capped-scan behavior; uncapped performance is still unmeasured. - No human audit was performed for every emitted card. diff --git a/docs/status/OBJECTIVE_AUDIT.md b/docs/status/OBJECTIVE_AUDIT.md index bf9a2ba98..c83550e67 100644 --- a/docs/status/OBJECTIVE_AUDIT.md +++ b/docs/status/OBJECTIVE_AUDIT.md @@ -35,7 +35,7 @@ witnesses by default. | Explicit receipts can be authored and validated safely | `receipt template` and `receipt validate` are covered by CLI e2e tests and support tiers | Experimental | Template output does not verify that the recorded command ran | | Public claims map to proof | `SUPPORT_TIERS.md` maps every current surface to proof and limits | In place | Keep updating for every new lane | | No soundness, UB-free, Miri-clean, site-execution, or default-blocking claim | Trust-boundary text is enforced across artifacts; support tiers and handoffs repeat limits | In place | Must remain part of all new projections | -| First real-crate dogfood measurement | Handoff `2026-05-18-real-crate-dogfood-v0.6.md` records top-50 capped `rust-smallvec`, `arrayvec`, and `memchr` runs plus a `memchr#215` PR-diff run; dogfood found and fixed import/declaration false positives, `cfg(target_feature)` false positives, capped repo scan timeout behavior, and missing owner-contract inheritance for operation cards | Experimental | More crates, more real PR diffs, uncapped/sampled runs, and human review are still needed before calibration claims | +| First real-crate dogfood measurement | Handoff `2026-05-18-real-crate-dogfood-v0.6.md` records top-50 capped `rust-smallvec`, `arrayvec`, and `memchr` runs plus `memchr#215` and `rust-smallvec#407` PR-diff runs; dogfood found and fixed import/declaration false positives, `cfg(target_feature)` false positives, capped repo scan timeout behavior, missing owner-contract inheritance for operation cards, and comment-derived owner false positives | Experimental | More crates, more real PR diffs, uncapped/sampled runs, and human review are still needed before calibration claims | ## Current Gaps diff --git a/docs/status/SUPPORT_TIERS.md b/docs/status/SUPPORT_TIERS.md index 35361bd4c..d92d93dc1 100644 --- a/docs/status/SUPPORT_TIERS.md +++ b/docs/status/SUPPORT_TIERS.md @@ -12,7 +12,7 @@ All tiers describe static review evidence. None means memory-safety proof. | Raw pointer card slice | experimental | cards | `raw_pointer_alignment`, `raw_pointer_deref`, `raw_pointer_read_unaligned`, `raw_pointer_write_assignment`, `split_raw_pointer_read_call`, `split_unsafe_block`, and safe-reference negative fixtures | source-level review evidence only | | Core operation smoke slice | experimental | cards | `maybeuninit_assume_init`, `vec_set_len`, `transmute_invalid_value`, `get_unchecked_mut_bounds`, and `pin_new_unchecked` fixture goldens | curated fixtures, not broad semantic proof | | Fixture calibration manifest | experimental | `fixtures/calibration.toml` / `cargo xtask check-calibration` | manifest covers positive, negative, and false-positive-control core fixture claims, including import/declaration and `cfg(target_feature)` false-positive controls, and validates expected card counts, classes, operation families, and hazards against goldens | proof index only; not real-world calibration or support-tier promotion evidence by itself | -| Real-crate dogfood measurement | experimental | dogfood handoff | `2026-05-18-real-crate-dogfood-v0.6.md` records top-50 capped `rust-smallvec`, `arrayvec`, and `memchr` repo runs plus a `memchr#215` PR-diff run; it also records the import/declaration, `cfg(target_feature)`, capped-scan, and owner-contract inheritance fixes those runs exposed | three capped snapshots and one PR diff only; no calibrated rates, no full audit, no uncapped performance claim, and no support-tier promotion | +| Real-crate dogfood measurement | experimental | dogfood handoff | `2026-05-18-real-crate-dogfood-v0.6.md` records top-50 capped `rust-smallvec`, `arrayvec`, and `memchr` repo runs plus `memchr#215` and `rust-smallvec#407` PR-diff runs; it also records the import/declaration, `cfg(target_feature)`, capped-scan, owner-contract inheritance, and comment-aware owner inference fixes those runs exposed | three capped snapshots and two PR diffs only; no calibrated rates, no full audit, no uncapped performance claim, and no support-tier promotion | | Contract evidence mining | experimental | cards | public unsafe fn/trait fixtures and private helper `SAFETY:` fixture | comment quality is heuristic | | Guard evidence mining | experimental | cards | raw-pointer alignment and comment-not-guard fixtures prove bounds evidence does not discharge alignment | obligation-specific patterns are still sparse | | Witness routing | experimental | cards | route-table tests plus raw pointer, FFI, unsafe impl Send, Pin, and invalid-value fixture routes | route recommendation only; receipt import is a separate surface and does not execute witnesses |