leo
leo copied to clipboard
[Bug] overflows allowed
🐛 Bug Report
using a ternary expression in math allows the computation to wrap overflows instead of panicking
Code snippet to reproduce
function main () {
let b = 150u8 + if true? 150u8 : 150u8;
console.log("TEST {}", b);
}
Stack trace & error message
d:\Work\leo_playground>D:\Work\leo-fuzz\leo\target\release\leo.exe run
Compiling Starting...
Compiling Compiling main program... ("d:\\Work\\leo_playground\\src/main.leo")
Compiling TEST 44
Compiling Complete
Done Finished in 3 milliseconds
Setup Detected saved setup
Setup Loading proving key...
Setup Complete
Setup Loading verification key...
Setup Complete
Done Finished in 14 milliseconds
Proving Starting...
Proving TEST 44
Proving Saving proof... ("d:\\Work\\leo_playground\\outputs/leo_playground.proof")
Done Finished in 9 milliseconds
Verifying Starting...
Verifying Proof is valid
Done Finished in 2 milliseconds
Expected Behavior
should cause an overflow error. instead wraps the int
Your Environment
- leo's latest github commit 0bc0ee4b564294b5dee68c61b24966e2c3a666c6
- rustc 1.47.0 (18bf6b4f0 2020-10-07)
- windows 10 build 10.0.19041.630
@collinc97 please edit estimate after you root cause
not fixed by asg (2657c448a0368511a189e30cbe437d8b08df18d9)
- It doesn't matter if there's an
if
. This code also compiles and runs:
let b = 150u8 + 150u8;
console.log("TEST {}", b); // TEST 44
- Works with
u8
type. Can be reproduced withu32
(maybe with other unsigned as well). Also unable to reproduce oni8
ori32
- errors with Overflow. - Resulting value is odd, here are results for different
u8
s:
let b = 100u8 + 100u8; // logs 200
let b = 100u8 + 200u8; // 44
let b = 200u8 + 200u8; // 144
let b = 255u8 + 255u8; // 254
let b = 255u8 + 1u8; // 0
- Similar behavior with
u32
s:
let b = 4294967295u32 + 4294967295u32; // 4294967294
let b = 4294967295u32 + 0u32; // 4294967295
let b = 4294967295u32 + 1u32; // 1
let b = 4294967295u32 + 100u32; // 99
- It is possible to sum more than 2 uints while still not overflowing:
let b : u32 = 4294967295u32 + 100u32 + 100u32 + 100u32 + 100u32; // 399
let b: u8 = 255u8 + 255u8 + 255u8 + 255u8 + 255u8; // 251
Looks like unsigned int value overflows and then resets. Also -1 is applied when max value is passed.
Seems related to #542
let b = 4294967295u32 + 1u32;
now prints 0 instead of 1.
Everything else still results with the same numbers as before.
as @damirka said several months ago it seems like the ternary isnt required to make this occur.
this bug is similar to #542 but i think may have different causes. #542 uses subtraction and only occurs on release builds where overflow checks don't occur, whereas this bug uses addition and also occurs on debug builds when rust overflow checks are present.
this still effects all math types, not just addition.
The issue is in snarkvm_gadets addmany
function definition in the uint_impl
macro implementation for addition. I would assume for other operations that the issue is similar.
This is fixed in ir
branch.
im not sure what changed but this was NOT fixed by IR. still happens as of staging commit 82f83d9
fixed on branch testnet3