RyuJIT can incorrectly eliminate an array bounds check when value numbering reasons about an array length using a different array reference identity than the one ultimately used for the array access.
This can occur when array-typed references flow through shared fields or other heap-visible locations and the optimizer associates an ARR_LENGTH value with a liberal value number that is later reused for bounds-check removal. In some cases, the proof used to remove the bounds check is no longer tied to the same array instance as the actual access.
As a result, JIT-generated code may perform an array access that would normally throw IndexOutOfRangeException, leading instead to incorrect behavior and potentially an out-of-bounds write.
Expected Behavior
Bounds checks should only be removed when the proof is tied to the same array reference identity as the array access being optimized.
Actual Behavior
The optimizer may use array-length information derived from one array reference to eliminate a bounds check on another array reference.
Suspected Root Cause
Value numbering currently allows ARR_LENGTH to be computed using a liberal value number even when the underlying array reference has distinct liberal and conservative value numbers.
Array-length reasoning should remain tied to the conservative array identity when the identities diverge; otherwise later CSE and bounds-check elimination can incorrectly treat different array references as equivalent.
Possible Fix Direction
When computing the value number for ARR_LENGTH, if the underlying array reference has different liberal and conservative VNs, use the conservative VN for both identities before deriving the array-length value number. This keeps array-length reasoning tied to the same array identity that is safe for CSE and bounds-check elimination.
Area
- src/coreclr/jit/valuenum.cpp
- Potentially related optimization paths in src/coreclr/jit/optcse.cpp
RyuJIT can incorrectly eliminate an array bounds check when value numbering reasons about an array length using a different array reference identity than the one ultimately used for the array access.
This can occur when array-typed references flow through shared fields or other heap-visible locations and the optimizer associates an ARR_LENGTH value with a liberal value number that is later reused for bounds-check removal. In some cases, the proof used to remove the bounds check is no longer tied to the same array instance as the actual access.
As a result, JIT-generated code may perform an array access that would normally throw IndexOutOfRangeException, leading instead to incorrect behavior and potentially an out-of-bounds write.
Expected Behavior
Bounds checks should only be removed when the proof is tied to the same array reference identity as the array access being optimized.
Actual Behavior
The optimizer may use array-length information derived from one array reference to eliminate a bounds check on another array reference.
Suspected Root Cause
Value numbering currently allows ARR_LENGTH to be computed using a liberal value number even when the underlying array reference has distinct liberal and conservative value numbers.
Array-length reasoning should remain tied to the conservative array identity when the identities diverge; otherwise later CSE and bounds-check elimination can incorrectly treat different array references as equivalent.
Possible Fix Direction
When computing the value number for ARR_LENGTH, if the underlying array reference has different liberal and conservative VNs, use the conservative VN for both identities before deriving the array-length value number. This keeps array-length reasoning tied to the same array identity that is safe for CSE and bounds-check elimination.
Area