Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rejected Audit Findings

Issues flagged during code audits (rounds 7-12) that were assessed and deliberately rejected. Documented here to prevent re-flagging in future audits.

Duration u128-to-u64 overflow in JSON output

File: src/json_output.rs (lines 130, 151) Flagged in: rounds 9, 10, 11, 12

Duration::as_millis() returns u128, cast to u64 without bounds checking. Overflows after ~584 million years. No real build will ever hit this. Not fixing.

Pre-1970 mtime cache collision

File: src/object_store/checksums.rs (lines 25-27) Flagged in: rounds 9, 10, 11, 12

Files with mtime before Unix epoch (1970) get unwrap_or_default() mapping to (0, 0). Two such files could share a cached mtime entry. Pre-1970 timestamps don’t occur on real build inputs. The mtime cache is only an optimization — the actual input checksum comparison catches real changes. Not fixing.

Dependency unchanged logic — no-dep products

File: src/executor/execution.rs (line 587) Flagged in: round 9

Agent claimed !deps.is_empty() && deps.iter().all(...) should be deps.is_empty() || deps.iter().all(...). Wrong — products with no dependencies should NOT reuse cached checksums. The optimization is specifically for products whose upstream deps produced identical output, meaning transitive inputs are unchanged. No-dep products have no such guarantee.

Batch handle_success return value ignored

File: src/executor/execution.rs (line 339) Flagged in: round 10

handle_success() return value is not checked in batch processing. This is correct — handle_success already calls record_failure internally when caching fails, properly marking the product as failed. In non-batch, the return value triggers a break from the retry loop, but batch has no retry loop. Stats are correct either way.

record_failure ignores mark_processor_failed in keep-going mode

File: src/executor/handlers.rs (lines 20-39) Flagged in: rounds 11, 12

In keep-going mode, mark_processor_failed parameter is ignored. This is by design — failed_processors is only checked in non-keep-going mode to skip subsequent products from the same processor. In keep-going mode, all products run regardless, so tracking failed processors is unnecessary.

Arc reference leak — failed_processors not unwrapped

File: src/executor/execution.rs (collect_build_stats) Flagged in: round 11

Agent claimed not unwrapping failed_processors Arc prevents other Arc::try_unwrap calls from succeeding. Wrong — each Arc has its own independent reference count. Not unwrapping one has zero effect on others.

Tera output paths lose directory structure

File: src/processors/generators/tera.rs (lines 100-106) Flagged in: round 10

Templates in subdirectories produce output at project root (e.g., tera.templates/sub/README.md.teraREADME.md). This is intentional — the comment on line 105 explicitly says “Output is at project root with the .tera extension stripped.” By design.

Lua stub_path uses suffix as directory name

File: src/processors/lua_processor.rs (line 126) Flagged in: round 10

rsconstruct.stub_path(source, suffix) uses suffix to construct the output directory (out/{suffix}). This is the designed Lua API — plugins control their own output directory naming via the suffix parameter.

Lua clean count masking with saturating_sub

File: src/processors/lua_processor.rs (lines 450-468) Flagged in: rounds 10, 11

Custom Lua clean functions report removal count via existed_before.saturating_sub(exist_after). If the Lua function doesn’t remove files, that’s the plugin’s responsibility. The count accurately reflects what was actually removed. Not a bug.

file_index src_exclude_dirs substring matching

File: src/file_index.rs (lines 76-80) Flagged in: rounds 9, 10

src_exclude_dirs uses path_str.contains(dir) for filtering. The documented convention uses slash-delimited patterns like "/kernel/", which prevents false positives on path substrings. This is the configured behavior.

Object store trim path reconstruction

File: src/object_store/management.rs (lines 86-103) Flagged in: round 9

Reconstructing checksums from filesystem paths (prefix + rest) during cache trim. The path structure is fixed (objects/[2-char]/[rest]), set by store_object(). Unexpected files in the objects directory are silently ignored during trim, which is the correct behavior.

Partial output caching (before the fix)

File: src/object_store/operations.rs (lines 144-147) Flagged in: round 9

Originally flagged as a design choice. User overruled — missing outputs are now an error (anyhow::ensure!). This was accepted and fixed in a later commit, not rejected.

Zspell read-modify-write race

File: src/processors/checkers/zspell.rs (lines 192-229) Flagged in: round 11

Agent claimed file read-modify-write isn’t protected. Wrong — self.words_to_add.lock() on line 193 acquires the mutex, which is held for the entire function (not dropped until return). The lock prevents concurrent threads from interleaving. Cross-process races are not a concern for RSConstruct.

Duplicate dependency edges in resolve_dependencies

File: src/graph.rs (lines 227-230) Flagged in: round 12

Agent claimed duplicate edges cause incorrect topological sort. The scenario requires a product to list the same input file twice, which doesn’t happen — FileIndex.scan() returns unique paths. Even if it did, duplicate edges would increment and decrement in_degree the same number of times, netting out correctly.

Python string injection in load_python_config

File: src/processors/generators/tera.rs (lines 205-208) Flagged in: round 12

Agent claimed newlines in file paths could inject Python code. File paths come from FileIndex (filesystem scan) or Tera templates written by the project author — both are trusted input. Linux file paths from filesystem scans don’t contain newlines.

Batch assert_eq should be error return

File: src/executor/execution.rs (lines 323-325) Flagged in: round 12

Agent suggested replacing assert_eq! with anyhow::bail! for batch result count validation. The assert is deliberate — a processor returning the wrong number of results is a contract violation (programming error), not a recoverable runtime condition. Assertions are appropriate for invariant violations.

Platform portability (Windows, macOS)

Flagged in: rounds 9, 10, 11, 12

Multiple agents flagged std::os::unix usage without #[cfg(unix)] guards, and missing #[cfg(windows)]/#[cfg(target_os = "macos")] blocks. RSConstruct is Linux-only. No platform compatibility code will be added.

DB recovery — file might not exist

File: src/db.rs Flagged in: round 12

Agent re-flagged db.rs recovery, claiming fs::remove_file could fail if the file doesn’t exist. This was already fixed in round 8 — let _ = fs::remove_file() was changed to fs::remove_file()? which properly propagates errors.