Skip to content

fix: mask left shifts in numeric fast path - #1096

Open
He-Pin wants to merge 2 commits into
databricks:masterfrom
He-Pin:fix/left-shift-fast-path-mask
Open

fix: mask left shifts in numeric fast path#1096
He-Pin wants to merge 2 commits into
databricks:masterfrom
He-Pin:fix/left-shift-fast-path-mask

Conversation

@He-Pin

@He-Pin He-Pin commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Motivation

Jsonnet specifies shift counts are modulo 64. The numeric fast path (visitBinaryOpAsDouble) checked overflow with the unmasked count while the JVM masked the actual shift, making results path-dependent: (1 << 64) * 1 incorrectly errored instead of returning 1.

Modification

  • Normalize left-shift count with rr % 64 before the overflow check in the numeric fast path.
  • Add regressions for counts 64, 65, 128, zero operand, and nested arithmetic.

Result

Expression before after go-jsonnet jrsonnet
(1 << 64) * 1 error 1 1 1
(1 << 65) * 1 2 2 2 2
(1 << 128) * 1 error 1 1 1
(0 << 128) * 1 error 0 0 0
((1 << 64) + 0) * 1 error 1 1 1

Full matrix (JVM/JS/Wasm/Native) + checkFormat passed.

References

Motivation:
Jsonnet interprets shift counts modulo 64, but the numeric fast path validated
left shifts using the unmasked count. Expressions routed through outer
arithmetic could therefore fail even when the generic evaluator succeeded.

Modification:
Normalize non-negative left-shift counts modulo 64 before both overflow
validation and execution, and add regressions for counts 64, 65, and 128.

Result:
Numeric fast-path behavior now matches the generic evaluator, go-jsonnet,
jrsonnet, and the Jsonnet specification without changing valid count-65
behavior.

References:
- databricks#1096
- https://jsonnet.org/ref/spec.html
@He-Pin
He-Pin force-pushed the fix/left-shift-fast-path-mask branch from 6920423 to 34e2b63 Compare July 29, 2026 08:27
@He-Pin He-Pin changed the title Mask large left shifts in the numeric fast path fix: mask left shifts in numeric fast path Jul 29, 2026
Motivation:
The original tests only covered zero and positive left operands.
The overflow check uses math.abs(ll), so negative values exercise
a distinct code path that should be regression-protected.

Modification:
Add assertions for (-1)<<64, (-2)<<65, (-3)<<128 through the
numeric fast path (via * 1).

Result:
Negative operand behavior is now locked in.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant