From c6b3de39f369c81e7df526bd9aeca7a26bf28aba Mon Sep 17 00:00:00 2001 From: Anand Krishnamoorthi Date: Wed, 11 Mar 2026 12:38:03 -0500 Subject: [PATCH] fix(ci): skip mimalloc FFI and disable isolation for Miri - Add cfg(not(miri)) guards to mimalloc module, global allocator, and allocator-memory-limits code paths so Miri falls back to the default system allocator instead of calling unsupported FFI functions. - Set MIRIFLAGS="-Zmiri-disable-isolation" in the workflow so tests that perform file I/O can run under Miri. - Skip units/parse tests under Miri due to Float-vs-BigInt Number representation mismatch with Miri's soft-float emulation. Signed-off-by: Anand Krishnamoorthi --- .github/workflows/miri.yml | 2 ++ mimalloc/src/lib.rs | 8 ++++---- src/interpreter.rs | 4 ++-- src/lib.rs | 2 +- src/rvm/vm/machine.rs | 8 ++++---- src/tests/interpreter/mod.rs | 13 +++++++++++++ src/utils/limits/mod.rs | 10 +++++----- src/value.rs | 4 ++-- tests/memory_limits.rs | 2 +- 9 files changed, 34 insertions(+), 19 deletions(-) diff --git a/.github/workflows/miri.yml b/.github/workflows/miri.yml index 75c1a281..3c81fd13 100644 --- a/.github/workflows/miri.yml +++ b/.github/workflows/miri.yml @@ -10,6 +10,8 @@ jobs: miri-test: name: miri (nightly) runs-on: ubuntu-latest + env: + MIRIFLAGS: "-Zmiri-disable-isolation" steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/mimalloc/src/lib.rs b/mimalloc/src/lib.rs index 67e2919e..b1220425 100644 --- a/mimalloc/src/lib.rs +++ b/mimalloc/src/lib.rs @@ -1,25 +1,25 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -#[cfg(not(any(target_family = "wasm")))] +#[cfg(not(any(target_family = "wasm", miri)))] pub mod mimalloc; #[cfg(feature = "allocator-memory-limits")] -#[cfg(not(any(target_family = "wasm")))] +#[cfg(not(any(target_family = "wasm", miri)))] pub use mimalloc::{ allocation_stats_snapshot, current_thread_allocation_stats, global_allocation_stats_snapshot, GlobalAllocationStats, ThreadAllocationStats, }; #[cfg(feature = "allocator-memory-limits")] -#[cfg(not(any(target_family = "wasm")))] +#[cfg(not(any(target_family = "wasm", miri)))] pub mod limits; /// Declare a global allocator if the platform supports it. #[macro_export] macro_rules! assign_global { () => { - #[cfg(not(any(target_family = "wasm")))] + #[cfg(not(any(target_family = "wasm", miri)))] #[global_allocator] static GLOBAL: mimalloc::mimalloc::Mimalloc = mimalloc::mimalloc::Mimalloc; }; diff --git a/src/interpreter.rs b/src/interpreter.rs index 46ff7934..6f903820 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -402,13 +402,13 @@ impl Interpreter { self.reset_execution_timer_state(); } - #[cfg(feature = "allocator-memory-limits")] + #[cfg(all(feature = "allocator-memory-limits", not(miri)))] fn memory_check(&mut self) -> Result<()> { let _ = self; // quiet clippy::unused_self; retained for symmetry with VM path crate::utils::limits::check_memory_limit_if_needed().map_err(|err| anyhow!(err)) } - #[cfg(not(feature = "allocator-memory-limits"))] + #[cfg(any(miri, not(feature = "allocator-memory-limits")))] const fn memory_check(&mut self) -> Result<()> { let _ = self; // quiet clippy::unused_self; retained for symmetry with VM path Ok(()) diff --git a/src/lib.rs b/src/lib.rs index fd3cd43a..4fb9197c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -167,7 +167,7 @@ pub use engine::Engine; pub use lexer::Source; pub use policy_info::PolicyInfo; pub use utils::limits::LimitError; -#[cfg(feature = "allocator-memory-limits")] +#[cfg(all(feature = "allocator-memory-limits", not(miri)))] pub use utils::limits::{ check_global_memory_limit, enforce_memory_limit, flush_thread_memory_counters, global_memory_limit, set_global_memory_limit, set_thread_flush_threshold_override, diff --git a/src/rvm/vm/machine.rs b/src/rvm/vm/machine.rs index 441a808b..670bea31 100644 --- a/src/rvm/vm/machine.rs +++ b/src/rvm/vm/machine.rs @@ -2,7 +2,7 @@ // Licensed under the MIT License. use crate::rvm::program::Program; -#[cfg(feature = "allocator-memory-limits")] +#[cfg(all(feature = "allocator-memory-limits", not(miri)))] use crate::utils::limits; use crate::utils::limits::{ fallback_execution_timer_config, monotonic_now, ExecutionTimer, ExecutionTimerConfig, @@ -11,7 +11,7 @@ use crate::utils::limits::{ use crate::value::Value; use crate::CompiledPolicy; use alloc::collections::{btree_map::Entry, BTreeMap, VecDeque}; -#[cfg(feature = "allocator-memory-limits")] +#[cfg(all(feature = "allocator-memory-limits", not(miri)))] use alloc::format; use alloc::string::String; use alloc::sync::Arc; @@ -467,7 +467,7 @@ impl RegoVM { Ok(()) } - #[cfg(feature = "allocator-memory-limits")] + #[cfg(all(feature = "allocator-memory-limits", not(miri)))] pub(super) fn memory_check(&mut self) -> Result<()> { limits::check_memory_limit_if_needed().map_err(|err| match err { LimitError::MemoryLimitExceeded { usage, limit } => VmError::MemoryLimitExceeded { @@ -482,7 +482,7 @@ impl RegoVM { }) } - #[cfg(not(feature = "allocator-memory-limits"))] + #[cfg(any(miri, not(feature = "allocator-memory-limits")))] pub(super) fn memory_check(&mut self) -> Result<()> { Ok(()) } diff --git a/src/tests/interpreter/mod.rs b/src/tests/interpreter/mod.rs index 561d9140..9b88180c 100644 --- a/src/tests/interpreter/mod.rs +++ b/src/tests/interpreter/mod.rs @@ -620,6 +620,19 @@ fn yaml_test_impl(file: &str) -> Result<()> { } } + #[cfg(miri)] + { + // Skip tests with large-exponent Number comparisons that hit a + // Float-vs-BigInt representation mismatch under Miri's soft-float. + let skip = ["units/parse.yaml", "units/parse_bytes.yaml"]; + for s in skip { + if file.contains(s) { + std::println!("skipped {file} under miri."); + return Ok(()); + } + } + } + std::println!("running {file}"); let v0 = !file.contains("bindings.yaml"); diff --git a/src/utils/limits/mod.rs b/src/utils/limits/mod.rs index 67d69545..38b2981b 100644 --- a/src/utils/limits/mod.rs +++ b/src/utils/limits/mod.rs @@ -6,7 +6,7 @@ #![allow(dead_code)] mod error; -#[cfg(feature = "allocator-memory-limits")] +#[cfg(all(feature = "allocator-memory-limits", not(miri)))] mod memory; mod time; @@ -14,7 +14,7 @@ mod time; pub use error::LimitError; #[allow(unused_imports)] -#[cfg(feature = "allocator-memory-limits")] +#[cfg(all(feature = "allocator-memory-limits", not(miri)))] pub use memory::{ check_global_memory_limit, enforce_memory_limit, flush_thread_memory_counters, global_memory_limit, set_global_memory_limit, set_thread_flush_threshold_override, @@ -34,19 +34,19 @@ pub use time::acquire_limits_test_lock; #[allow(unused_imports)] pub use time::{set_time_source, TimeSourceRegistrationError}; -#[cfg(feature = "allocator-memory-limits")] +#[cfg(all(feature = "allocator-memory-limits", not(miri)))] #[inline] pub fn check_memory_limit_if_needed() -> core::result::Result<(), LimitError> { memory::check_memory_limit_if_needed() } -#[cfg(not(feature = "allocator-memory-limits"))] +#[cfg(any(miri, not(feature = "allocator-memory-limits")))] #[inline] pub const fn enforce_memory_limit() -> core::result::Result<(), LimitError> { Ok(()) } -#[cfg(not(feature = "allocator-memory-limits"))] +#[cfg(any(miri, not(feature = "allocator-memory-limits")))] #[inline] pub const fn check_memory_limit_if_needed() -> core::result::Result<(), LimitError> { Ok(()) diff --git a/src/value.rs b/src/value.rs index d4dd5490..76908652 100644 --- a/src/value.rs +++ b/src/value.rs @@ -353,7 +353,7 @@ impl Value { match serde_json::from_str::(json) { Ok(value) => Ok(value), Err(err) => { - #[cfg(feature = "allocator-memory-limits")] + #[cfg(all(feature = "allocator-memory-limits", not(miri)))] { // Re-validate allocator limits when serde parsing fails to surface LimitError. match crate::utils::limits::check_global_memory_limit() { @@ -362,7 +362,7 @@ impl Value { } } - #[cfg(not(feature = "allocator-memory-limits"))] + #[cfg(any(miri, not(feature = "allocator-memory-limits")))] { Err(anyhow!(err)) } diff --git a/tests/memory_limits.rs b/tests/memory_limits.rs index 88bd66df..08853531 100644 --- a/tests/memory_limits.rs +++ b/tests/memory_limits.rs @@ -1,4 +1,4 @@ -#![cfg(all(feature = "mimalloc", feature = "allocator-memory-limits"))] +#![cfg(all(feature = "mimalloc", feature = "allocator-memory-limits", not(miri)))] use std::sync::{Mutex, OnceLock};