Skip to content

Commit

Permalink
fix: grow memory when not enough space on stack
Browse files Browse the repository at this point in the history
+ add additional tests
  • Loading branch information
BowTiedWoo committed Jan 10, 2025
1 parent 3c1f521 commit 7462815
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 36 deletions.
89 changes: 89 additions & 0 deletions clar2wasm/src/standard/standard.wat
Original file line number Diff line number Diff line change
Expand Up @@ -2653,6 +2653,28 @@
(local $i i32) (local $j i32)
(local.set $j (local.tee $i (global.get $stack-pointer)))

;; Check if we need more memory (40 bytes is max needed for uint128)
(if (i32.gt_u
(i32.add (local.get $i) (i32.const 40))
(i32.mul (memory.size) (i32.const 65536)))
(then
;; Calculate needed pages (64KB per page)
(memory.grow
(i32.add
(i32.div_u
(i32.sub
(i32.add (local.get $i) (i32.const 40))
(i32.mul (memory.size) (i32.const 65536))
)
(i32.const 65536)
)
(i32.const 1) ;; Add one extra page for safety
)
)
drop ;; Drop the previous memory size returned by memory.grow
)
)

;; slow loop while $hi > 0
(if (i64.ne (local.get $hi) (i64.const 0))
(then
Expand Down Expand Up @@ -2725,6 +2747,28 @@

(func $stdlib.int-to-string (param $lo i64) (param $hi i64) (result i32 i32)
(local $negative i32) (local $len i32)

;; Grow memory if needed (41 bytes: 40 for digits + 1 for minus sign)
(if (i32.gt_u
(i32.add (global.get $stack-pointer) (i32.const 41))
(i32.mul (memory.size) (i32.const 65536))) ;; 0x10000 = memory size of a page
(then
(memory.grow
(i32.add
(i32.shr_u
(i32.sub
(i32.add (global.get $stack-pointer) (i32.const 41))
(i32.mul (memory.size) (i32.const 65536))
)
(i32.const 16) ;; 2^16 = 65536
)
(i32.const 1) ;; Extra page for safety
)
)
drop
)
)

(local.set $negative (i64.lt_s (local.get $hi) (i64.const 0)))
;; add a '-' if n < 0
(if (local.get $negative)
Expand Down Expand Up @@ -2762,6 +2806,28 @@
(local $i i32) (local $j i32)
(local.set $j (local.tee $i (global.get $stack-pointer)))

;; Check if we need more memory (40 bytes is max needed for uint128)
(if (i32.gt_u
(i32.add (local.get $i) (i32.const 40))
(i32.mul (memory.size) (i32.const 65536))) ;; 0x10000 = memory size of a page
(then
;; Calculate needed pages (64KB per page)
(memory.grow
(i32.add
(i32.div_u
(i32.sub
(i32.add (local.get $i) (i32.const 40))
(i32.mul (memory.size) (i32.const 65536))
)
(i32.const 65536)
)
(i32.const 1) ;; Add one extra page for safety
)
)
drop ;; Drop the previous memory size returned by memory.grow
)
)

;; slow loop while $hi > 0
(if (i64.ne (local.get $hi) (i64.const 0))
(then
Expand Down Expand Up @@ -2837,6 +2903,29 @@

(func $stdlib.int-to-utf8 (param $lo i64) (param $hi i64) (result i32 i32)
(local $negative i32) (local $len i32)

;; Grow memory if needed (44 bytes: 40 for digits + 4 for UTF-8 minus sign)
(if (i32.gt_u
(i32.add (global.get $stack-pointer) (i32.const 44))
(i32.mul (memory.size) (i32.const 65536))
)
(then
(memory.grow
(i32.add
(i32.shr_u ;; Use shift instead of division
(i32.sub
(i32.add (global.get $stack-pointer) (i32.const 44))
(i32.mul (memory.size) (i32.const 65536))
)
(i32.const 16) ;; 2^16 = 65536
)
(i32.const 1) ;; Extra page for safety
)
)
drop
)
)

(local.set $negative (i32.shl (i64.lt_s (local.get $hi) (i64.const 0)) (i32.const 2)))
;; add a '-' if n < 0
(if (local.get $negative)
Expand Down
120 changes: 84 additions & 36 deletions clar2wasm/tests/oom-checker/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,6 @@ fn concat_oom() {
);
}

#[cfg(not(feature = "test-clarity-v1"))]
#[test]
fn replace_at_oom() {
crosscheck_oom_with_non_literal_args(
"(replace-at? (list 1 2 3) u0 42)",
&[list_of(TypeSignature::IntType, 3)],
Ok(Some(
Value::some(
Value::cons_list_unsanitized(vec![Value::Int(42), Value::Int(2), Value::Int(3)])
.unwrap(),
)
.unwrap(),
)),
);
}

#[test]
fn map_oom() {
crosscheck_oom_with_non_literal_args(
Expand Down Expand Up @@ -243,26 +227,6 @@ fn get_burn_block_info_pox_addrs_oom() {
);
}

#[test]
#[ignore = "issue #592"]
fn int_to_ascii_oom() {
crosscheck_oom(
"(int-to-ascii 42)",
Ok(Some(
Value::string_ascii_from_bytes(b"42".to_vec()).unwrap(),
)),
);
}

#[test]
#[ignore = "issue #592"]
fn int_to_utf8_oom() {
crosscheck_oom(
"(int-to-utf8 42)",
Ok(Some(Value::string_utf8_from_bytes(b"42".to_vec()).unwrap())),
);
}

#[test]
fn data_var_oom() {
crosscheck_oom(
Expand All @@ -282,3 +246,87 @@ fn secp256k1_recover_oom() {
Ok(Some(Value::okay(Value::buff_from(vec![3, 173, 184, 222, 75, 251, 101, 219, 44, 253, 97, 32, 213, 92, 101, 38, 174, 156, 82, 230, 117, 219, 126, 71, 48, 134, 54, 83, 75, 167, 120, 97, 16]).unwrap()).unwrap())),
);
}

#[cfg(not(feature = "test-clarity-v1"))]
#[cfg(test)]
mod clarity_v2_v3 {
use clarity::vm::types::TypeSignature;
use clarity::vm::Value;

use crate::{crosscheck_oom, crosscheck_oom_with_non_literal_args, list_of};

#[test]
fn replace_at_oom() {
crosscheck_oom_with_non_literal_args(
"(replace-at? (list 1 2 3) u0 42)",
&[list_of(TypeSignature::IntType, 3)],
Ok(Some(
Value::some(
Value::cons_list_unsanitized(vec![
Value::Int(42),
Value::Int(2),
Value::Int(3),
])
.unwrap(),
)
.unwrap(),
)),
);
}

#[test]
fn int_to_ascii_oom_negative() {
crosscheck_oom(
"(int-to-ascii -42)",
Ok(Some(
Value::string_ascii_from_bytes(b"-42".to_vec()).unwrap(),
)),
);
}

#[test]
fn int_to_utf8_oom_negative() {
crosscheck_oom(
"(int-to-utf8 -42)",
Ok(Some(
Value::string_utf8_from_bytes(b"-42".to_vec()).unwrap(),
)),
);
}

#[test]
fn int_to_ascii_oom() {
crosscheck_oom(
"(int-to-ascii 42)",
Ok(Some(
Value::string_ascii_from_bytes(b"42".to_vec()).unwrap(),
)),
);
}

#[test]
fn int_to_utf8_oom() {
crosscheck_oom(
"(int-to-utf8 42)",
Ok(Some(Value::string_utf8_from_bytes(b"42".to_vec()).unwrap())),
);
}

#[test]
fn unsigned_value_int_to_ascii_oom() {
crosscheck_oom(
"(int-to-ascii u42)",
Ok(Some(
Value::string_ascii_from_bytes(b"42".to_vec()).unwrap(),
)),
);
}

#[test]
fn unsigned_value_int_to_utf8_oom() {
crosscheck_oom(
"(int-to-utf8 u42)",
Ok(Some(Value::string_utf8_from_bytes(b"42".to_vec()).unwrap())),
);
}
}

0 comments on commit 7462815

Please sign in to comment.