Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctly check for overflow in add, mul and pow #6452

Merged
merged 65 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
eba72bc
add flag check in sway-core
SwayStar123 Aug 22, 2024
b7ca9d5
add log and log2 tests for u16, u32, u64, u8
SwayStar123 Aug 22, 2024
3f6bbbd
use compiler intrinsics in panic_on_overflow_enabled
SwayStar123 Aug 22, 2024
1f1ef85
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 22, 2024
9bcbbdf
comment out failing tests
SwayStar123 Aug 22, 2024
9ae376f
add commented 0th root test
SwayStar123 Aug 23, 2024
120155d
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 23, 2024
bb66005
comment tests and add logs
SwayStar123 Aug 23, 2024
0e81036
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 23, 2024
be43433
fmt
SwayStar123 Aug 26, 2024
19c0152
Merge branch 'swaystar123/proper_overflow_unsafe_math_checking' of ht…
SwayStar123 Aug 26, 2024
1659638
change u8 add and mul back to how it was
SwayStar123 Aug 26, 2024
4b585b1
f,mt
SwayStar123 Aug 26, 2024
1bcadae
add overflow tests
SwayStar123 Aug 26, 2024
434f1a3
add overflow tests
SwayStar123 Aug 26, 2024
5f2dce2
uncomment tests
SwayStar123 Aug 26, 2024
8d9ee95
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 26, 2024
4dcbe17
properly overflow
SwayStar123 Aug 26, 2024
01874e1
fmt
SwayStar123 Aug 26, 2024
a32edeb
remove unsafe math tests
SwayStar123 Aug 27, 2024
f7e8e7b
fmt
SwayStar123 Aug 27, 2024
3c48ffb
add back u256 log tests
SwayStar123 Aug 27, 2024
3ad9f3f
add back pow overflow tests
SwayStar123 Aug 27, 2024
4d4fcfc
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 27, 2024
1c78e35
move flag check to seperate if
SwayStar123 Aug 27, 2024
9ca5832
Merge branch 'swaystar123/proper_overflow_unsafe_math_checking' of ht…
SwayStar123 Aug 27, 2024
25d4f4c
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 28, 2024
60dabf4
add pow capping and tests
SwayStar123 Aug 28, 2024
5eb34eb
attempt u256 pow fix
SwayStar123 Aug 29, 2024
d271f37
assign directly
SwayStar123 Aug 29, 2024
499df33
use wqml instead of mul
SwayStar123 Aug 29, 2024
d3de539
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Aug 30, 2024
e807b7b
add i to 48 in assembly
SwayStar123 Aug 30, 2024
c168312
Merge branch 'swaystar123/proper_overflow_unsafe_math_checking' of ht…
SwayStar123 Aug 30, 2024
1e89675
simplify asm
SwayStar123 Aug 30, 2024
ae9b0b2
Update sway-lib-std/src/math.sw
SwayStar123 Sep 2, 2024
b2b17cc
Update sway-lib-std/src/math.sw
SwayStar123 Sep 2, 2024
bbc8728
Update sway-lib-std/src/math.sw
SwayStar123 Sep 2, 2024
7a1e44d
Update sway-lib-core/src/ops.sw
SwayStar123 Sep 2, 2024
5672dd7
Update sway-lib-std/src/math.sw
SwayStar123 Sep 2, 2024
a8871e2
Update test/src/in_language_tests/test_programs/math_inline_tests/src…
SwayStar123 Sep 2, 2024
e10fa19
update documentation
SwayStar123 Sep 2, 2024
fe73915
Update sway-lib-std/src/math.sw
SwayStar123 Sep 2, 2024
5746b6c
add more math tests
SwayStar123 Sep 2, 2024
6784761
Merge branch 'swaystar123/proper_overflow_unsafe_math_checking' of ht…
SwayStar123 Sep 2, 2024
80e55f0
Update sway-lib-core/src/ops.sw
SwayStar123 Sep 2, 2024
0f8e90d
Update sway-lib-core/src/ops.sw
SwayStar123 Sep 2, 2024
876b98b
import option variants
SwayStar123 Sep 2, 2024
8f897ba
Merge branch 'swaystar123/proper_overflow_unsafe_math_checking' of ht…
SwayStar123 Sep 2, 2024
65f554a
import self aswell
SwayStar123 Sep 2, 2024
901343d
self not Self
SwayStar123 Sep 2, 2024
a5bae63
Merge branch 'master' of https://github.com/FuelLabs/sway into swayst…
SwayStar123 Sep 2, 2024
d576c47
fmt
SwayStar123 Sep 2, 2024
636ff3b
remove _u256
SwayStar123 Sep 2, 2024
110a913
fix tests
SwayStar123 Sep 2, 2024
1f1ee30
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
sdankel Sep 4, 2024
0ad0cb8
rename panic_on_overflow_enabled function
SwayStar123 Sep 5, 2024
f645aca
Merge branch 'swaystar123/proper_overflow_unsafe_math_checking' of ht…
SwayStar123 Sep 5, 2024
642038d
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Sep 5, 2024
f2d9b9d
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Sep 5, 2024
71501ba
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Sep 5, 2024
fc4bc3c
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
bitzoic Sep 6, 2024
45845a1
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Sep 6, 2024
79e5962
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
K1-R1 Sep 6, 2024
8f8816e
Merge branch 'master' into swaystar123/proper_overflow_unsafe_math_ch…
SwayStar123 Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 64 additions & 8 deletions sway-lib-core/src/ops.sw
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ impl Add for u32 {
// any non-64-bit value is compiled to a u64 value under-the-hood
// constants (like Self::max() below) are also automatically promoted to u64
let res = __add(self, other);
// integer overflow
if __gt(res, Self::max()) {
// integer overflow
__revert(0)
if panic_on_overflow_is_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__mod(res, __add(Self::max(), 1))
}
} else {
// no overflow
res
Expand All @@ -73,7 +79,13 @@ impl Add for u16 {
fn add(self, other: Self) -> Self {
let res = __add(self, other);
if __gt(res, Self::max()) {
__revert(0)
if panic_on_overflow_is_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__mod(res, __add(Self::max(), 1))
}
} else {
res
}
Expand All @@ -93,7 +105,16 @@ impl Add for u8 {
input: u64
};
if __gt(res_u64, max_u8_u64) {
__revert(0)
if panic_on_overflow_is_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
let res_u64 = __mod(res_u64, __add(max_u8_u64, 1));
asm(input: res_u64) {
input: u8
}
}
} else {
asm(input: res_u64) {
input: u8
Expand Down Expand Up @@ -229,8 +250,14 @@ impl Multiply for u32 {
// constants (like Self::max() below) are also automatically promoted to u64
let res = __mul(self, other);
if __gt(res, Self::max()) {
// integer overflow
__revert(0)
if panic_on_overflow_is_enabled() {
// integer overflow
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__mod(res, __add(Self::max(), 1))
}
} else {
// no overflow
res
Expand All @@ -242,7 +269,11 @@ impl Multiply for u16 {
fn multiply(self, other: Self) -> Self {
let res = __mul(self, other);
if __gt(res, Self::max()) {
__revert(0)
if panic_on_overflow_is_enabled() {
__revert(0)
} else {
__mod(res, __add(Self::max(), 1))
}
} else {
res
}
Expand All @@ -262,7 +293,16 @@ impl Multiply for u8 {
input: u64
};
if __gt(res_u64, max_u8_u64) {
__revert(0)
if panic_on_overflow_is_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
let res_u64 = __mod(res_u64, __add(max_u8_u64, 1));
asm(input: res_u64) {
input: u8
}
}
} else {
asm(input: res_u64) {
input: u8
Expand Down Expand Up @@ -1258,3 +1298,19 @@ pub fn ok_str_eq() {
assert("" != "a");
assert("a" != "b");
}

fn flags() -> u64 {
SwayStar123 marked this conversation as resolved.
Show resolved Hide resolved
asm() {
flag
}
}

fn panic_on_overflow_is_enabled() -> bool {
__eq(
__and(
flags(),
0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010,
),
0,
)
}
98 changes: 81 additions & 17 deletions sway-lib-std/src/math.sw
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
library;

use ::assert::*;
use ::revert::revert;
use ::option::Option::{self, None, Some};
use ::flags::{
disable_panic_on_overflow,
panic_on_overflow_enabled,
Expand Down Expand Up @@ -78,12 +80,38 @@ pub trait Power {
fn pow(self, exponent: u32) -> Self;
}

fn u256_checked_mul(a: u256, b: u256) -> Option<u256> {
let res = u256::zero();

// The six-bit immediate value is used to select operating mode, as follows:

// Bits Short name Description
// ..XXXX reserved Reserved and must be zero
// .X.... indirect0 Is lhs operand ($rB) indirect or not
// X..... indirect1 Is rhs operand ($rC) indirect or not
// As both operands are indirect, 110000 is used, which is 48 in decimal.
let of = asm(res: res, a: a, b: b) {
wqml res a b i48;
of: u64
};

if of != 0 {
return None;
}

Some(res)
}

impl Power for u256 {
/// Raises self to the power of `exponent`, using exponentiation by squaring.
///
/// # Panics
/// # Additional Information
///
/// * If panic on overflow is disabled, and the result overflows, the return value will be 0.
///
/// Panics if the result overflows the type.
/// # Reverts
///
/// * Reverts if the result overflows the type, if panic on overflow is enabled.
fn pow(self, exponent: u32) -> Self {
let one = 0x0000000000000000000000000000000000000000000000000000000000000001u256;

Expand All @@ -97,13 +125,28 @@ impl Power for u256 {

while exp > 1 {
if (exp & 1) == 1 {
acc = acc * base;
// acc = acc * base;
let res = u256_checked_mul(acc, base);
acc = match res {
Some(val) => val,
None => return u256::zero(),
}
}
exp = exp >> 1;
base = base * base;
// base = base * base;
let res = u256_checked_mul(base, base);
base = match res {
Some(val) => val,
None => return u256::zero(),
}
}

acc * base
// acc * base
let res = u256_checked_mul(acc, base);
match res {
Some(val) => val,
None => u256::zero(),
}
}
}

Expand All @@ -118,14 +161,21 @@ impl Power for u64 {

impl Power for u32 {
fn pow(self, exponent: u32) -> Self {
let res = asm(r1: self, r2: exponent, r3) {
let mut res = asm(r1: self, r2: exponent, r3) {
exp r3 r1 r2;
r3: u64
};
// If panic on wrapping math is enabled, only then revert
if panic_on_overflow_enabled() {
assert(res <= Self::max().as_u64());

if res > Self::max().as_u64() {
// If panic on wrapping math is enabled, only then revert
if panic_on_overflow_enabled() {
revert(0);
} else {
// Follow spec of returning 0 for overflow
res = 0;
}
}

asm(r1: res) {
r1: Self
}
Expand All @@ -134,14 +184,21 @@ impl Power for u32 {

impl Power for u16 {
fn pow(self, exponent: u32) -> Self {
let res = asm(r1: self, r2: exponent, r3) {
let mut res = asm(r1: self, r2: exponent, r3) {
exp r3 r1 r2;
r3: u64
};
// If panic on wrapping math is enabled, only then revert
if panic_on_overflow_enabled() {
assert(res <= Self::max().as_u64());

if res > Self::max().as_u64() {
// If panic on wrapping math is enabled, only then revert
if panic_on_overflow_enabled() {
revert(0);
} else {
// Follow spec of returning 0 for overflow
res = 0;
}
}

asm(r1: res) {
r1: Self
}
Expand All @@ -150,14 +207,21 @@ impl Power for u16 {

impl Power for u8 {
fn pow(self, exponent: u32) -> Self {
let res = asm(r1: self, r2: exponent, r3) {
let mut res = asm(r1: self, r2: exponent, r3) {
exp r3 r1 r2;
r3: u64
};
// If panic on wrapping math is enabled, only then revert
if panic_on_overflow_enabled() {
assert(res <= Self::max().as_u64());

if res > Self::max().as_u64() {
// If panic on wrapping math is enabled, only then revert
if panic_on_overflow_enabled() {
revert(0);
} else {
// Follow spec of returning 0 for overflow
res = 0;
}
}

asm(r1: res) {
r1: Self
}
Expand Down
Loading
Loading