Reject negative dynamic segment sizes in bit syntax matching#2377
Reject negative dynamic segment sizes in bit syntax matching#2377pguyot wants to merge 1 commit into
Conversation
PR Review: Reject negative dynamic segment sizesCommit: The interpreter now rejects negative and over-capacity scaled sizes before changing the match offset. However, the equivalent JIT paths still multiply before establishing that the product is representable or fits in the source binary. A large positive size can therefore reproduce the same wraparound class this commit is intended to close. The typed JIT fast path also assumes that every value described by Findings[P1] Validate JIT scaling before multiplyingLocations: The new JIT check only proves that a register size is non-negative: MSt5 = cond_jump_to_label({SizeReg, '<', 0}, Fail, MMod, MSt4),
MSt6 = MMod:mul(MSt5, SizeReg, Unit)
Concrete triggers include:
This can produce a false successful match or write an invalid match offset. Because the lowering is shared, this affects all JIT backends rather than only x86-64. The fix should mirror Suggested regression coverage: diff --git a/tests/erlang_tests/test_bs.erl b/tests/erlang_tests/test_bs.erl
@@
test_negative_dynamic_size() ->
B = id(<<1>>),
@@
nope = float_unit64(id(-1), id(<<1, 2, 3, 4, 5, 6, 7, 8>>)),
+ % Products that wrap at native width, or truncate through the JIT primitive ABI,
+ % must fail rather than matching an empty segment or corrupting the match offset.
+ nope = skip_unit64(id(1 bsl 26), B),
+ nope = skip_unit64(id(1 bsl 58), B),
+ nope = int_unit64(id(1 bsl 26), B),
+ nope = int_unit64(id(1 bsl 58), B),
nope = bin_unit8(id(-1), B),The [P1] Do not untag boxed values in the typed
|
A dynamic segment size comes from a register and can be negative. It was scaled by the segment unit before being validated, so the scaled value could wrap to a small size that passed the capacity check and matched, or move the match state offset before the start of the binary. The JIT also untagged small integers with a logical shift, which turned any negative integer into a large positive one. Signed-off-by: Paul Guyot <pguyot@kallisys.net>
b2de9a7 to
8538c84
Compare
A dynamic segment size comes from a register and can be negative. It was scaled by the segment unit before being validated, so the scaled value could wrap to a small size that passed the capacity check and matched, or move the match state offset before the start of the binary.
The JIT also untagged small integers with a logical shift, which turned any negative integer into a large positive one.
These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later