Prevent panic by Number::modulo - #773
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens Number::modulo to avoid a panic when operands are floats that are mathematically integral but not exactly representable as integers (e.g., magnitude beyond 2^53), ensuring modulo returns an error instead of panicking.
Changes:
- Removes the
ints_to_biginthelper that unconditionallyunwrap()ed bigint conversions and could panic. - Updates
Number::moduloto only proceed when both operands can be safely converted toBigInt, otherwise returningmodulo on floating-point number. - Adds regression coverage via an interpreter YAML case and a Rust unit test for large integral floats.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/number.rs |
Reworks Number::modulo to avoid panic on failed float→bigint conversion; removes the panic-prone helper; adds unit tests. |
tests/interpreter/cases/builtins/numbers/mod.yaml |
Adds a regression test for modulo on an integral-but-too-large float that previously could panic. |
anakrish
left a comment
There was a problem hiding this comment.
Thanks for identifying and fixing this @jaylorch. Once the verus formalization of number is done, I'll want to revisit number.
I don't think the official OPA semantics of numbers is that well defined (e.g large integers) and might not be worth being compatible with if we can devise a simpler semantics that policies could be written to.
|
I had to rebase, which apparently requires another approval. |
In
Number::modulo, it callsNumber::ints_to_bigint, which could panic. The reason is that calling.to_integer()isn't enough to guarantee that.to_bigint_owned()will returnSome, butNumber::ints_to_bigintassumes it will and callsunwrap(). In particular, it might be that it's a float corresponding to an integer that's larger thanF64_SAFE_INTEGER. The fix is to not callNumber::ints_to_bigint(and indeed to delete that entire function, which is only used in this one place), and instead only callunwrapwhenSomeis returned.A concrete example of interpreter input that would cause a panic is
100000000000000000e-1 % 2. This PR prevents that panic.