aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-06-25 06:57:04 +0300
committerValentin Popov <valentin@popov.link>2026-06-25 10:45:39 +0300
commit607a64ca8d48c2265482f2dbd050889d0bc8b1ec (patch)
treebd756ac2069bd5b8df7750e14247de0e34b8a5fe
parente79d26ea68a562c95c13405516547acbbc23cefd (diff)
downloadfparkan-607a64ca8d48c2265482f2dbd050889d0bc8b1ec.tar.xz
fparkan-607a64ca8d48c2265482f2dbd050889d0bc8b1ec.zip
refactor(vulkan-policy): narrow unsafe module boundaries
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi.rs1
-rw-r--r--xtask/src/main.rs53
2 files changed, 52 insertions, 2 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi.rs b/adapters/fparkan-render-vulkan/src/ffi.rs
index 54e9cf3..5977f43 100644
--- a/adapters/fparkan-render-vulkan/src/ffi.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi.rs
@@ -1,4 +1,3 @@
-#![allow(unsafe_code)]
#![cfg_attr(
test,
allow(
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index da8c16f..e1e5970 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -1199,6 +1199,7 @@ fn scan_policy_file(path: &Path, failures: &mut Vec<String>) -> Result<(), Strin
path.display()
));
}
+ validate_unsafe_module_attribute_policy(path, &text, failures);
let mut previous_line_has_safety_comment = false;
for (index, line) in text.lines().enumerate() {
let trimmed = line.trim_start();
@@ -1224,6 +1225,27 @@ fn scan_policy_file(path: &Path, failures: &mut Vec<String>) -> Result<(), Strin
Ok(())
}
+fn validate_unsafe_module_attribute_policy(path: &Path, text: &str, failures: &mut Vec<String>) {
+ let declares_unsafe_module_boundary = text
+ .lines()
+ .map(str::trim_start)
+ .any(|line| line.starts_with("#![allow(unsafe_code)]"));
+ match (
+ is_audited_unsafe_source(path),
+ declares_unsafe_module_boundary,
+ ) {
+ (true, false) => failures.push(format!(
+ "{}: audited Vulkan FFI module must declare #![allow(unsafe_code)]",
+ path.display()
+ )),
+ (false, true) => failures.push(format!(
+ "{}: #![allow(unsafe_code)] is only permitted in audited Vulkan FFI modules",
+ path.display()
+ )),
+ (true, true) | (false, false) => {}
+ }
+}
+
fn contains_unsafe_construct(line: &str) -> bool {
line.contains(concat!("un", "safe {"))
|| line.contains(concat!("un", "safe fn"))
@@ -1240,7 +1262,6 @@ fn has_safety_comment(line: &str) -> bool {
}
const AUDITED_UNSAFE_SOURCE_FILES: &[&str] = &[
- "adapters/fparkan-render-vulkan/src/ffi.rs",
"adapters/fparkan-render-vulkan/src/ffi/instance.rs",
"adapters/fparkan-render-vulkan/src/ffi/capabilities.rs",
"adapters/fparkan-render-vulkan/src/ffi/resources.rs",
@@ -3036,4 +3057,34 @@ source = "git+https://example.invalid/repo"
)));
assert!(!contains_unsafe_construct("#![forbid(unsafe_code)]"));
}
+
+ #[test]
+ fn unsafe_module_attributes_must_match_audited_ffi_allowlist() {
+ let audited = Path::new("adapters/fparkan-render-vulkan/src/ffi/runtime.rs");
+ let non_audited = Path::new("adapters/fparkan-render-vulkan/src/ffi.rs");
+
+ let mut failures = Vec::new();
+ validate_unsafe_module_attribute_policy(audited, "mod x;\n", &mut failures);
+ assert_eq!(
+ failures,
+ vec![format!(
+ "{}: audited Vulkan FFI module must declare #![allow(unsafe_code)]",
+ audited.display()
+ )]
+ );
+
+ failures.clear();
+ validate_unsafe_module_attribute_policy(
+ non_audited,
+ "#![allow(unsafe_code)]\nmod runtime;\n",
+ &mut failures,
+ );
+ assert_eq!(
+ failures,
+ vec![format!(
+ "{}: #![allow(unsafe_code)] is only permitted in audited Vulkan FFI modules",
+ non_audited.display()
+ )]
+ );
+ }
}