From c269dbdf595e43f00227ecc36a66ec47228a0482 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 20:06:31 +0000 Subject: [PATCH] test(rust): skip the vtab permission tests when the OS ignores mode bits `unreadable_file_yields_null_content_without_erroring_the_row` chmods a fixture 0o000 and asserts `content` comes back NULL. Root bypasses permission bits, so the read succeeds and the assertion fails -- the product is fine, the test's precondition just cannot hold for a privileged process. The hosted sandbox runs as uid 0, so `cargo test --workspace --features cli` was never clean there and `cargo mutants` aborted on the unmutated baseline. Probe the precondition instead of asserting it: `make_unreadable` chmods the file and reports whether a read actually fails, and both permission tests bail out with a note when it does not. Probing beats a `geteuid() == 0` check -- it needs no `unsafe`/libc, and it also covers a non-root process holding CAP_DAC_OVERRIDE. `star_does_not_read_file_bodies` shares the precondition. It passed under root rather than failing, but only vacuously, so it gets the same guard. Fixes #977 --- packages/rust/tests/vtab.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/rust/tests/vtab.rs b/packages/rust/tests/vtab.rs index e329efce8..4ec4e2245 100644 --- a/packages/rust/tests/vtab.rs +++ b/packages/rust/tests/vtab.rs @@ -6,11 +6,21 @@ use std::fs; use std::io::Write; use std::os::unix::fs::PermissionsExt; +use std::path::Path; use dirsql::vtab::load_module; use rusqlite::Connection; use tempfile::TempDir; +/// Strip every permission bit from `path`, reporting whether the OS actually +/// enforces the result. A privileged process -- root, or anything holding +/// `CAP_DAC_OVERRIDE` -- reads the file regardless, so the unreadable +/// precondition cannot hold there and the caller has nothing to assert. +fn make_unreadable(path: &Path) -> bool { + fs::set_permissions(path, fs::Permissions::from_mode(0o000)).unwrap(); + fs::read(path).is_err() +} + /// A connection with the path-table module registered and one vtab named `t` /// spanning `glob` under `dir`. fn open_over(dir: &TempDir, glob: &str) -> Connection { @@ -148,7 +158,10 @@ fn unreadable_file_yields_null_content_without_erroring_the_row() { let dir = TempDir::new().unwrap(); let path = dir.path().join("secret.md"); fs::write(&path, "classified").unwrap(); - fs::set_permissions(&path, fs::Permissions::from_mode(0o000)).unwrap(); + if !make_unreadable(&path) { + eprintln!("skipped: this process bypasses file permission bits"); + return; + } let conn = open_over(&dir, "**/*"); let (name, body): (String, Option) = conn @@ -166,7 +179,10 @@ fn star_does_not_read_file_bodies() { let dir = TempDir::new().unwrap(); let path = dir.path().join("locked.md"); fs::write(&path, "unreadable").unwrap(); - fs::set_permissions(&path, fs::Permissions::from_mode(0o000)).unwrap(); + if !make_unreadable(&path) { + eprintln!("skipped: this process bypasses file permission bits"); + return; + } let conn = open_over(&dir, "**/*"); // If SELECT * read content eagerly this would surface the permission