- 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 <anakrish@microsoft.com>
Policy evaluation at scale needs to be able to set memory limits
so that a bad policy does not hog memory or to ensure that
policy evaluation itself does not use too much memory which could
cause other components to suffer.
This PR introduces capability to set and enforce global memory limits.
It also lays the groundwork for enabling per evaluation limits in future.
Once a global memory limit is set, Regorus maintains per thread counters
to track memory activity (allocation, deallocation) of a thread.
These counters are periodically flushed to global memory counters.
Per thread counters avoid the contention that updating global counters
on each alloc/free would cause.
Policy evaluation periodically checks these counters and raises errors
if allocated memory has exceeded the configured limit.
Currently memory limit capability is exposed only to FFI and C#.
Also update mimalloc to v2.2.6
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Lints are added (deny) at crate level.
In each offending file, the failing lints are explicitly allowed.
Each file will be fixed in subsequent PRs.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Supply chain: Use the popular num-bigint crate for handling large integers
- Optimization: Handle f64, i64, u64 directly. These will be the most common instances of a number.
OPA number semantics isn't clear.
https://github.com/open-policy-agent/opa/issues/6281
As part of this change, we update the following failing tests:
- A local test that relies on what 15.3/3 evaluates to.
With our current change, we round in a different direction than what OPA does, but consistent
with Rust. We produce 5.1000000000000005 where as the OPA test expects 5.1.
There is no clear definition in Rego of what the right answer is. Moreover, policies should not
rely on exact floating point value comparison. Therefore this deviations is justified.
The test is patched to pass.
- Another local vm test that exercised 1.1 + 2.2
- Another local vm test that exercises 5.5 - 2.2
- An OPA test that expects that a large integer number say 10e308 is printed in exponent notation.
num-bigint does not print using scientific notation and instead prints all the digits.
The benefit of preserving this compatibility is not clear. We skip this test.
- Doc tests that exercised handling floating point numbers with more than 15 (what f64 supports)
digits of precision. There is no usecase for this scenario. The tests are updated to reflect
the behavior.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* feat!: add Rego Virtual Machine (RVM) implementation
This commit introduces a register-based virtual machine for executing Rego
policies with bytecode-style instructions. Unlike the existing tree-walking
interpreter, the RVM compiles policies into instruction sequences that operate
on virtual registers, offering better performance and optimization potential.
Core Components:
Instruction Set Architecture:
- Define instruction types for data operations, control flow, and builtins
- Implement instruction parameter encoding and display formatting
- Add instruction parser with comprehensive test coverage
Virtual Machine Engine:
- Register-based execution model with program counter management
- Loop execution supporting iterators, comprehensions, and quantifiers
- Function call handling with argument evaluation and context management
- Rule evaluation with default value resolution and virtual data support
- Arithmetic and comparison operation implementations
Program Representation:
- Program listing builder with instruction sequencing
- Rule tree construction for organizing policy rules
- Binary and JSON serialization for compiled programs
- Recompilation support for program modification
Testing Infrastructure:
- Extensive YAML test suites covering all VM features
- Rust unit tests for VM execution and instruction parsing
- Test suites for loops, comprehensions, builtins, and control flow
BREAKING CHANGE: Introduces new VM execution path alongside interpreter
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* docs: add detailed RVM architecture references
Introduce architecture.md explaining program artifacts, serialization, and runtime subsystems.
Document the full opcode catalog in instruction-set.md, including operands, parameter tables, and outcomes.
Walk through execution flow, stacks, and operational guidance in vm-runtime.md, tying the runtime to the new architecture docs.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
---------
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Disable default features in dependencies
- Use anyhow::Error::msg to map errors. Note: anyhow will itself be removed later.
- lazy_static/spin_no_std used in no_std environments
- ensure_no_std binary is built to target thumbv7m-none-eabi to ensure that
there are no std dependencies. thumbv7m-none-eabi target has no std support.
- The opa-no-std feature enables only those Regorus features that work with no_std.
- Enable tests with no_std
- Update sizes of regorus binary in README.md
- Ensure that regorus example can be built with only std
- Ensure that regorus example can be built with no_std
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- `std` feature is enabled by default
- By default enable #![no_std] compilation
- Import std create if `std` feature is enabled or if testing
- Use core, alloc types
- Make it clear where std types are being used
- In no std, use BTreeMap in place of HashMap.
HashMap is not available in no std due to lack of a
secure random number generator
Note: The project does not yet compile without std feature being specified.
But it's really close to being able to do so.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
- Replace std with alloc, core in most places in src
Tests, bindings aren't changed.
- Introduce BuiltinsMap type alias inplace of HashMap.
In no_std case, this could be aliases to BTreeMap
- Fix clippy warnings
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
The feature does not interoperate well with other serde_json features like untagged enums.
Fixes#199
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Provide wrappers around serde_json::from_value and serde_yaml::from_value since
they may not be apparent and the user may end up serializing to json/yaml and
rereading as a regorus::Value
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* `arc` feature to make engine usable from multiple threads.
`arc` is turned on by default. When enabled, std::sync::Arc
will be used instead of std::rc::Rc. The former makes regorus
types like Engine, Value, ast nodes etc Send, allowing for
usability from multiple threads.
Arc would add a performance overhead though since the reference
counting will now become atomic.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* Make engine and related types Debug
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
* Input, Data as json. Evaluate bool queries.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
---------
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Number is implemented using rust_decimal::Decimal which uses a 96 bit mantissa.
TODO:
a) Support u64, i64 variants
b) Determine desired semantics for floating-point
c) Determine desired big integer length
d) Explore other big int/big float crates
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This reduces std::mem::size_of::<Value>() to 16 bytes.
String values are also efficiently copied like Objects, arrays, sets etc.
When multiple function rules are evaluated, ensure that constant argument values
match before running the rule. If actual parameter does not match the constant parameter,
then the rule is skipped.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
1. Numeric indices will be converted to strings for refs beginning with `data`
if there is not valid numeric key
2. Error out if input document already contains value for a ref
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Rename compare.rs to comparison.rs to match OPA documentation of builtins.
Also update loop handling to ensure that the current scope is restored after
each iteration of the loop so as to undo side effects of the iteration.
Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>