leo icon indicating copy to clipboard operation
leo copied to clipboard

[Bug] overflows allowed

Open 0rphon opened this issue 4 years ago • 10 comments

🐛 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

0rphon avatar Nov 16 '20 22:11 0rphon

@collinc97 please edit estimate after you root cause

myoussefmir avatar Nov 24 '20 19:11 myoussefmir

not fixed by asg (2657c448a0368511a189e30cbe437d8b08df18d9)

0rphon avatar Feb 03 '21 02:02 0rphon

More on this bug:

  1. 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
  1. Works with u8 type. Can be reproduced with u32 (maybe with other unsigned as well). Also unable to reproduce on i8 or i32 - errors with Overflow.
  2. Resulting value is odd, here are results for different u8s:
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
  1. Similar behavior with u32s:
let b = 4294967295u32 + 4294967295u32; // 4294967294
let b = 4294967295u32 + 0u32; // 4294967295
let b = 4294967295u32 + 1u32; // 1
let b = 4294967295u32 + 100u32; // 99
  1. 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.

damirka avatar Mar 01 '21 22:03 damirka

Seems related to #542

damirka avatar Mar 02 '21 11:03 damirka

let b = 4294967295u32 + 1u32; now prints 0 instead of 1. Everything else still results with the same numbers as before.

gluax avatar Jun 10 '21 18:06 gluax

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.

0rphon avatar Jun 10 '21 23:06 0rphon

this still effects all math types, not just addition.

0rphon avatar Jun 11 '21 00:06 0rphon

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.

gluax avatar Jun 29 '21 17:06 gluax

This is fixed in ir branch.

Protryon avatar Jun 29 '21 17:06 Protryon

im not sure what changed but this was NOT fixed by IR. still happens as of staging commit 82f83d9

0rphon avatar Feb 15 '22 19:02 0rphon

fixed on branch testnet3

collinc97 avatar Oct 13 '22 21:10 collinc97