From e13904b4c9b75ce53be2cd0b80851192f472f6c2 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 18 Jun 2024 01:08:51 +0300 Subject: [PATCH 01/12] detect write op --- .../mappers/linked-list-repeat/file.txt | 2150 +++++++++++++++++ .../src/linked_list_repeat.rs | 6 +- .../linked-list-repeat/wasm/src/lib.rs | 6 +- 3 files changed, 2157 insertions(+), 5 deletions(-) create mode 100644 contracts/benchmarks/mappers/linked-list-repeat/file.txt diff --git a/contracts/benchmarks/mappers/linked-list-repeat/file.txt b/contracts/benchmarks/mappers/linked-list-repeat/file.txt new file mode 100644 index 0000000000..799122fd71 --- /dev/null +++ b/contracts/benchmarks/mappers/linked-list-repeat/file.txt @@ -0,0 +1,2150 @@ + /home/bibi/Desktop/mx-sdk-rs/contracts/benchmarks/mappers/linked-list-repeat + +Found 1 contract crates. + +(1/1) +In /home/bibi/Desktop/mx-sdk-rs/contracts/benchmarks/mappers/linked-list-repeat/meta +Calling `cargo run build` +Using workspace target directory: /home/bibi/Desktop/mx-sdk-rs/target ... +Building linked-list-repeat.wasm in /home/bibi/Desktop/mx-sdk-rs/contracts/benchmarks/mappers/linked-list-repeat/wasm ... +RUSTFLAGS="-C link-arg=-s -C link-arg=-zstack-size=131072" cargo build --target=wasm32-unknown-unknown --release --target-dir /home/bibi/Desktop/mx-sdk-rs/target +Copying /home/bibi/Desktop/mx-sdk-rs/target/wasm32-unknown-unknown/release/linked_list_repeat_wasm.wasm to ../output/linked-list-repeat.wasm ... +Calling wasm-opt on ../output/linked-list-repeat.wasm ... +Extracting imports to ../output/linked-list-repeat.imports.json ... +FailAllocator used while memory allocation is accessible in code. Contract may fail unexpectedly when memory allocation is attempted +Instruction: Call { function_index: 24 } +Call instruction: calls function index 24 +Instruction: I32Const { value: 131268 } +Instruction: I32Const { value: 131268 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: I32Const { value: 1 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: End +Instruction: Call { function_index: 2 } +Call instruction: calls function index 2 +Instruction: LocalTee { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 3 } +Call instruction: calls function index 3 +Instruction: Drop +Instruction: LocalGet { local_index: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 4 } +Call instruction: calls function index 4 +Instruction: I32Const { value: 0 } +Instruction: I32GtS +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 96 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Eqz +Instruction: If { blockty: Type(I64) } +Instruction: I64Const { value: 0 } +Instruction: Else +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: Call { function_index: 28 } +Call instruction: calls function index 28 +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: Call { function_index: 25 } +Call instruction: calls function index 25 +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } +Instruction: Call { function_index: 23 } +Call instruction: calls function index 23 +Instruction: LocalSet { local_index: 3 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } +Instruction: Call { function_index: 25 } +Call instruction: calls function index 25 +Instruction: LocalSet { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } +Instruction: LocalSet { local_index: 6 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } +Instruction: Call { function_index: 23 } +Call instruction: calls function index 23 +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 5 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 6 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 3 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 66 } +Call instruction: calls function index 66 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: If { blockty: Type(I32) } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: Call { function_index: 25 } +Call instruction: calls function index 25 +Instruction: LocalSet { local_index: 3 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: LocalTee { local_index: 6 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalSet { local_index: 7 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalTee { local_index: 8 } +Instruction: Call { function_index: 31 } +Call instruction: calls function index 31 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 3 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 66 } +Call instruction: calls function index 66 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 33 } +Call instruction: calls function index 33 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 1 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: I32Const { value: 4 } +Instruction: Call { function_index: 47 } +Call instruction: calls function index 47 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 24 } +Call instruction: calls function index 24 +Instruction: LocalTee { local_index: 0 } +Instruction: Call { function_index: 17 } +Call instruction: calls function index 17 +Instruction: Drop +Instruction: LocalGet { local_index: 0 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 36 } +Call instruction: calls function index 36 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 1 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: Call { function_index: 24 } +Call instruction: calls function index 24 +Instruction: LocalTee { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 5 } +Call instruction: calls function index 5 +Instruction: Drop +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 38 } +Call instruction: calls function index 38 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 7 } +Call instruction: calls function index 7 +Instruction: LocalTee { local_index: 3 } +Instruction: I32Const { value: 24 } +Instruction: I32Shl +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: I32Const { value: 8 } +Instruction: I32Shl +Instruction: I32Or +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 8 } +Instruction: I32ShrU +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 24 } +Instruction: I32ShrU +Instruction: I32Or +Instruction: I32Or +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: I32Const { value: 4 } +Instruction: Call { function_index: 73 } +Call instruction: calls function index 73 +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 24 } +Call instruction: calls function index 24 +Instruction: LocalTee { local_index: 1 } +Instruction: Call { function_index: 6 } +Call instruction: calls function index 6 +Instruction: Drop +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 7 } +Call instruction: calls function index 7 +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 0 } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 24 } +Call instruction: calls function index 24 +Instruction: LocalTee { local_index: 0 } +Instruction: Call { function_index: 8 } +Call instruction: calls function index 8 +Instruction: Drop +Instruction: LocalGet { local_index: 0 } +Instruction: End +Instruction: I32Const { value: 131086 } +Instruction: I32Const { value: 23 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: Call { function_index: 24 } +Call instruction: calls function index 24 +Instruction: LocalTee { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 16 } +Call instruction: calls function index 16 +Instruction: Drop +Instruction: LocalGet { local_index: 2 } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 40 } +Call instruction: calls function index 40 +Instruction: LocalTee { local_index: 3 } +Instruction: Call { function_index: 7 } +Call instruction: calls function index 7 +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 0 } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 28, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: LocalTee { local_index: 3 } +Instruction: Call { function_index: 33 } +Call instruction: calls function index 33 +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 44 } +Call instruction: calls function index 44 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I64Const { value: 0 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: I32Const { value: 8 } +Instruction: Call { function_index: 47 } +Call instruction: calls function index 47 +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 11 } +Call instruction: calls function index 11 +Instruction: LocalTee { local_index: 0 } +Instruction: I64Const { value: 4294967296 } +Instruction: I64GeU +Instruction: If { blockty: Empty } +Instruction: I32Const { value: 131189 } +Instruction: I32Const { value: 11 } +Instruction: I32Const { value: 131072 } +Instruction: I32Const { value: 14 } +Instruction: Call { function_index: 41 } +Call instruction: calls function index 41 +Instruction: Unreachable +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32WrapI64 +Instruction: End +Instruction: Call { function_index: 12 } +Call instruction: calls function index 12 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Eq +Instruction: If { blockty: Empty } +Instruction: Return +Instruction: End +Instruction: I32Const { value: 131112 } +Instruction: I32Const { value: 25 } +Instruction: Call { function_index: 13 } +Call instruction: calls function index 13 +Instruction: Unreachable +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 53 } +Call instruction: calls function index 53 +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 2 } +Call instruction: calls function index 2 +Instruction: LocalTee { local_index: 1 } +Instruction: Call { function_index: 18 } +Call instruction: calls function index 18 +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Eqz +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 1 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: I32Const { value: 4 } +Instruction: Call { function_index: 74 } +Call instruction: calls function index 74 +Instruction: I32Const { value: 131162 } +Instruction: I32Const { value: 22 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: LocalTee { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 9 } +Call instruction: calls function index 9 +Instruction: Drop +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 10 } +Call instruction: calls function index 10 +Instruction: Unreachable +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 14 } +Call instruction: calls function index 14 +Instruction: I32Eqz +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 15 } +Call instruction: calls function index 15 +Instruction: I32Const { value: 0 } +Instruction: I32Ne +Instruction: End +Instruction: Block { blockty: Empty } +Instruction: Block { blockty: Empty } +Instruction: Block { blockty: Type(I32) } +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 8, memory: 0 } } +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalTee { local_index: 4 } +Instruction: Call { function_index: 7 } +Call instruction: calls function index 7 +Instruction: LocalTee { local_index: 5 } +Instruction: I32Const { value: 10000 } +Instruction: I32GtU +Instruction: BrIf { relative_depth: 1 } +Instruction: I32Const { value: 141276 } +Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: BrIf { relative_depth: 1 } +Instruction: I32Const { value: 141272 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: I32Const { value: 141276 } +Instruction: I32Const { value: 1 } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Const { value: 0 } +Instruction: I32Const { value: 131272 } +Instruction: LocalGet { local_index: 5 } +Instruction: Call { function_index: 52 } +Call instruction: calls function index 52 +Instruction: Drop +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 1 } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 8, memory: 0 } } +Instruction: End +Instruction: I32Const { value: 1 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Add +Instruction: LocalTee { local_index: 0 } +Instruction: I32Const { value: 141272 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: I32GtU +Instruction: BrIf { relative_depth: 1 } +Instruction: Drop +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32LtU +Instruction: BrIf { relative_depth: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 10000 } +Instruction: I32GtU +Instruction: BrIf { relative_depth: 3 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 131272 } +Instruction: I32Add +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 89 } +Call instruction: calls function index 89 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: -25 } +Instruction: Call { function_index: 6 } +Call instruction: calls function index 6 +Instruction: Drop +Instruction: I32Const { value: -25 } +Instruction: Call { function_index: 7 } +Call instruction: calls function index 7 +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 56 } +Call instruction: calls function index 56 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: Call { function_index: 19 } +Call instruction: calls function index 19 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 58 } +Call instruction: calls function index 58 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 25 } +Call instruction: calls function index 25 +Instruction: LocalTee { local_index: 0 } +Instruction: I32Const { value: 131157 } +Instruction: I32Const { value: 5 } +Instruction: Call { function_index: 9 } +Call instruction: calls function index 9 +Instruction: Drop +Instruction: LocalGet { local_index: 0 } +Instruction: End +Instruction: I32Const { value: 131224 } +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 24 } +Instruction: I32Shl +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: I32Const { value: 8 } +Instruction: I32Shl +Instruction: I32Or +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32ShrU +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 24 } +Instruction: I32ShrU +Instruction: I32Or +Instruction: I32Or +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: I32Const { value: 4 } +Instruction: Call { function_index: 73 } +Call instruction: calls function index 73 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 19 } +Call instruction: calls function index 19 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 25 } +Call instruction: calls function index 25 +Instruction: LocalTee { local_index: 0 } +Instruction: I32Const { value: 131152 } +Instruction: I32Const { value: 5 } +Instruction: Call { function_index: 9 } +Call instruction: calls function index 9 +Instruction: Drop +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 24 } +Instruction: I32Shl +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: I32Const { value: 8 } +Instruction: I32Shl +Instruction: I32Or +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 8 } +Instruction: I32ShrU +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 24 } +Instruction: I32ShrU +Instruction: I32Or +Instruction: I32Or +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: I32Const { value: 4 } +Instruction: Call { function_index: 9 } +Call instruction: calls function index 9 +Instruction: Drop +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: Call { function_index: 59 } +Call instruction: calls function index 59 +Instruction: LocalSet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 38 } +Call instruction: calls function index 38 +Instruction: LocalGet { local_index: 2 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 65 } +Call instruction: calls function index 65 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 56 } +Instruction: I64Shl +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 65280 } +Instruction: I64And +Instruction: I64Const { value: 40 } +Instruction: I64Shl +Instruction: I64Or +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 16711680 } +Instruction: I64And +Instruction: I64Const { value: 24 } +Instruction: I64Shl +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 4278190080 } +Instruction: I64And +Instruction: I64Const { value: 8 } +Instruction: I64Shl +Instruction: I64Or +Instruction: I64Or +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 8 } +Instruction: I64ShrU +Instruction: I64Const { value: 4278190080 } +Instruction: I64And +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 24 } +Instruction: I64ShrU +Instruction: I64Const { value: 16711680 } +Instruction: I64And +Instruction: I64Or +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 40 } +Instruction: I64ShrU +Instruction: I64Const { value: 65280 } +Instruction: I64And +Instruction: LocalGet { local_index: 0 } +Instruction: I64Const { value: 56 } +Instruction: I64ShrU +Instruction: I64Or +Instruction: I64Or +Instruction: I64Or +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: I32Const { value: 8 } +Instruction: Call { function_index: 73 } +Call instruction: calls function index 73 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: Call { function_index: 54 } +Call instruction: calls function index 54 +Instruction: I32Eqz +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 3 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: Call { function_index: 39 } +Call instruction: calls function index 39 +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 36 } +Call instruction: calls function index 36 +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 4 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: I32Eq +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 28, memory: 0 } } +Instruction: If { blockty: Empty } +Instruction: I32Const { value: 141272 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: I32Const { value: 141276 } +Instruction: I32Const { value: 0 } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 32 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: Return +Instruction: End +Instruction: I32Const { value: 131072 } +Instruction: I32Const { value: 14 } +Instruction: Call { function_index: 50 } +Call instruction: calls function index 50 +Instruction: Unreachable +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 3 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: Call { function_index: 39 } +Call instruction: calls function index 39 +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 36 } +Call instruction: calls function index 36 +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 72 } +Call instruction: calls function index 72 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 32 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalTee { local_index: 3 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Block { blockty: Empty } +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 58 } +Call instruction: calls function index 58 +Instruction: LocalTee { local_index: 1 } +Instruction: Call { function_index: 54 } +Call instruction: calls function index 54 +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: I32Const { value: 0 } +Instruction: LocalSet { local_index: 1 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: LocalTee { local_index: 3 } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 39 } +Call instruction: calls function index 39 +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 3 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 4 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: Call { function_index: 49 } +Call instruction: calls function index 49 +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: I32Ne +Instruction: BrIf { relative_depth: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 28, memory: 0 } } +Instruction: I32Eqz +Instruction: BrIf { relative_depth: 0 } +Instruction: I32Const { value: 141272 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: I32Const { value: 141276 } +Instruction: I32Const { value: 0 } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 32 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: Return +Instruction: End +Instruction: I32Const { value: 131072 } +Instruction: I32Const { value: 14 } +Instruction: Call { function_index: 50 } +Call instruction: calls function index 50 +Instruction: Unreachable +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 80 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: -64 } +Instruction: I32Sub +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalTee { local_index: 3 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 68, memory: 0 } } +Instruction: Call { function_index: 29 } +Call instruction: calls function index 29 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Const { value: 56 } +Instruction: Call { function_index: 89 } +Call instruction: calls function index 89 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 2 } +Instruction: GlobalSet { global_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I64Const { value: 0 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: I32Const { value: 8 } +Instruction: Call { function_index: 74 } +Call instruction: calls function index 74 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 9 } +Call instruction: calls function index 9 +Instruction: Drop +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 53 } +Call instruction: calls function index 53 +Instruction: If { blockty: Empty } +Instruction: I32Const { value: 131137 } +Instruction: I32Const { value: 15 } +Instruction: Call { function_index: 50 } +Call instruction: calls function index 50 +Instruction: Unreachable +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Add +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: End +Instruction: I32Const { value: 131200 } +Instruction: I32Const { value: 12 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: End +Instruction: I32Const { value: 131212 } +Instruction: I32Const { value: 9 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: End +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 2 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: Call { function_index: 45 } +Call instruction: calls function index 45 +Instruction: LocalSet { local_index: 6 } +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 40 } +Call instruction: calls function index 40 +Instruction: LocalSet { local_index: 7 } +Instruction: Call { function_index: 76 } +Call instruction: calls function index 76 +Instruction: LocalSet { local_index: 2 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 6 } +Instruction: I32Ne +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 7 } +Instruction: Call { function_index: 25 } +Call instruction: calls function index 25 +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 24 } +Instruction: I32Shl +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: I32Const { value: 8 } +Instruction: I32Shl +Instruction: I32Or +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 8 } +Instruction: I32ShrU +Instruction: I32Const { value: 65280 } +Instruction: I32And +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 24 } +Instruction: I32ShrU +Instruction: I32Or +Instruction: I32Or +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 5 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: I32Const { value: 4 } +Instruction: Call { function_index: 9 } +Call instruction: calls function index 9 +Instruction: Drop +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalTee { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalTee { local_index: 8 } +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: I32Const { value: 0 } +Instruction: LocalSet { local_index: 4 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: LocalTee { local_index: 9 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } +Instruction: LocalTee { local_index: 4 } +Instruction: Call { function_index: 67 } +Call instruction: calls function index 67 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 4 } +Instruction: LocalGet { local_index: 9 } +Instruction: Call { function_index: 62 } +Call instruction: calls function index 62 +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: Call { function_index: 62 } +Call instruction: calls function index 62 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 8 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 57 } +Call instruction: calls function index 57 +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: -64 } +Instruction: I32Add +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 40 } +Call instruction: calls function index 40 +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 76 } +Call instruction: calls function index 76 +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: Call { function_index: 69 } +Call instruction: calls function index 69 +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 44 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: Call { function_index: 30 } +Call instruction: calls function index 30 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 44, memory: 0 } } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 48, memory: 0 } } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 26 } +Call instruction: calls function index 26 +Instruction: LocalGet { local_index: 1 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 1 } +Instruction: I64ExtendI32U +Instruction: Call { function_index: 21 } +Call instruction: calls function index 21 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: -64 } +Instruction: I32Sub +Instruction: GlobalSet { global_index: 0 } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: -64 } +Instruction: I32Add +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: Call { function_index: 45 } +Call instruction: calls function index 45 +Instruction: LocalSet { local_index: 5 } +Instruction: Call { function_index: 76 } +Call instruction: calls function index 76 +Instruction: LocalSet { local_index: 1 } +Instruction: Block { blockty: Empty } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 5 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 12 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalTee { local_index: 2 } +Instruction: Call { function_index: 66 } +Call instruction: calls function index 66 +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 28 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 31 } +Call instruction: calls function index 31 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } +Instruction: I32Eqz +Instruction: BrIf { relative_depth: 3 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 44, memory: 0 } } +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 40, memory: 0 } } +Instruction: LocalSet { local_index: 3 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 36, memory: 0 } } +Instruction: LocalTee { local_index: 6 } +Instruction: Call { function_index: 66 } +Call instruction: calls function index 66 +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 2 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 67 } +Call instruction: calls function index 67 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 36, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 62 } +Call instruction: calls function index 62 +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 52, memory: 0 } } +Instruction: End +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 3 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 28 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 67 } +Call instruction: calls function index 67 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 40, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 62 } +Call instruction: calls function index 62 +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 56, memory: 0 } } +Instruction: End +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 6 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: Call { function_index: 55 } +Call instruction: calls function index 55 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 48, memory: 0 } } +Instruction: I32Const { value: 1 } +Instruction: I32Sub +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 48, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Add +Instruction: Call { function_index: 57 } +Call instruction: calls function index 57 +Instruction: End +Instruction: LocalGet { local_index: 5 } +Instruction: I32Const { value: 1 } +Instruction: I32Sub +Instruction: LocalSet { local_index: 5 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: -64 } +Instruction: I32Sub +Instruction: GlobalSet { global_index: 0 } +Instruction: Return +Instruction: End +Instruction: Call { function_index: 81 } +Call instruction: calls function index 81 +Instruction: Call { function_index: 88 } +Call instruction: calls function index 88 +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 76 } +Call instruction: calls function index 76 +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 69 } +Call instruction: calls function index 69 +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 28 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: Call { function_index: 30 } +Call instruction: calls function index 30 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 32, memory: 0 } } +Instruction: Call { function_index: 22 } +Call instruction: calls function index 22 +Instruction: Drop +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 128 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 2 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: Call { function_index: 45 } +Call instruction: calls function index 45 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 32 } +Instruction: I32Add +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 43 } +Call instruction: calls function index 43 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 108 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 56 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalTee { local_index: 11 } +Instruction: I64Store { memarg: MemArg { align: 2, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 40 } +Instruction: I32Add +Instruction: LocalTee { local_index: 5 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 16 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 48 } +Instruction: I32Add +Instruction: LocalTee { local_index: 6 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 24 } +Instruction: I32Add +Instruction: LocalGet { local_index: 11 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 32, memory: 0 } } +Instruction: LocalTee { local_index: 11 } +Instruction: I64Store { memarg: MemArg { align: 2, max_align: 3, offset: 84, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 11 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64ExtendI32U +Instruction: LocalSet { local_index: 12 } +Instruction: I64Const { value: 0 } +Instruction: LocalSet { local_index: 11 } +Instruction: Call { function_index: 75 } +Call instruction: calls function index 75 +Instruction: LocalSet { local_index: 1 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 11 } +Instruction: LocalGet { local_index: 12 } +Instruction: I64Eq +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 80 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 28 } +Call instruction: calls function index 28 +Instruction: LocalGet { local_index: 5 } +Instruction: LocalGet { local_index: 11 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 6 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 96 } +Instruction: I32Add +Instruction: LocalTee { local_index: 7 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 4 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 104 } +Instruction: I32Add +Instruction: LocalTee { local_index: 8 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 11 } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 32, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: -64 } +Instruction: I32Sub +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 76, memory: 0 } } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalTee { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 76, memory: 0 } } +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } +Instruction: LocalTee { local_index: 9 } +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 68, memory: 0 } } +Instruction: I32Const { value: 0 } +Instruction: LocalSet { local_index: 3 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 80 } +Instruction: I32Add +Instruction: LocalTee { local_index: 10 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 72, memory: 0 } } +Instruction: LocalTee { local_index: 3 } +Instruction: Call { function_index: 68 } +Call instruction: calls function index 68 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 116, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 10 } +Instruction: Call { function_index: 64 } +Call instruction: calls function index 64 +Instruction: End +Instruction: LocalGet { local_index: 8 } +Instruction: LocalGet { local_index: 4 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 7 } +Instruction: LocalGet { local_index: 6 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 88 } +Instruction: I32Add +Instruction: LocalGet { local_index: 5 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 32, memory: 0 } } +Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 80, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 120, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 0 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 116, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 112, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 80 } +Instruction: I32Add +Instruction: Call { function_index: 64 } +Call instruction: calls function index 64 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 9 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 72, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: -64 } +Instruction: I32Sub +Instruction: Call { function_index: 57 } +Call instruction: calls function index 57 +Instruction: LocalGet { local_index: 11 } +Instruction: I64Const { value: 1 } +Instruction: I64Add +Instruction: LocalSet { local_index: 11 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 128 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 160 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 43 } +Call instruction: calls function index 43 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 75 } +Call instruction: calls function index 75 +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 36, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 40 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 36 } +Instruction: I32Add +Instruction: Call { function_index: 71 } +Call instruction: calls function index 71 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } +Instruction: LocalSet { local_index: 3 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } +Instruction: LocalSet { local_index: 4 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } +Instruction: LocalSet { local_index: 6 } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } +Instruction: LocalSet { local_index: 10 } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } +Instruction: LocalSet { local_index: 11 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 104 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 40 } +Instruction: I32Add +Instruction: Call { function_index: 27 } +Call instruction: calls function index 27 +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 104, memory: 0 } } +Instruction: I64Eqz +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 112, memory: 0 } } +Instruction: LocalSet { local_index: 12 } +Instruction: I32Const { value: 0 } +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 140, memory: 0 } } +Instruction: LocalSet { local_index: 7 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 136, memory: 0 } } +Instruction: LocalSet { local_index: 8 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 132, memory: 0 } } +Instruction: LocalSet { local_index: 9 } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 120, memory: 0 } } +Instruction: LocalSet { local_index: 13 } +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 128, memory: 0 } } +Instruction: LocalGet { local_index: 6 } +Instruction: Call { function_index: 26 } +Call instruction: calls function index 26 +Instruction: I32Eqz +Instruction: LocalGet { local_index: 11 } +Instruction: LocalGet { local_index: 12 } +Instruction: I64Ne +Instruction: I32Or +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 9 } +Instruction: LocalGet { local_index: 5 } +Instruction: Call { function_index: 51 } +Call instruction: calls function index 51 +Instruction: I32Eqz +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 8 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 26 } +Call instruction: calls function index 26 +Instruction: I32Eqz +Instruction: LocalGet { local_index: 10 } +Instruction: LocalGet { local_index: 13 } +Instruction: I64Ne +Instruction: I32Or +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 7 } +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 51 } +Call instruction: calls function index 51 +Instruction: LocalSet { local_index: 2 } +Instruction: End +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 1 } +Instruction: I64ExtendI32U +Instruction: Call { function_index: 21 } +Call instruction: calls function index 21 +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 160 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 96 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 1 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: Call { function_index: 45 } +Call instruction: calls function index 45 +Instruction: LocalSet { local_index: 5 } +Instruction: Call { function_index: 75 } +Call instruction: calls function index 75 +Instruction: LocalSet { local_index: 1 } +Instruction: Block { blockty: Empty } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 5 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } +Instruction: LocalTee { local_index: 2 } +Instruction: Call { function_index: 66 } +Call instruction: calls function index 66 +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 24 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 29 } +Call instruction: calls function index 29 +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 24, memory: 0 } } +Instruction: I64Eqz +Instruction: BrIf { relative_depth: 3 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 72, memory: 0 } } +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 68, memory: 0 } } +Instruction: LocalSet { local_index: 3 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } +Instruction: LocalTee { local_index: 6 } +Instruction: Call { function_index: 66 } +Call instruction: calls function index 66 +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 80 } +Instruction: I32Add +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 70 } +Call instruction: calls function index 70 +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 2 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: Call { function_index: 68 } +Call instruction: calls function index 68 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 60, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 64 } +Call instruction: calls function index 64 +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 84, memory: 0 } } +Instruction: End +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 3 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 24 } +Instruction: I32Add +Instruction: LocalTee { local_index: 4 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: Call { function_index: 68 } +Call instruction: calls function index 68 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 4 } +Instruction: Call { function_index: 64 } +Call instruction: calls function index 64 +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 88, memory: 0 } } +Instruction: End +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 6 } +Instruction: Call { function_index: 63 } +Call instruction: calls function index 63 +Instruction: Call { function_index: 55 } +Call instruction: calls function index 55 +Instruction: LocalGet { local_index: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 80, memory: 0 } } +Instruction: I32Const { value: 1 } +Instruction: I32Sub +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 80, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 80 } +Instruction: I32Add +Instruction: Call { function_index: 57 } +Call instruction: calls function index 57 +Instruction: End +Instruction: LocalGet { local_index: 5 } +Instruction: I32Const { value: 1 } +Instruction: I32Sub +Instruction: LocalSet { local_index: 5 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 96 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: Return +Instruction: End +Instruction: Call { function_index: 81 } +Call instruction: calls function index 81 +Instruction: Unreachable +Instruction: End +Instruction: GlobalGet { global_index: 0 } +Instruction: I32Const { value: 128 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 0 } +Instruction: GlobalSet { global_index: 0 } +Instruction: Call { function_index: 20 } +Call instruction: calls function index 20 +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 46 } +Call instruction: calls function index 46 +Instruction: LocalGet { local_index: 0 } +Instruction: Call { function_index: 75 } +Call instruction: calls function index 75 +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: Call { function_index: 71 } +Call instruction: calls function index 71 +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 72 } +Instruction: I32Add +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 8 } +Instruction: I32Add +Instruction: Call { function_index: 27 } +Call instruction: calls function index 27 +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 72, memory: 0 } } +Instruction: I64Eqz +Instruction: I32Eqz +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 108, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 88, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 104, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 100, memory: 0 } } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 96, memory: 0 } } +Instruction: I32Const { value: 131224 } +Instruction: I32Const { value: 0 } +Instruction: Call { function_index: 42 } +Call instruction: calls function index 42 +Instruction: LocalTee { local_index: 1 } +Instruction: Call { function_index: 38 } +Call instruction: calls function index 38 +Instruction: LocalGet { local_index: 0 } +Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 80, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 65 } +Call instruction: calls function index 65 +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 37 } +Call instruction: calls function index 37 +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 38 } +Call instruction: calls function index 38 +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 65 } +Call instruction: calls function index 65 +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 37 } +Call instruction: calls function index 37 +Instruction: LocalGet { local_index: 1 } +Instruction: Call { function_index: 22 } +Call instruction: calls function index 22 +Instruction: Drop +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 128 } +Instruction: I32Add +Instruction: GlobalSet { global_index: 0 } +Instruction: End +Instruction: End +Instruction: I32Const { value: 131224 } +Instruction: I32Const { value: 14 } +Instruction: Call { function_index: 13 } +Call instruction: calls function index 13 +Instruction: Unreachable +Instruction: End +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalTee { local_index: 4 } +Instruction: I32Const { value: 16 } +Instruction: I32LtU +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalSet { local_index: 2 } +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: I32Const { value: 0 } +Instruction: LocalGet { local_index: 0 } +Instruction: I32Sub +Instruction: I32Const { value: 3 } +Instruction: I32And +Instruction: LocalTee { local_index: 3 } +Instruction: I32Add +Instruction: LocalSet { local_index: 5 } +Instruction: LocalGet { local_index: 3 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 0 } +Instruction: LocalSet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalSet { local_index: 6 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 6 } +Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 6 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalSet { local_index: 6 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalTee { local_index: 2 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32LtU +Instruction: BrIf { relative_depth: 0 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 5 } +Instruction: LocalGet { local_index: 4 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Sub +Instruction: LocalTee { local_index: 8 } +Instruction: I32Const { value: -4 } +Instruction: I32And +Instruction: LocalTee { local_index: 7 } +Instruction: I32Add +Instruction: LocalSet { local_index: 2 } +Instruction: Block { blockty: Empty } +Instruction: LocalGet { local_index: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Add +Instruction: LocalTee { local_index: 3 } +Instruction: I32Const { value: 3 } +Instruction: I32And +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 7 } +Instruction: I32Const { value: 0 } +Instruction: I32LeS +Instruction: BrIf { relative_depth: 1 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: 3 } +Instruction: I32Shl +Instruction: LocalTee { local_index: 4 } +Instruction: I32Const { value: 24 } +Instruction: I32And +Instruction: LocalSet { local_index: 9 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32Const { value: -4 } +Instruction: I32And +Instruction: LocalTee { local_index: 6 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: I32Const { value: 0 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Sub +Instruction: I32Const { value: 24 } +Instruction: I32And +Instruction: LocalSet { local_index: 4 } +Instruction: LocalGet { local_index: 6 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalSet { local_index: 6 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 5 } +Instruction: LocalGet { local_index: 6 } +Instruction: LocalGet { local_index: 9 } +Instruction: I32ShrU +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalTee { local_index: 6 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Shl +Instruction: I32Or +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: LocalTee { local_index: 5 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32LtU +Instruction: BrIf { relative_depth: 0 } +Instruction: End +Instruction: Br { relative_depth: 1 } +Instruction: End +Instruction: LocalGet { local_index: 7 } +Instruction: I32Const { value: 0 } +Instruction: I32LeS +Instruction: BrIf { relative_depth: 0 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalSet { local_index: 1 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 5 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 5 } +Instruction: I32Const { value: 4 } +Instruction: I32Add +Instruction: LocalTee { local_index: 5 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32LtU +Instruction: BrIf { relative_depth: 0 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 8 } +Instruction: I32Const { value: 3 } +Instruction: I32And +Instruction: LocalSet { local_index: 4 } +Instruction: LocalGet { local_index: 3 } +Instruction: LocalGet { local_index: 7 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: End +Instruction: LocalGet { local_index: 4 } +Instruction: If { blockty: Empty } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 4 } +Instruction: I32Add +Instruction: LocalSet { local_index: 3 } +Instruction: Loop { blockty: Empty } +Instruction: LocalGet { local_index: 2 } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } +Instruction: LocalGet { local_index: 1 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalSet { local_index: 1 } +Instruction: LocalGet { local_index: 2 } +Instruction: I32Const { value: 1 } +Instruction: I32Add +Instruction: LocalTee { local_index: 2 } +Instruction: LocalGet { local_index: 3 } +Instruction: I32LtU +Instruction: BrIf { relative_depth: 0 } +Instruction: End +Instruction: End +Instruction: LocalGet { local_index: 0 } +Instruction: End +Checking EI version: 1.3 ... OK +Packing ../output/linked-list-repeat.mxsc.json ... +Contract size: 6615 bytes. +analyze this via wasm +analyze this via wasm diff --git a/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs b/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs index 40dfcba638..cc7d8959ff 100644 --- a/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs +++ b/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs @@ -1,8 +1,9 @@ #![no_std] +use benchmark_common::ExampleStruct; + multiversx_sc::imports!(); -use benchmark_common::ExampleStruct; pub mod linked_list_repeat_proxy; #[multiversx_sc::contract] @@ -38,7 +39,8 @@ pub trait LinkedListRepeat: benchmark_common::BenchmarkCommon { #[storage_mapper("benchmark")] fn bench(&self) -> LinkedListMapper; - #[endpoint] + #[view] + // #[endpoint] fn add_struct(&self, num_repeats: usize, value: ExampleStruct) { let mut bench = self.bench_struct(); for i in 0..num_repeats { diff --git a/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs index 1e79aa533a..9e22454e98 100644 --- a/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench => bench - add_struct => add_struct + bench___view => bench + add_struct___view => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct => bench_struct + bench_struct___view => bench_struct ) } From e5bfff759fc02dedba5cc9e9cb7147f7e2af8e35 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 18 Jun 2024 01:15:16 +0300 Subject: [PATCH 02/12] detect write op --- .../mappers/queue-repeat/wasm/src/lib.rs | 4 +- .../mappers/set-repeat/wasm/src/lib.rs | 4 +- .../mappers/vec-repeat/wasm/src/lib.rs | 4 +- contracts/examples/adder/src/adder.rs | 24 +++- contracts/examples/adder/wasm/src/lib.rs | 4 +- .../src/parse/attributes/endpoint_attr.rs | 2 +- framework/derive/src/parse/endpoint_parse.rs | 8 +- .../src/contract/sc_config/wasm_build.rs | 5 + .../meta-lib/src/tools/wasm_extractor.rs | 110 +++++++++++++++++- 9 files changed, 148 insertions(+), 17 deletions(-) diff --git a/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs index 887fb0c6e6..c254f43e57 100644 --- a/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench => bench + bench___view => bench add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct => bench_struct + bench_struct___view => bench_struct ) } diff --git a/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs index 7a1a61db74..79d7ac9f8a 100644 --- a/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench => bench + bench___view => bench add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct => bench_struct + bench_struct___view => bench_struct ) } diff --git a/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs index 6f915470d8..4a56536d8a 100644 --- a/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench => bench + bench___view => bench add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct => bench_struct + bench_struct___view => bench_struct ) } diff --git a/contracts/examples/adder/src/adder.rs b/contracts/examples/adder/src/adder.rs index 307f4112f5..18426a514f 100644 --- a/contracts/examples/adder/src/adder.rs +++ b/contracts/examples/adder/src/adder.rs @@ -1,3 +1,25 @@ +// 0 true, +// 1 true, +// 2 true, +// 3 true, +// 4 false, +// 5 true, +// 6 true, +// 7 true, +// 8 true, +// 9 true, +//10 true, +//11 true, +//12 true, +//13 true, +//14 false, +//15 true, +//16 true, +//17 false, +//18 true, +//19 false, +//20 true, + #![no_std] use multiversx_sc::imports::*; @@ -23,7 +45,7 @@ pub trait Adder { } /// Add desired amount to the storage variable. - #[endpoint] + #[view] fn add(&self, value: BigUint) { self.sum().update(|sum| *sum += value); } diff --git a/contracts/examples/adder/wasm/src/lib.rs b/contracts/examples/adder/wasm/src/lib.rs index 19ea33c7e1..f61318cdc4 100644 --- a/contracts/examples/adder/wasm/src/lib.rs +++ b/contracts/examples/adder/wasm/src/lib.rs @@ -20,8 +20,8 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - getSum => sum - add => add + getSum___view => sum + add___view => add ) } diff --git a/framework/derive/src/parse/attributes/endpoint_attr.rs b/framework/derive/src/parse/attributes/endpoint_attr.rs index 678675b202..4b742f5116 100644 --- a/framework/derive/src/parse/attributes/endpoint_attr.rs +++ b/framework/derive/src/parse/attributes/endpoint_attr.rs @@ -57,7 +57,7 @@ pub struct ViewAttribute { pub view_name: Option, } -impl ViewAttribute { +impl ViewAttribute { pub fn parse(attr: &syn::Attribute) -> Option { match is_attr_with_one_opt_token_tree_arg(attr, ATTR_VIEW) { None => None, diff --git a/framework/derive/src/parse/endpoint_parse.rs b/framework/derive/src/parse/endpoint_parse.rs index 5edc30ad08..1262e47571 100644 --- a/framework/derive/src/parse/endpoint_parse.rs +++ b/framework/derive/src/parse/endpoint_parse.rs @@ -133,8 +133,12 @@ pub fn process_view_attribute( .map(|view_attribute| { check_single_role(&*method); let view_ident = match view_attribute.view_name { - Some(ident) => ident, - None => method.name.clone(), + Some(ident) => { + format_ident!("{}___view", ident) + }, + None => { + format_ident!("{}___view", method.name.clone()) + }, }; method.public_role = PublicRole::Endpoint(EndpointMetadata { public_name: view_ident, diff --git a/framework/meta-lib/src/contract/sc_config/wasm_build.rs b/framework/meta-lib/src/contract/sc_config/wasm_build.rs index 5b318da9a0..49ac6bb2d7 100644 --- a/framework/meta-lib/src/contract/sc_config/wasm_build.rs +++ b/framework/meta-lib/src/contract/sc_config/wasm_build.rs @@ -93,6 +93,11 @@ impl ContractVariant { print_pack_mxsc_file(&output_mxsc_path); print_contract_size(compiled_bytes.len()); let mut abi = ContractAbiJson::from(&self.abi); + for endpoint in &abi.endpoints { + if endpoint.name.contains("__view") { + println!("analyze this via wasm"); + } + } let build_info = core::mem::take(&mut abi.build_info).unwrap(); let ei_check_json = EiCheckJson::new(&self.settings.check_ei, wasm_info.ei_check); let report = ReportInfoJson::new(&wasm_info, ei_check_json, compiled_bytes.len()); diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index 50d5b78aff..4c0d171ac8 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -1,7 +1,9 @@ use colored::Colorize; -use std::fs; +use semver::Op; +use std::{collections::HashMap, fs}; use wasmparser::{ - BinaryReaderError, DataSectionReader, FunctionBody, ImportSectionReader, Parser, Payload, + BinaryReaderError, DataSectionReader, ExportSectionReader, FunctionBody, ImportSectionReader, + Operator, Parser, Payload, }; use crate::ei::EIVersion; @@ -12,6 +14,12 @@ const PANIC_WITH_MESSAGE: &[u8; 16] = b"panic occurred: "; const PANIC_WITHOUT_MESSAGE: &[u8; 14] = b"panic occurred"; const ERROR_FAIL_ALLOCATOR: &[u8; 27] = b"memory allocation forbidden"; const MEMORY_GROW_OPCODE: u8 = 0x40; +const WRITE_OP: [&str; 1] = [ + // "mBufferAppend", + // "mBufferAppendBytes", + // "mBufferSetBytes", + "mBufferStorageStore", +]; pub struct WasmInfo { pub imports: Vec, @@ -50,12 +58,15 @@ fn populate_wasm_info( let mut ei_check = false; let mut memory_grow_flag = false; let mut has_panic = "none"; + let mut function_names: HashMap = HashMap::new(); + let mut read_functions: Vec = Vec::new(); - let parser = Parser::new(0); + let mut parser = Parser::new(0); for payload in parser.parse_all(&wasm_data) { match payload? { Payload::ImportSection(import_section) => { - imports = extract_imports(import_section, extract_imports_enabled); + imports = + extract_imports(import_section, extract_imports_enabled, &mut read_functions); ei_check = is_ei_valid(imports.clone(), check_ei); }, Payload::DataSection(data_section) => { @@ -67,12 +78,38 @@ fn populate_wasm_info( } }, Payload::CodeSectionEntry(code_section) => { - memory_grow_flag = is_mem_grow(code_section); + memory_grow_flag = is_mem_grow(code_section.clone()); + }, + Payload::ExportSection(export_section) => { + parse_export_section(export_section, &mut function_names); + // println!("{:#?}", function_names); }, _ => (), } } + parser = Parser::new(0); + for payload in parser.parse_all(&wasm_data) { + if let Payload::CodeSectionEntry(body) = payload? { + analyze_function_body(body, &mut read_functions); + } + } + + // println!("{:#?}", read_functions); + for (index, name) in function_names { + let i: usize = index.try_into().unwrap(); + if !read_functions[i] { + println!( + "{} >> {}", + "Write storage in VIEW endpoint entitled " + .to_string() + .red() + .bold(), + name.red().bold() + ); + } + } + let report = ReportCreator { path, has_allocator: allocator_trigger, @@ -88,6 +125,63 @@ fn populate_wasm_info( }) } +fn parse_export_section( + export_section: ExportSectionReader, + function_names: &mut HashMap, +) { + for export in export_section { + let export = export.expect("Failed to read export section"); + if let wasmparser::ExternalKind::Func = export.kind { + if export.name.to_string().ends_with("__view") { + function_names.insert(export.index, export.name.to_string()); + } + } + } +} + +fn analyze_function_body(body: FunctionBody, functions: &mut Vec) { + // Implement your function body analysis here + // For example, you can parse the locals and instructions + // let locals_reader = body + // .get_locals_reader() + // .expect("Failed to get locals reader"); + let mut instructions_reader = body + .get_operators_reader() + .expect("Failed to get operators reader"); + + // println!("Function has {} locals", locals_reader.get_count()); + + let mut value = true; + while let Ok(op) = instructions_reader.read() { + match op { + Operator::Call { function_index } => { + let function_usize: usize = function_index.try_into().unwrap(); + if function_usize >= functions.len() { + functions.push(true); + return; + } + + value &= functions[function_usize]; + + if !value { + functions.push(value); + return; + } + }, + Operator::I32Load { memarg } => { + if memarg.offset > 0 { + functions.push(false); + return; + } + }, + _ => (), + } + } + + functions.push(value); + // println!("===================="); +} + fn is_fail_allocator_triggered(data_section: DataSectionReader) -> bool { for data_fragment in data_section.into_iter().flatten() { if data_fragment @@ -140,6 +234,7 @@ fn is_panic_without_message_triggered(data_section: DataSectionReader) -> bool { pub fn extract_imports( import_section: ImportSectionReader, import_extraction_enabled: bool, + write_or_read_functions: &mut Vec, ) -> Vec { if !import_extraction_enabled { return Vec::new(); @@ -148,6 +243,11 @@ pub fn extract_imports( let mut import_names = Vec::new(); for import in import_section.into_iter().flatten() { import_names.push(import.name.to_string()); + if WRITE_OP.contains(&import.name) { + write_or_read_functions.push(false); + } else { + write_or_read_functions.push(true); + } } import_names.sort(); From a71bd3e625df61364f00a1d6984c3fd182de6224 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Thu, 20 Jun 2024 15:56:17 +0300 Subject: [PATCH 03/12] remove alter of the view endpoint name --- contracts/examples/adder/src/adder.rs | 22 ------------- contracts/examples/adder/wasm/src/lib.rs | 4 +-- framework/derive/src/parse/endpoint_parse.rs | 8 ++--- .../src/contract/sc_config/wasm_build.rs | 32 ++++++++++++++++--- .../meta-lib/src/tools/wasm_extractor.rs | 22 ++++++------- 5 files changed, 40 insertions(+), 48 deletions(-) diff --git a/contracts/examples/adder/src/adder.rs b/contracts/examples/adder/src/adder.rs index 18426a514f..77358e4b7b 100644 --- a/contracts/examples/adder/src/adder.rs +++ b/contracts/examples/adder/src/adder.rs @@ -1,25 +1,3 @@ -// 0 true, -// 1 true, -// 2 true, -// 3 true, -// 4 false, -// 5 true, -// 6 true, -// 7 true, -// 8 true, -// 9 true, -//10 true, -//11 true, -//12 true, -//13 true, -//14 false, -//15 true, -//16 true, -//17 false, -//18 true, -//19 false, -//20 true, - #![no_std] use multiversx_sc::imports::*; diff --git a/contracts/examples/adder/wasm/src/lib.rs b/contracts/examples/adder/wasm/src/lib.rs index f61318cdc4..19ea33c7e1 100644 --- a/contracts/examples/adder/wasm/src/lib.rs +++ b/contracts/examples/adder/wasm/src/lib.rs @@ -20,8 +20,8 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade - getSum___view => sum - add___view => add + getSum => sum + add => add ) } diff --git a/framework/derive/src/parse/endpoint_parse.rs b/framework/derive/src/parse/endpoint_parse.rs index 1262e47571..5edc30ad08 100644 --- a/framework/derive/src/parse/endpoint_parse.rs +++ b/framework/derive/src/parse/endpoint_parse.rs @@ -133,12 +133,8 @@ pub fn process_view_attribute( .map(|view_attribute| { check_single_role(&*method); let view_ident = match view_attribute.view_name { - Some(ident) => { - format_ident!("{}___view", ident) - }, - None => { - format_ident!("{}___view", method.name.clone()) - }, + Some(ident) => ident, + None => method.name.clone(), }; method.public_role = PublicRole::Endpoint(EndpointMetadata { public_name: view_ident, diff --git a/framework/meta-lib/src/contract/sc_config/wasm_build.rs b/framework/meta-lib/src/contract/sc_config/wasm_build.rs index 49ac6bb2d7..e7a9bec5ed 100644 --- a/framework/meta-lib/src/contract/sc_config/wasm_build.rs +++ b/framework/meta-lib/src/contract/sc_config/wasm_build.rs @@ -93,9 +93,14 @@ impl ContractVariant { print_pack_mxsc_file(&output_mxsc_path); print_contract_size(compiled_bytes.len()); let mut abi = ContractAbiJson::from(&self.abi); + let mut view_endpoints = Vec::new(); for endpoint in &abi.endpoints { - if endpoint.name.contains("__view") { - println!("analyze this via wasm"); + match endpoint.mutability { + crate::abi_json::EndpointMutabilityAbiJson::Readonly => { + view_endpoints.push(&endpoint.name) + }, + crate::abi_json::EndpointMutabilityAbiJson::Mutable => (), + crate::abi_json::EndpointMutabilityAbiJson::Pure => (), } } let build_info = core::mem::take(&mut abi.build_info).unwrap(); @@ -135,11 +140,24 @@ impl ContractVariant { fn extract_wasm_info(&self, build_args: &BuildArgs, output_path: &str) -> WasmInfo { let output_wasm_path = format!("{output_path}/{}", self.wasm_output_name(build_args)); + let abi = ContractAbiJson::from(&self.abi); + let mut view_endpoints = Vec::new(); + for endpoint in &abi.endpoints { + match endpoint.mutability { + crate::abi_json::EndpointMutabilityAbiJson::Readonly => { + view_endpoints.push(endpoint.name.clone()) + }, + crate::abi_json::EndpointMutabilityAbiJson::Mutable => (), + crate::abi_json::EndpointMutabilityAbiJson::Pure => (), + } + } + if !build_args.extract_imports { return WasmInfo::extract_wasm_info( &output_wasm_path, build_args.extract_imports, &self.settings.check_ei, + view_endpoints, ) .expect("error occured while extracting imports from .wasm "); } @@ -151,9 +169,13 @@ impl ContractVariant { ); print_extract_imports(&output_imports_json_path); - let wasm_data = - WasmInfo::extract_wasm_info(&output_wasm_path, true, &self.settings.check_ei) - .expect("error occured while extracting imports from .wasm "); + let wasm_data = WasmInfo::extract_wasm_info( + &output_wasm_path, + true, + &self.settings.check_ei, + view_endpoints, + ) + .expect("error occured while extracting imports from .wasm "); write_imports_output( output_imports_json_path.as_str(), diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index 4c0d171ac8..fa466440da 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -1,5 +1,4 @@ use colored::Colorize; -use semver::Op; use std::{collections::HashMap, fs}; use wasmparser::{ BinaryReaderError, DataSectionReader, ExportSectionReader, FunctionBody, ImportSectionReader, @@ -14,12 +13,7 @@ const PANIC_WITH_MESSAGE: &[u8; 16] = b"panic occurred: "; const PANIC_WITHOUT_MESSAGE: &[u8; 14] = b"panic occurred"; const ERROR_FAIL_ALLOCATOR: &[u8; 27] = b"memory allocation forbidden"; const MEMORY_GROW_OPCODE: u8 = 0x40; -const WRITE_OP: [&str; 1] = [ - // "mBufferAppend", - // "mBufferAppendBytes", - // "mBufferSetBytes", - "mBufferStorageStore", -]; +const WRITE_OP: [&str; 1] = ["mBufferStorageStore"]; pub struct WasmInfo { pub imports: Vec, @@ -34,6 +28,7 @@ impl WasmInfo { output_wasm_path: &str, extract_imports_enabled: bool, check_ei: &Option, + view_endpoints: Vec, ) -> Result { let wasm_data = fs::read(output_wasm_path) .expect("error occured while extracting information from .wasm: file not found"); @@ -43,6 +38,7 @@ impl WasmInfo { wasm_data, extract_imports_enabled, check_ei, + view_endpoints, ) } } @@ -52,6 +48,7 @@ fn populate_wasm_info( wasm_data: Vec, extract_imports_enabled: bool, check_ei: &Option, + view_endpoints: Vec, ) -> Result { let mut imports = Vec::new(); let mut allocator_trigger = false; @@ -81,8 +78,7 @@ fn populate_wasm_info( memory_grow_flag = is_mem_grow(code_section.clone()); }, Payload::ExportSection(export_section) => { - parse_export_section(export_section, &mut function_names); - // println!("{:#?}", function_names); + parse_export_section(export_section, &mut function_names, view_endpoints.clone()); }, _ => (), } @@ -95,13 +91,12 @@ fn populate_wasm_info( } } - // println!("{:#?}", read_functions); for (index, name) in function_names { let i: usize = index.try_into().unwrap(); if !read_functions[i] { println!( - "{} >> {}", - "Write storage in VIEW endpoint entitled " + "{} {}", + "Write storage operation in VIEW endpoint:" .to_string() .red() .bold(), @@ -128,11 +123,12 @@ fn populate_wasm_info( fn parse_export_section( export_section: ExportSectionReader, function_names: &mut HashMap, + view_endpoints: Vec, ) { for export in export_section { let export = export.expect("Failed to read export section"); if let wasmparser::ExternalKind::Func = export.kind { - if export.name.to_string().ends_with("__view") { + if view_endpoints.contains(&export.name.to_string()) { function_names.insert(export.index, export.name.to_string()); } } From 22ea5901960d2c0905476aed63aac42fb211cc90 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Thu, 29 Aug 2024 21:08:08 +0300 Subject: [PATCH 04/12] write op detect - revert contracts --- .../benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs | 6 +++--- contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs | 4 ++-- contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs | 4 ++-- contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs index 9e22454e98..1e79aa533a 100644 --- a/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/linked-list-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench___view => bench - add_struct___view => add_struct + bench => bench + add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct___view => bench_struct + bench_struct => bench_struct ) } diff --git a/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs index c254f43e57..887fb0c6e6 100644 --- a/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/queue-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench___view => bench + bench => bench add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct___view => bench_struct + bench_struct => bench_struct ) } diff --git a/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs index 79d7ac9f8a..7a1a61db74 100644 --- a/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/set-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench___view => bench + bench => bench add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct___view => bench_struct + bench_struct => bench_struct ) } diff --git a/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs b/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs index 4a56536d8a..6f915470d8 100644 --- a/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs +++ b/contracts/benchmarks/mappers/vec-repeat/wasm/src/lib.rs @@ -21,11 +21,11 @@ multiversx_sc_wasm_adapter::endpoints! { add => add count => count remove => remove - bench___view => bench + bench => bench add_struct => add_struct count_struct => count_struct remove_struct => remove_struct - bench_struct___view => bench_struct + bench_struct => bench_struct ) } From 7515c2f308ccf218e76ca0d302c4560bbd3c24cb Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 10 Sep 2024 18:47:50 +0300 Subject: [PATCH 05/12] detect write in storage in view endpoint --- .../meta-lib/src/tools/wasm_extractor.rs | 123 ++++++++++-------- 1 file changed, 69 insertions(+), 54 deletions(-) diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index fa466440da..a348a40e30 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -1,5 +1,8 @@ use colored::Colorize; -use std::{collections::HashMap, fs}; +use std::{ + collections::{HashMap, HashSet}, + fs, +}; use wasmparser::{ BinaryReaderError, DataSectionReader, ExportSectionReader, FunctionBody, ImportSectionReader, Operator, Parser, Payload, @@ -55,19 +58,24 @@ fn populate_wasm_info( let mut ei_check = false; let mut memory_grow_flag = false; let mut has_panic = "none"; - let mut function_names: HashMap = HashMap::new(); - let mut read_functions: Vec = Vec::new(); + let mut call_graph: HashMap> = HashMap::new(); + let mut views_data: HashMap = HashMap::new(); + let mut write_functions: Vec = Vec::new(); let mut parser = Parser::new(0); for payload in parser.parse_all(&wasm_data) { match payload? { Payload::ImportSection(import_section) => { - imports = - extract_imports(import_section, extract_imports_enabled, &mut read_functions); - ei_check = is_ei_valid(imports.clone(), check_ei); + imports = extract_imports( + import_section, + extract_imports_enabled, + &mut call_graph, + &mut write_functions, + ); + ei_check = is_ei_valid(&imports, check_ei); }, Payload::DataSection(data_section) => { - allocator_trigger = is_fail_allocator_triggered(data_section.clone()); + allocator_trigger = is_fail_allocator_triggered(&data_section); if is_panic_with_message_triggered(data_section.clone()) { has_panic = WITH_MESSAGE; } else if is_panic_without_message_triggered(data_section) { @@ -75,10 +83,10 @@ fn populate_wasm_info( } }, Payload::CodeSectionEntry(code_section) => { - memory_grow_flag = is_mem_grow(code_section.clone()); + memory_grow_flag = is_mem_grow(&code_section); }, Payload::ExportSection(export_section) => { - parse_export_section(export_section, &mut function_names, view_endpoints.clone()); + views_data = parse_export_section(export_section, &view_endpoints); }, _ => (), } @@ -87,13 +95,16 @@ fn populate_wasm_info( parser = Parser::new(0); for payload in parser.parse_all(&wasm_data) { if let Payload::CodeSectionEntry(body) = payload? { - analyze_function_body(body, &mut read_functions); + create_call_graph(body, &mut call_graph); } } + let mut visited: HashSet = HashSet::new(); + for (index, _name) in &views_data { + mark_write(*index, &call_graph, &mut write_functions, &mut visited); + } - for (index, name) in function_names { - let i: usize = index.try_into().unwrap(); - if !read_functions[i] { + for (index, name) in views_data { + if write_functions.contains(&index) { println!( "{} {}", "Write storage operation in VIEW endpoint:" @@ -122,64 +133,68 @@ fn populate_wasm_info( fn parse_export_section( export_section: ExportSectionReader, - function_names: &mut HashMap, - view_endpoints: Vec, -) { + view_endpoints: &Vec, +) -> HashMap { + let mut views_data: HashMap = HashMap::new(); for export in export_section { let export = export.expect("Failed to read export section"); if let wasmparser::ExternalKind::Func = export.kind { if view_endpoints.contains(&export.name.to_string()) { - function_names.insert(export.index, export.name.to_string()); + views_data.insert(export.index.try_into().unwrap(), export.name.to_string()); + } + } + } + views_data +} + +fn mark_write( + func: usize, + call_graph: &HashMap>, + write_functions: &mut Vec, + visited: &mut HashSet, +) { + // Return early to prevent cycles. + if visited.contains(&func) { + return; + } + + visited.insert(func); + + if let Some(callees) = call_graph.get(&func) { + for &callee in callees { + if write_functions.contains(&callee) { + write_functions.push(func); + } else { + mark_write(callee, call_graph, write_functions, visited); + if write_functions.contains(&callee) { + write_functions.push(func); + } } } } } -fn analyze_function_body(body: FunctionBody, functions: &mut Vec) { - // Implement your function body analysis here - // For example, you can parse the locals and instructions - // let locals_reader = body - // .get_locals_reader() - // .expect("Failed to get locals reader"); +fn create_call_graph(body: FunctionBody, call_graph: &mut HashMap>) { let mut instructions_reader = body .get_operators_reader() .expect("Failed to get operators reader"); - // println!("Function has {} locals", locals_reader.get_count()); - - let mut value = true; + let mut call_functions = Vec::new(); while let Ok(op) = instructions_reader.read() { match op { Operator::Call { function_index } => { let function_usize: usize = function_index.try_into().unwrap(); - if function_usize >= functions.len() { - functions.push(true); - return; - } - - value &= functions[function_usize]; - - if !value { - functions.push(value); - return; - } - }, - Operator::I32Load { memarg } => { - if memarg.offset > 0 { - functions.push(false); - return; - } + call_functions.push(function_usize); }, _ => (), } } - functions.push(value); - // println!("===================="); + call_graph.insert(call_graph.len(), call_functions); } -fn is_fail_allocator_triggered(data_section: DataSectionReader) -> bool { - for data_fragment in data_section.into_iter().flatten() { +fn is_fail_allocator_triggered(data_section: &DataSectionReader) -> bool { + for data_fragment in data_section.clone().into_iter().flatten() { if data_fragment .data .windows(ERROR_FAIL_ALLOCATOR.len()) @@ -230,19 +245,19 @@ fn is_panic_without_message_triggered(data_section: DataSectionReader) -> bool { pub fn extract_imports( import_section: ImportSectionReader, import_extraction_enabled: bool, - write_or_read_functions: &mut Vec, + call_graph: &mut HashMap>, + write_functions: &mut Vec, ) -> Vec { if !import_extraction_enabled { return Vec::new(); } let mut import_names = Vec::new(); - for import in import_section.into_iter().flatten() { + for (index, import) in import_section.into_iter().flatten().enumerate() { import_names.push(import.name.to_string()); + call_graph.insert(index, vec![]); if WRITE_OP.contains(&import.name) { - write_or_read_functions.push(false); - } else { - write_or_read_functions.push(true); + write_functions.push(index); } } @@ -251,7 +266,7 @@ pub fn extract_imports( import_names } -fn is_ei_valid(imports: Vec, check_ei: &Option) -> bool { +fn is_ei_valid(imports: &Vec, check_ei: &Option) -> bool { if let Some(ei) = check_ei { let mut num_errors = 0; for import in imports { @@ -268,7 +283,7 @@ fn is_ei_valid(imports: Vec, check_ei: &Option) -> bool { false } -fn is_mem_grow(code_section: FunctionBody) -> bool { +fn is_mem_grow(code_section: &FunctionBody) -> bool { let mut code = code_section.get_binary_reader(); while code.bytes_remaining() > 0 { if code.read_u8().unwrap() == MEMORY_GROW_OPCODE { From e166376c5d1bf468e69c36b49261fe4f26173525 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Thu, 12 Sep 2024 18:39:05 +0300 Subject: [PATCH 06/12] detect write op in view storage - cleanup --- .../mappers/linked-list-repeat/file.txt | 2150 ----------------- .../src/linked_list_repeat.rs | 6 +- contracts/examples/adder/src/adder.rs | 2 +- .../src/parse/attributes/endpoint_attr.rs | 2 +- 4 files changed, 4 insertions(+), 2156 deletions(-) delete mode 100644 contracts/benchmarks/mappers/linked-list-repeat/file.txt diff --git a/contracts/benchmarks/mappers/linked-list-repeat/file.txt b/contracts/benchmarks/mappers/linked-list-repeat/file.txt deleted file mode 100644 index 799122fd71..0000000000 --- a/contracts/benchmarks/mappers/linked-list-repeat/file.txt +++ /dev/null @@ -1,2150 +0,0 @@ - /home/bibi/Desktop/mx-sdk-rs/contracts/benchmarks/mappers/linked-list-repeat - -Found 1 contract crates. - -(1/1) -In /home/bibi/Desktop/mx-sdk-rs/contracts/benchmarks/mappers/linked-list-repeat/meta -Calling `cargo run build` -Using workspace target directory: /home/bibi/Desktop/mx-sdk-rs/target ... -Building linked-list-repeat.wasm in /home/bibi/Desktop/mx-sdk-rs/contracts/benchmarks/mappers/linked-list-repeat/wasm ... -RUSTFLAGS="-C link-arg=-s -C link-arg=-zstack-size=131072" cargo build --target=wasm32-unknown-unknown --release --target-dir /home/bibi/Desktop/mx-sdk-rs/target -Copying /home/bibi/Desktop/mx-sdk-rs/target/wasm32-unknown-unknown/release/linked_list_repeat_wasm.wasm to ../output/linked-list-repeat.wasm ... -Calling wasm-opt on ../output/linked-list-repeat.wasm ... -Extracting imports to ../output/linked-list-repeat.imports.json ... -FailAllocator used while memory allocation is accessible in code. Contract may fail unexpectedly when memory allocation is attempted -Instruction: Call { function_index: 24 } -Call instruction: calls function index 24 -Instruction: I32Const { value: 131268 } -Instruction: I32Const { value: 131268 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: I32Const { value: 1 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: End -Instruction: Call { function_index: 2 } -Call instruction: calls function index 2 -Instruction: LocalTee { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 3 } -Call instruction: calls function index 3 -Instruction: Drop -Instruction: LocalGet { local_index: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 4 } -Call instruction: calls function index 4 -Instruction: I32Const { value: 0 } -Instruction: I32GtS -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 96 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Eqz -Instruction: If { blockty: Type(I64) } -Instruction: I64Const { value: 0 } -Instruction: Else -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: Call { function_index: 28 } -Call instruction: calls function index 28 -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: Call { function_index: 25 } -Call instruction: calls function index 25 -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } -Instruction: Call { function_index: 23 } -Call instruction: calls function index 23 -Instruction: LocalSet { local_index: 3 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } -Instruction: Call { function_index: 25 } -Call instruction: calls function index 25 -Instruction: LocalSet { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } -Instruction: LocalSet { local_index: 6 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } -Instruction: Call { function_index: 23 } -Call instruction: calls function index 23 -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 5 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 6 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 3 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 66 } -Call instruction: calls function index 66 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: If { blockty: Type(I32) } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: Call { function_index: 25 } -Call instruction: calls function index 25 -Instruction: LocalSet { local_index: 3 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: LocalTee { local_index: 6 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalSet { local_index: 7 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalTee { local_index: 8 } -Instruction: Call { function_index: 31 } -Call instruction: calls function index 31 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 3 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 66 } -Call instruction: calls function index 66 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 33 } -Call instruction: calls function index 33 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 1 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: I32Const { value: 4 } -Instruction: Call { function_index: 47 } -Call instruction: calls function index 47 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 24 } -Call instruction: calls function index 24 -Instruction: LocalTee { local_index: 0 } -Instruction: Call { function_index: 17 } -Call instruction: calls function index 17 -Instruction: Drop -Instruction: LocalGet { local_index: 0 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 36 } -Call instruction: calls function index 36 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 1 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: Call { function_index: 24 } -Call instruction: calls function index 24 -Instruction: LocalTee { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 5 } -Call instruction: calls function index 5 -Instruction: Drop -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 38 } -Call instruction: calls function index 38 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 7 } -Call instruction: calls function index 7 -Instruction: LocalTee { local_index: 3 } -Instruction: I32Const { value: 24 } -Instruction: I32Shl -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: I32Const { value: 8 } -Instruction: I32Shl -Instruction: I32Or -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 8 } -Instruction: I32ShrU -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 24 } -Instruction: I32ShrU -Instruction: I32Or -Instruction: I32Or -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: I32Const { value: 4 } -Instruction: Call { function_index: 73 } -Call instruction: calls function index 73 -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 24 } -Call instruction: calls function index 24 -Instruction: LocalTee { local_index: 1 } -Instruction: Call { function_index: 6 } -Call instruction: calls function index 6 -Instruction: Drop -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 7 } -Call instruction: calls function index 7 -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 0 } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 24 } -Call instruction: calls function index 24 -Instruction: LocalTee { local_index: 0 } -Instruction: Call { function_index: 8 } -Call instruction: calls function index 8 -Instruction: Drop -Instruction: LocalGet { local_index: 0 } -Instruction: End -Instruction: I32Const { value: 131086 } -Instruction: I32Const { value: 23 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: Call { function_index: 24 } -Call instruction: calls function index 24 -Instruction: LocalTee { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 16 } -Call instruction: calls function index 16 -Instruction: Drop -Instruction: LocalGet { local_index: 2 } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 40 } -Call instruction: calls function index 40 -Instruction: LocalTee { local_index: 3 } -Instruction: Call { function_index: 7 } -Call instruction: calls function index 7 -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 0 } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 28, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: LocalTee { local_index: 3 } -Instruction: Call { function_index: 33 } -Call instruction: calls function index 33 -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 44 } -Call instruction: calls function index 44 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I64Const { value: 0 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: I32Const { value: 8 } -Instruction: Call { function_index: 47 } -Call instruction: calls function index 47 -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 11 } -Call instruction: calls function index 11 -Instruction: LocalTee { local_index: 0 } -Instruction: I64Const { value: 4294967296 } -Instruction: I64GeU -Instruction: If { blockty: Empty } -Instruction: I32Const { value: 131189 } -Instruction: I32Const { value: 11 } -Instruction: I32Const { value: 131072 } -Instruction: I32Const { value: 14 } -Instruction: Call { function_index: 41 } -Call instruction: calls function index 41 -Instruction: Unreachable -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32WrapI64 -Instruction: End -Instruction: Call { function_index: 12 } -Call instruction: calls function index 12 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Eq -Instruction: If { blockty: Empty } -Instruction: Return -Instruction: End -Instruction: I32Const { value: 131112 } -Instruction: I32Const { value: 25 } -Instruction: Call { function_index: 13 } -Call instruction: calls function index 13 -Instruction: Unreachable -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 53 } -Call instruction: calls function index 53 -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 2 } -Call instruction: calls function index 2 -Instruction: LocalTee { local_index: 1 } -Instruction: Call { function_index: 18 } -Call instruction: calls function index 18 -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Eqz -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 1 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: I32Const { value: 4 } -Instruction: Call { function_index: 74 } -Call instruction: calls function index 74 -Instruction: I32Const { value: 131162 } -Instruction: I32Const { value: 22 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: LocalTee { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 9 } -Call instruction: calls function index 9 -Instruction: Drop -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 10 } -Call instruction: calls function index 10 -Instruction: Unreachable -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 14 } -Call instruction: calls function index 14 -Instruction: I32Eqz -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 15 } -Call instruction: calls function index 15 -Instruction: I32Const { value: 0 } -Instruction: I32Ne -Instruction: End -Instruction: Block { blockty: Empty } -Instruction: Block { blockty: Empty } -Instruction: Block { blockty: Type(I32) } -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 8, memory: 0 } } -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalTee { local_index: 4 } -Instruction: Call { function_index: 7 } -Call instruction: calls function index 7 -Instruction: LocalTee { local_index: 5 } -Instruction: I32Const { value: 10000 } -Instruction: I32GtU -Instruction: BrIf { relative_depth: 1 } -Instruction: I32Const { value: 141276 } -Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: BrIf { relative_depth: 1 } -Instruction: I32Const { value: 141272 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: I32Const { value: 141276 } -Instruction: I32Const { value: 1 } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Const { value: 0 } -Instruction: I32Const { value: 131272 } -Instruction: LocalGet { local_index: 5 } -Instruction: Call { function_index: 52 } -Call instruction: calls function index 52 -Instruction: Drop -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 1 } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 8, memory: 0 } } -Instruction: End -Instruction: I32Const { value: 1 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Add -Instruction: LocalTee { local_index: 0 } -Instruction: I32Const { value: 141272 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: I32GtU -Instruction: BrIf { relative_depth: 1 } -Instruction: Drop -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32LtU -Instruction: BrIf { relative_depth: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 10000 } -Instruction: I32GtU -Instruction: BrIf { relative_depth: 3 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 131272 } -Instruction: I32Add -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 89 } -Call instruction: calls function index 89 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: -25 } -Instruction: Call { function_index: 6 } -Call instruction: calls function index 6 -Instruction: Drop -Instruction: I32Const { value: -25 } -Instruction: Call { function_index: 7 } -Call instruction: calls function index 7 -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 56 } -Call instruction: calls function index 56 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: Call { function_index: 19 } -Call instruction: calls function index 19 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 58 } -Call instruction: calls function index 58 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 25 } -Call instruction: calls function index 25 -Instruction: LocalTee { local_index: 0 } -Instruction: I32Const { value: 131157 } -Instruction: I32Const { value: 5 } -Instruction: Call { function_index: 9 } -Call instruction: calls function index 9 -Instruction: Drop -Instruction: LocalGet { local_index: 0 } -Instruction: End -Instruction: I32Const { value: 131224 } -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 24 } -Instruction: I32Shl -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: I32Const { value: 8 } -Instruction: I32Shl -Instruction: I32Or -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32ShrU -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 24 } -Instruction: I32ShrU -Instruction: I32Or -Instruction: I32Or -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: I32Const { value: 4 } -Instruction: Call { function_index: 73 } -Call instruction: calls function index 73 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 19 } -Call instruction: calls function index 19 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 25 } -Call instruction: calls function index 25 -Instruction: LocalTee { local_index: 0 } -Instruction: I32Const { value: 131152 } -Instruction: I32Const { value: 5 } -Instruction: Call { function_index: 9 } -Call instruction: calls function index 9 -Instruction: Drop -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 24 } -Instruction: I32Shl -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: I32Const { value: 8 } -Instruction: I32Shl -Instruction: I32Or -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 8 } -Instruction: I32ShrU -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 24 } -Instruction: I32ShrU -Instruction: I32Or -Instruction: I32Or -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: I32Const { value: 4 } -Instruction: Call { function_index: 9 } -Call instruction: calls function index 9 -Instruction: Drop -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: Call { function_index: 59 } -Call instruction: calls function index 59 -Instruction: LocalSet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 38 } -Call instruction: calls function index 38 -Instruction: LocalGet { local_index: 2 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 65 } -Call instruction: calls function index 65 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 56 } -Instruction: I64Shl -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 65280 } -Instruction: I64And -Instruction: I64Const { value: 40 } -Instruction: I64Shl -Instruction: I64Or -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 16711680 } -Instruction: I64And -Instruction: I64Const { value: 24 } -Instruction: I64Shl -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 4278190080 } -Instruction: I64And -Instruction: I64Const { value: 8 } -Instruction: I64Shl -Instruction: I64Or -Instruction: I64Or -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 8 } -Instruction: I64ShrU -Instruction: I64Const { value: 4278190080 } -Instruction: I64And -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 24 } -Instruction: I64ShrU -Instruction: I64Const { value: 16711680 } -Instruction: I64And -Instruction: I64Or -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 40 } -Instruction: I64ShrU -Instruction: I64Const { value: 65280 } -Instruction: I64And -Instruction: LocalGet { local_index: 0 } -Instruction: I64Const { value: 56 } -Instruction: I64ShrU -Instruction: I64Or -Instruction: I64Or -Instruction: I64Or -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: I32Const { value: 8 } -Instruction: Call { function_index: 73 } -Call instruction: calls function index 73 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: Call { function_index: 54 } -Call instruction: calls function index 54 -Instruction: I32Eqz -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 3 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: Call { function_index: 39 } -Call instruction: calls function index 39 -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 36 } -Call instruction: calls function index 36 -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 4 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: I32Eq -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 28, memory: 0 } } -Instruction: If { blockty: Empty } -Instruction: I32Const { value: 141272 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: I32Const { value: 141276 } -Instruction: I32Const { value: 0 } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 32 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: Return -Instruction: End -Instruction: I32Const { value: 131072 } -Instruction: I32Const { value: 14 } -Instruction: Call { function_index: 50 } -Call instruction: calls function index 50 -Instruction: Unreachable -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 3 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: Call { function_index: 39 } -Call instruction: calls function index 39 -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 36 } -Call instruction: calls function index 36 -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 72 } -Call instruction: calls function index 72 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 32 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalTee { local_index: 3 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Block { blockty: Empty } -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 58 } -Call instruction: calls function index 58 -Instruction: LocalTee { local_index: 1 } -Instruction: Call { function_index: 54 } -Call instruction: calls function index 54 -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: I32Const { value: 0 } -Instruction: LocalSet { local_index: 1 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: LocalTee { local_index: 3 } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 39 } -Call instruction: calls function index 39 -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 3 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 4 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: Call { function_index: 49 } -Call instruction: calls function index 49 -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: I32Ne -Instruction: BrIf { relative_depth: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 28, memory: 0 } } -Instruction: I32Eqz -Instruction: BrIf { relative_depth: 0 } -Instruction: I32Const { value: 141272 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: I32Const { value: 141276 } -Instruction: I32Const { value: 0 } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 32 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: Return -Instruction: End -Instruction: I32Const { value: 131072 } -Instruction: I32Const { value: 14 } -Instruction: Call { function_index: 50 } -Call instruction: calls function index 50 -Instruction: Unreachable -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 80 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: -64 } -Instruction: I32Sub -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalTee { local_index: 3 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 68, memory: 0 } } -Instruction: Call { function_index: 29 } -Call instruction: calls function index 29 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Const { value: 56 } -Instruction: Call { function_index: 89 } -Call instruction: calls function index 89 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 2 } -Instruction: GlobalSet { global_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I64Const { value: 0 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: I32Const { value: 8 } -Instruction: Call { function_index: 74 } -Call instruction: calls function index 74 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 9 } -Call instruction: calls function index 9 -Instruction: Drop -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 53 } -Call instruction: calls function index 53 -Instruction: If { blockty: Empty } -Instruction: I32Const { value: 131137 } -Instruction: I32Const { value: 15 } -Instruction: Call { function_index: 50 } -Call instruction: calls function index 50 -Instruction: Unreachable -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Add -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: End -Instruction: I32Const { value: 131200 } -Instruction: I32Const { value: 12 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: End -Instruction: I32Const { value: 131212 } -Instruction: I32Const { value: 9 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: End -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 2 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: Call { function_index: 45 } -Call instruction: calls function index 45 -Instruction: LocalSet { local_index: 6 } -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 40 } -Call instruction: calls function index 40 -Instruction: LocalSet { local_index: 7 } -Instruction: Call { function_index: 76 } -Call instruction: calls function index 76 -Instruction: LocalSet { local_index: 2 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 6 } -Instruction: I32Ne -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 7 } -Instruction: Call { function_index: 25 } -Call instruction: calls function index 25 -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 24 } -Instruction: I32Shl -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: I32Const { value: 8 } -Instruction: I32Shl -Instruction: I32Or -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 8 } -Instruction: I32ShrU -Instruction: I32Const { value: 65280 } -Instruction: I32And -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 24 } -Instruction: I32ShrU -Instruction: I32Or -Instruction: I32Or -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 5 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: I32Const { value: 4 } -Instruction: Call { function_index: 9 } -Call instruction: calls function index 9 -Instruction: Drop -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalTee { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalTee { local_index: 8 } -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: I32Const { value: 0 } -Instruction: LocalSet { local_index: 4 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: LocalTee { local_index: 9 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } -Instruction: LocalTee { local_index: 4 } -Instruction: Call { function_index: 67 } -Call instruction: calls function index 67 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 4 } -Instruction: LocalGet { local_index: 9 } -Instruction: Call { function_index: 62 } -Call instruction: calls function index 62 -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: Call { function_index: 62 } -Call instruction: calls function index 62 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 8 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 8, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 57 } -Call instruction: calls function index 57 -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: -64 } -Instruction: I32Add -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 40 } -Call instruction: calls function index 40 -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 76 } -Call instruction: calls function index 76 -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: Call { function_index: 69 } -Call instruction: calls function index 69 -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 44 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: Call { function_index: 30 } -Call instruction: calls function index 30 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 44, memory: 0 } } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 48, memory: 0 } } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 26 } -Call instruction: calls function index 26 -Instruction: LocalGet { local_index: 1 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 1 } -Instruction: I64ExtendI32U -Instruction: Call { function_index: 21 } -Call instruction: calls function index 21 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: -64 } -Instruction: I32Sub -Instruction: GlobalSet { global_index: 0 } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: -64 } -Instruction: I32Add -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: Call { function_index: 45 } -Call instruction: calls function index 45 -Instruction: LocalSet { local_index: 5 } -Instruction: Call { function_index: 76 } -Call instruction: calls function index 76 -Instruction: LocalSet { local_index: 1 } -Instruction: Block { blockty: Empty } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 5 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 12 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalTee { local_index: 2 } -Instruction: Call { function_index: 66 } -Call instruction: calls function index 66 -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 28 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 31 } -Call instruction: calls function index 31 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } -Instruction: I32Eqz -Instruction: BrIf { relative_depth: 3 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 44, memory: 0 } } -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 40, memory: 0 } } -Instruction: LocalSet { local_index: 3 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 36, memory: 0 } } -Instruction: LocalTee { local_index: 6 } -Instruction: Call { function_index: 66 } -Call instruction: calls function index 66 -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 2 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 67 } -Call instruction: calls function index 67 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 36, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 62 } -Call instruction: calls function index 62 -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 52, memory: 0 } } -Instruction: End -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 3 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 28 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 67 } -Call instruction: calls function index 67 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 40, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 62 } -Call instruction: calls function index 62 -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 56, memory: 0 } } -Instruction: End -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 6 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: Call { function_index: 55 } -Call instruction: calls function index 55 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 48, memory: 0 } } -Instruction: I32Const { value: 1 } -Instruction: I32Sub -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 48, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Add -Instruction: Call { function_index: 57 } -Call instruction: calls function index 57 -Instruction: End -Instruction: LocalGet { local_index: 5 } -Instruction: I32Const { value: 1 } -Instruction: I32Sub -Instruction: LocalSet { local_index: 5 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: -64 } -Instruction: I32Sub -Instruction: GlobalSet { global_index: 0 } -Instruction: Return -Instruction: End -Instruction: Call { function_index: 81 } -Call instruction: calls function index 81 -Instruction: Call { function_index: 88 } -Call instruction: calls function index 88 -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 76 } -Call instruction: calls function index 76 -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 69 } -Call instruction: calls function index 69 -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 28 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: Call { function_index: 30 } -Call instruction: calls function index 30 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 32, memory: 0 } } -Instruction: Call { function_index: 22 } -Call instruction: calls function index 22 -Instruction: Drop -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 128 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 2 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: Call { function_index: 45 } -Call instruction: calls function index 45 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 32 } -Instruction: I32Add -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 43 } -Call instruction: calls function index 43 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 108 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 56 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalTee { local_index: 11 } -Instruction: I64Store { memarg: MemArg { align: 2, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 40 } -Instruction: I32Add -Instruction: LocalTee { local_index: 5 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 16 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 48 } -Instruction: I32Add -Instruction: LocalTee { local_index: 6 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 24 } -Instruction: I32Add -Instruction: LocalGet { local_index: 11 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 32, memory: 0 } } -Instruction: LocalTee { local_index: 11 } -Instruction: I64Store { memarg: MemArg { align: 2, max_align: 3, offset: 84, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 11 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64ExtendI32U -Instruction: LocalSet { local_index: 12 } -Instruction: I64Const { value: 0 } -Instruction: LocalSet { local_index: 11 } -Instruction: Call { function_index: 75 } -Call instruction: calls function index 75 -Instruction: LocalSet { local_index: 1 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 11 } -Instruction: LocalGet { local_index: 12 } -Instruction: I64Eq -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 80 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 28 } -Call instruction: calls function index 28 -Instruction: LocalGet { local_index: 5 } -Instruction: LocalGet { local_index: 11 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 6 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 96 } -Instruction: I32Add -Instruction: LocalTee { local_index: 7 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 4 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 104 } -Instruction: I32Add -Instruction: LocalTee { local_index: 8 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 11 } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 32, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: -64 } -Instruction: I32Sub -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 76, memory: 0 } } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalTee { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 76, memory: 0 } } -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } -Instruction: LocalTee { local_index: 9 } -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 68, memory: 0 } } -Instruction: I32Const { value: 0 } -Instruction: LocalSet { local_index: 3 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 80 } -Instruction: I32Add -Instruction: LocalTee { local_index: 10 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 72, memory: 0 } } -Instruction: LocalTee { local_index: 3 } -Instruction: Call { function_index: 68 } -Call instruction: calls function index 68 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 116, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 10 } -Instruction: Call { function_index: 64 } -Call instruction: calls function index 64 -Instruction: End -Instruction: LocalGet { local_index: 8 } -Instruction: LocalGet { local_index: 4 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 7 } -Instruction: LocalGet { local_index: 6 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 88 } -Instruction: I32Add -Instruction: LocalGet { local_index: 5 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 32, memory: 0 } } -Instruction: I64Store { memarg: MemArg { align: 3, max_align: 3, offset: 80, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 120, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 0 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 116, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 112, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 80 } -Instruction: I32Add -Instruction: Call { function_index: 64 } -Call instruction: calls function index 64 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 9 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 72, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: -64 } -Instruction: I32Sub -Instruction: Call { function_index: 57 } -Call instruction: calls function index 57 -Instruction: LocalGet { local_index: 11 } -Instruction: I64Const { value: 1 } -Instruction: I64Add -Instruction: LocalSet { local_index: 11 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 128 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 160 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 43 } -Call instruction: calls function index 43 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 75 } -Call instruction: calls function index 75 -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 36, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 40 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 36 } -Instruction: I32Add -Instruction: Call { function_index: 71 } -Call instruction: calls function index 71 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 28, memory: 0 } } -Instruction: LocalSet { local_index: 3 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 24, memory: 0 } } -Instruction: LocalSet { local_index: 4 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 20, memory: 0 } } -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 16, memory: 0 } } -Instruction: LocalSet { local_index: 6 } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 8, memory: 0 } } -Instruction: LocalSet { local_index: 10 } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 0, memory: 0 } } -Instruction: LocalSet { local_index: 11 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 104 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 40 } -Instruction: I32Add -Instruction: Call { function_index: 27 } -Call instruction: calls function index 27 -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 104, memory: 0 } } -Instruction: I64Eqz -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 112, memory: 0 } } -Instruction: LocalSet { local_index: 12 } -Instruction: I32Const { value: 0 } -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 140, memory: 0 } } -Instruction: LocalSet { local_index: 7 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 136, memory: 0 } } -Instruction: LocalSet { local_index: 8 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 132, memory: 0 } } -Instruction: LocalSet { local_index: 9 } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 120, memory: 0 } } -Instruction: LocalSet { local_index: 13 } -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 128, memory: 0 } } -Instruction: LocalGet { local_index: 6 } -Instruction: Call { function_index: 26 } -Call instruction: calls function index 26 -Instruction: I32Eqz -Instruction: LocalGet { local_index: 11 } -Instruction: LocalGet { local_index: 12 } -Instruction: I64Ne -Instruction: I32Or -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 9 } -Instruction: LocalGet { local_index: 5 } -Instruction: Call { function_index: 51 } -Call instruction: calls function index 51 -Instruction: I32Eqz -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 8 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 26 } -Call instruction: calls function index 26 -Instruction: I32Eqz -Instruction: LocalGet { local_index: 10 } -Instruction: LocalGet { local_index: 13 } -Instruction: I64Ne -Instruction: I32Or -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 7 } -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 51 } -Call instruction: calls function index 51 -Instruction: LocalSet { local_index: 2 } -Instruction: End -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 1 } -Instruction: I64ExtendI32U -Instruction: Call { function_index: 21 } -Call instruction: calls function index 21 -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 160 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 96 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 1 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: Call { function_index: 45 } -Call instruction: calls function index 45 -Instruction: LocalSet { local_index: 5 } -Instruction: Call { function_index: 75 } -Call instruction: calls function index 75 -Instruction: LocalSet { local_index: 1 } -Instruction: Block { blockty: Empty } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 5 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 12, memory: 0 } } -Instruction: LocalTee { local_index: 2 } -Instruction: Call { function_index: 66 } -Call instruction: calls function index 66 -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 24 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 29 } -Call instruction: calls function index 29 -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 24, memory: 0 } } -Instruction: I64Eqz -Instruction: BrIf { relative_depth: 3 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 72, memory: 0 } } -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 68, memory: 0 } } -Instruction: LocalSet { local_index: 3 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } -Instruction: LocalTee { local_index: 6 } -Instruction: Call { function_index: 66 } -Call instruction: calls function index 66 -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 80 } -Instruction: I32Add -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 70 } -Call instruction: calls function index 70 -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 2 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: Call { function_index: 68 } -Call instruction: calls function index 68 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 60, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 64 } -Call instruction: calls function index 64 -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 84, memory: 0 } } -Instruction: End -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 3 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 24 } -Instruction: I32Add -Instruction: LocalTee { local_index: 4 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: Call { function_index: 68 } -Call instruction: calls function index 68 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 64, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 4 } -Instruction: Call { function_index: 64 } -Call instruction: calls function index 64 -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 88, memory: 0 } } -Instruction: End -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 6 } -Instruction: Call { function_index: 63 } -Call instruction: calls function index 63 -Instruction: Call { function_index: 55 } -Call instruction: calls function index 55 -Instruction: LocalGet { local_index: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 80, memory: 0 } } -Instruction: I32Const { value: 1 } -Instruction: I32Sub -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 80, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 80 } -Instruction: I32Add -Instruction: Call { function_index: 57 } -Call instruction: calls function index 57 -Instruction: End -Instruction: LocalGet { local_index: 5 } -Instruction: I32Const { value: 1 } -Instruction: I32Sub -Instruction: LocalSet { local_index: 5 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 96 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: Return -Instruction: End -Instruction: Call { function_index: 81 } -Call instruction: calls function index 81 -Instruction: Unreachable -Instruction: End -Instruction: GlobalGet { global_index: 0 } -Instruction: I32Const { value: 128 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 0 } -Instruction: GlobalSet { global_index: 0 } -Instruction: Call { function_index: 20 } -Call instruction: calls function index 20 -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 46 } -Call instruction: calls function index 46 -Instruction: LocalGet { local_index: 0 } -Instruction: Call { function_index: 75 } -Call instruction: calls function index 75 -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 4, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: Call { function_index: 71 } -Call instruction: calls function index 71 -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 72 } -Instruction: I32Add -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 8 } -Instruction: I32Add -Instruction: Call { function_index: 27 } -Call instruction: calls function index 27 -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 72, memory: 0 } } -Instruction: I64Eqz -Instruction: I32Eqz -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 108, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 88, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 104, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 100, memory: 0 } } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 96, memory: 0 } } -Instruction: I32Const { value: 131224 } -Instruction: I32Const { value: 0 } -Instruction: Call { function_index: 42 } -Call instruction: calls function index 42 -Instruction: LocalTee { local_index: 1 } -Instruction: Call { function_index: 38 } -Call instruction: calls function index 38 -Instruction: LocalGet { local_index: 0 } -Instruction: I64Load { memarg: MemArg { align: 3, max_align: 3, offset: 80, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 65 } -Call instruction: calls function index 65 -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 37 } -Call instruction: calls function index 37 -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 38 } -Call instruction: calls function index 38 -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 65 } -Call instruction: calls function index 65 -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 37 } -Call instruction: calls function index 37 -Instruction: LocalGet { local_index: 1 } -Instruction: Call { function_index: 22 } -Call instruction: calls function index 22 -Instruction: Drop -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 128 } -Instruction: I32Add -Instruction: GlobalSet { global_index: 0 } -Instruction: End -Instruction: End -Instruction: I32Const { value: 131224 } -Instruction: I32Const { value: 14 } -Instruction: Call { function_index: 13 } -Call instruction: calls function index 13 -Instruction: Unreachable -Instruction: End -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalTee { local_index: 4 } -Instruction: I32Const { value: 16 } -Instruction: I32LtU -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalSet { local_index: 2 } -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: I32Const { value: 0 } -Instruction: LocalGet { local_index: 0 } -Instruction: I32Sub -Instruction: I32Const { value: 3 } -Instruction: I32And -Instruction: LocalTee { local_index: 3 } -Instruction: I32Add -Instruction: LocalSet { local_index: 5 } -Instruction: LocalGet { local_index: 3 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 0 } -Instruction: LocalSet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalSet { local_index: 6 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 6 } -Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 6 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalSet { local_index: 6 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalTee { local_index: 2 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32LtU -Instruction: BrIf { relative_depth: 0 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 5 } -Instruction: LocalGet { local_index: 4 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Sub -Instruction: LocalTee { local_index: 8 } -Instruction: I32Const { value: -4 } -Instruction: I32And -Instruction: LocalTee { local_index: 7 } -Instruction: I32Add -Instruction: LocalSet { local_index: 2 } -Instruction: Block { blockty: Empty } -Instruction: LocalGet { local_index: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Add -Instruction: LocalTee { local_index: 3 } -Instruction: I32Const { value: 3 } -Instruction: I32And -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 7 } -Instruction: I32Const { value: 0 } -Instruction: I32LeS -Instruction: BrIf { relative_depth: 1 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: 3 } -Instruction: I32Shl -Instruction: LocalTee { local_index: 4 } -Instruction: I32Const { value: 24 } -Instruction: I32And -Instruction: LocalSet { local_index: 9 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32Const { value: -4 } -Instruction: I32And -Instruction: LocalTee { local_index: 6 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: I32Const { value: 0 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Sub -Instruction: I32Const { value: 24 } -Instruction: I32And -Instruction: LocalSet { local_index: 4 } -Instruction: LocalGet { local_index: 6 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalSet { local_index: 6 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 5 } -Instruction: LocalGet { local_index: 6 } -Instruction: LocalGet { local_index: 9 } -Instruction: I32ShrU -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalTee { local_index: 6 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Shl -Instruction: I32Or -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: LocalTee { local_index: 5 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32LtU -Instruction: BrIf { relative_depth: 0 } -Instruction: End -Instruction: Br { relative_depth: 1 } -Instruction: End -Instruction: LocalGet { local_index: 7 } -Instruction: I32Const { value: 0 } -Instruction: I32LeS -Instruction: BrIf { relative_depth: 0 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalSet { local_index: 1 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 5 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: I32Store { memarg: MemArg { align: 2, max_align: 2, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 5 } -Instruction: I32Const { value: 4 } -Instruction: I32Add -Instruction: LocalTee { local_index: 5 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32LtU -Instruction: BrIf { relative_depth: 0 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 8 } -Instruction: I32Const { value: 3 } -Instruction: I32And -Instruction: LocalSet { local_index: 4 } -Instruction: LocalGet { local_index: 3 } -Instruction: LocalGet { local_index: 7 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: End -Instruction: LocalGet { local_index: 4 } -Instruction: If { blockty: Empty } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 4 } -Instruction: I32Add -Instruction: LocalSet { local_index: 3 } -Instruction: Loop { blockty: Empty } -Instruction: LocalGet { local_index: 2 } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Load8U { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: I32Store8 { memarg: MemArg { align: 0, max_align: 0, offset: 0, memory: 0 } } -Instruction: LocalGet { local_index: 1 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalSet { local_index: 1 } -Instruction: LocalGet { local_index: 2 } -Instruction: I32Const { value: 1 } -Instruction: I32Add -Instruction: LocalTee { local_index: 2 } -Instruction: LocalGet { local_index: 3 } -Instruction: I32LtU -Instruction: BrIf { relative_depth: 0 } -Instruction: End -Instruction: End -Instruction: LocalGet { local_index: 0 } -Instruction: End -Checking EI version: 1.3 ... OK -Packing ../output/linked-list-repeat.mxsc.json ... -Contract size: 6615 bytes. -analyze this via wasm -analyze this via wasm diff --git a/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs b/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs index cc7d8959ff..40dfcba638 100644 --- a/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs +++ b/contracts/benchmarks/mappers/linked-list-repeat/src/linked_list_repeat.rs @@ -1,9 +1,8 @@ #![no_std] -use benchmark_common::ExampleStruct; - multiversx_sc::imports!(); +use benchmark_common::ExampleStruct; pub mod linked_list_repeat_proxy; #[multiversx_sc::contract] @@ -39,8 +38,7 @@ pub trait LinkedListRepeat: benchmark_common::BenchmarkCommon { #[storage_mapper("benchmark")] fn bench(&self) -> LinkedListMapper; - #[view] - // #[endpoint] + #[endpoint] fn add_struct(&self, num_repeats: usize, value: ExampleStruct) { let mut bench = self.bench_struct(); for i in 0..num_repeats { diff --git a/contracts/examples/adder/src/adder.rs b/contracts/examples/adder/src/adder.rs index 77358e4b7b..307f4112f5 100644 --- a/contracts/examples/adder/src/adder.rs +++ b/contracts/examples/adder/src/adder.rs @@ -23,7 +23,7 @@ pub trait Adder { } /// Add desired amount to the storage variable. - #[view] + #[endpoint] fn add(&self, value: BigUint) { self.sum().update(|sum| *sum += value); } diff --git a/framework/derive/src/parse/attributes/endpoint_attr.rs b/framework/derive/src/parse/attributes/endpoint_attr.rs index 4b742f5116..678675b202 100644 --- a/framework/derive/src/parse/attributes/endpoint_attr.rs +++ b/framework/derive/src/parse/attributes/endpoint_attr.rs @@ -57,7 +57,7 @@ pub struct ViewAttribute { pub view_name: Option, } -impl ViewAttribute { +impl ViewAttribute { pub fn parse(attr: &syn::Attribute) -> Option { match is_attr_with_one_opt_token_tree_arg(attr, ATTR_VIEW) { None => None, From 9e9bba15bf5d4aa7ec1807be56a43a8e219048ee Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Fri, 13 Sep 2024 14:20:19 +0300 Subject: [PATCH 07/12] detect write op in view storage - fix clippy --- .../meta-lib/src/tools/wasm_extractor.rs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index a348a40e30..4cd80507d4 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -75,7 +75,7 @@ fn populate_wasm_info( ei_check = is_ei_valid(&imports, check_ei); }, Payload::DataSection(data_section) => { - allocator_trigger = is_fail_allocator_triggered(&data_section); + allocator_trigger = is_fail_allocator_triggered(data_section.clone()); if is_panic_with_message_triggered(data_section.clone()) { has_panic = WITH_MESSAGE; } else if is_panic_without_message_triggered(data_section) { @@ -99,8 +99,8 @@ fn populate_wasm_info( } } let mut visited: HashSet = HashSet::new(); - for (index, _name) in &views_data { - mark_write(*index, &call_graph, &mut write_functions, &mut visited); + for key in views_data.keys() { + mark_write(*key, &call_graph, &mut write_functions, &mut visited); } for (index, name) in views_data { @@ -133,7 +133,7 @@ fn populate_wasm_info( fn parse_export_section( export_section: ExportSectionReader, - view_endpoints: &Vec, + view_endpoints: &[String], ) -> HashMap { let mut views_data: HashMap = HashMap::new(); for export in export_section { @@ -181,20 +181,17 @@ fn create_call_graph(body: FunctionBody, call_graph: &mut HashMap { - let function_usize: usize = function_index.try_into().unwrap(); - call_functions.push(function_usize); - }, - _ => (), + if let Operator::Call { function_index } = op { + let function_usize: usize = function_index.try_into().unwrap(); + call_functions.push(function_usize); } } call_graph.insert(call_graph.len(), call_functions); } -fn is_fail_allocator_triggered(data_section: &DataSectionReader) -> bool { - for data_fragment in data_section.clone().into_iter().flatten() { +fn is_fail_allocator_triggered(data_section: DataSectionReader) -> bool { + for data_fragment in data_section.into_iter().flatten() { if data_fragment .data .windows(ERROR_FAIL_ALLOCATOR.len()) @@ -266,7 +263,7 @@ pub fn extract_imports( import_names } -fn is_ei_valid(imports: &Vec, check_ei: &Option) -> bool { +fn is_ei_valid(imports: &[String], check_ei: &Option) -> bool { if let Some(ei) = check_ei { let mut num_errors = 0; for import in imports { From d145b73eba13d4b2bb095ab10ae5fcc576c054bd Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Fri, 13 Sep 2024 19:11:46 +0300 Subject: [PATCH 08/12] detect write op in view storage - refactor: removed has_format, changed data structure for view_endpoints, impl default for WasmInfo and ReportCreator --- .../src/contract/sc_config/wasm_build.rs | 20 +-- .../meta-lib/src/tools/report_creator.rs | 10 ++ .../meta-lib/src/tools/wasm_extractor.rs | 143 ++++++++---------- 3 files changed, 83 insertions(+), 90 deletions(-) diff --git a/framework/meta-lib/src/contract/sc_config/wasm_build.rs b/framework/meta-lib/src/contract/sc_config/wasm_build.rs index e7a9bec5ed..4311bd0979 100644 --- a/framework/meta-lib/src/contract/sc_config/wasm_build.rs +++ b/framework/meta-lib/src/contract/sc_config/wasm_build.rs @@ -1,4 +1,4 @@ -use std::{ffi::OsStr, fs, process::Command}; +use std::{collections::HashMap, ffi::OsStr, fs, process::Command}; use super::ContractVariant; use crate::{ @@ -95,12 +95,8 @@ impl ContractVariant { let mut abi = ContractAbiJson::from(&self.abi); let mut view_endpoints = Vec::new(); for endpoint in &abi.endpoints { - match endpoint.mutability { - crate::abi_json::EndpointMutabilityAbiJson::Readonly => { - view_endpoints.push(&endpoint.name) - }, - crate::abi_json::EndpointMutabilityAbiJson::Mutable => (), - crate::abi_json::EndpointMutabilityAbiJson::Pure => (), + if let crate::abi_json::EndpointMutabilityAbiJson::Readonly = endpoint.mutability { + view_endpoints.push(&endpoint.name) } } let build_info = core::mem::take(&mut abi.build_info).unwrap(); @@ -141,14 +137,10 @@ impl ContractVariant { let output_wasm_path = format!("{output_path}/{}", self.wasm_output_name(build_args)); let abi = ContractAbiJson::from(&self.abi); - let mut view_endpoints = Vec::new(); + let mut view_endpoints: HashMap<&str, usize> = HashMap::new(); for endpoint in &abi.endpoints { - match endpoint.mutability { - crate::abi_json::EndpointMutabilityAbiJson::Readonly => { - view_endpoints.push(endpoint.name.clone()) - }, - crate::abi_json::EndpointMutabilityAbiJson::Mutable => (), - crate::abi_json::EndpointMutabilityAbiJson::Pure => (), + if let crate::abi_json::EndpointMutabilityAbiJson::Readonly = endpoint.mutability { + view_endpoints.insert(&endpoint.name, 0); } } diff --git a/framework/meta-lib/src/tools/report_creator.rs b/framework/meta-lib/src/tools/report_creator.rs index 37af10fa4e..60de81dc31 100644 --- a/framework/meta-lib/src/tools/report_creator.rs +++ b/framework/meta-lib/src/tools/report_creator.rs @@ -8,3 +8,13 @@ pub struct ReportCreator { } impl ReportCreator {} + +impl Default for ReportCreator { + fn default() -> Self { + ReportCreator { + path: String::new(), + has_allocator: false, + has_panic: "none".to_string(), + } + } +} diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index 4cd80507d4..63dad6b3ad 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -12,18 +12,21 @@ use crate::ei::EIVersion; use super::report_creator::{ReportCreator, WITHOUT_MESSAGE, WITH_MESSAGE}; +type CallGraph = HashMap>; + const PANIC_WITH_MESSAGE: &[u8; 16] = b"panic occurred: "; const PANIC_WITHOUT_MESSAGE: &[u8; 14] = b"panic occurred"; const ERROR_FAIL_ALLOCATOR: &[u8; 27] = b"memory allocation forbidden"; const MEMORY_GROW_OPCODE: u8 = 0x40; const WRITE_OP: [&str; 1] = ["mBufferStorageStore"]; +#[derive(Default)] pub struct WasmInfo { pub imports: Vec, pub ei_check: bool, pub memory_grow_flag: bool, - pub has_format: bool, pub report: ReportCreator, + pub call_graph: CallGraph, } impl WasmInfo { @@ -31,7 +34,7 @@ impl WasmInfo { output_wasm_path: &str, extract_imports_enabled: bool, check_ei: &Option, - view_endpoints: Vec, + view_endpoints: HashMap<&str, usize>, ) -> Result { let wasm_data = fs::read(output_wasm_path) .expect("error occured while extracting information from .wasm: file not found"); @@ -51,60 +54,67 @@ fn populate_wasm_info( wasm_data: Vec, extract_imports_enabled: bool, check_ei: &Option, - view_endpoints: Vec, + mut view_endpoints: HashMap<&str, usize>, ) -> Result { - let mut imports = Vec::new(); - let mut allocator_trigger = false; - let mut ei_check = false; - let mut memory_grow_flag = false; - let mut has_panic = "none"; - let mut call_graph: HashMap> = HashMap::new(); - let mut views_data: HashMap = HashMap::new(); - let mut write_functions: Vec = Vec::new(); - - let mut parser = Parser::new(0); + let mut wasm_info = WasmInfo::default(); + let mut write_functions: HashSet = HashSet::new(); + + let parser = Parser::new(0); for payload in parser.parse_all(&wasm_data) { match payload? { Payload::ImportSection(import_section) => { - imports = extract_imports( - import_section, - extract_imports_enabled, - &mut call_graph, - &mut write_functions, - ); - ei_check = is_ei_valid(&imports, check_ei); + write_functions = + process_imports(import_section, extract_imports_enabled, &mut wasm_info); + wasm_info.ei_check = is_ei_valid(&wasm_info.imports, check_ei); }, Payload::DataSection(data_section) => { - allocator_trigger = is_fail_allocator_triggered(data_section.clone()); + wasm_info.report.has_allocator = is_fail_allocator_triggered(data_section.clone()); if is_panic_with_message_triggered(data_section.clone()) { - has_panic = WITH_MESSAGE; + wasm_info.report.has_panic = WITH_MESSAGE.to_owned(); } else if is_panic_without_message_triggered(data_section) { - has_panic = WITHOUT_MESSAGE; + wasm_info.report.has_panic = WITHOUT_MESSAGE.to_owned(); } }, Payload::CodeSectionEntry(code_section) => { - memory_grow_flag = is_mem_grow(&code_section); + wasm_info.memory_grow_flag = is_mem_grow(&code_section); + create_call_graph(code_section, &mut wasm_info.call_graph); }, Payload::ExportSection(export_section) => { - views_data = parse_export_section(export_section, &view_endpoints); + parse_export_section(export_section, &mut view_endpoints); }, _ => (), } } - parser = Parser::new(0); - for payload in parser.parse_all(&wasm_data) { - if let Payload::CodeSectionEntry(body) = payload? { - create_call_graph(body, &mut call_graph); - } - } + detect_write_operations_in_views(&view_endpoints, &wasm_info.call_graph, &mut write_functions); + + let report = ReportCreator { + path, + has_allocator: wasm_info.report.has_allocator, + has_panic: wasm_info.report.has_panic, + }; + + Ok(WasmInfo { + imports: wasm_info.imports, + ei_check: wasm_info.ei_check, + memory_grow_flag: wasm_info.memory_grow_flag, + call_graph: wasm_info.call_graph, + report, + }) +} + +fn detect_write_operations_in_views( + views_data: &HashMap<&str, usize>, + call_graph: &CallGraph, + write_functions: &mut HashSet, +) { let mut visited: HashSet = HashSet::new(); - for key in views_data.keys() { - mark_write(*key, &call_graph, &mut write_functions, &mut visited); + for index in views_data.values() { + mark_write(*index, call_graph, write_functions, &mut visited); } - for (index, name) in views_data { - if write_functions.contains(&index) { + for (name, index) in views_data { + if write_functions.contains(index) { println!( "{} {}", "Write storage operation in VIEW endpoint:" @@ -115,42 +125,26 @@ fn populate_wasm_info( ); } } - - let report = ReportCreator { - path, - has_allocator: allocator_trigger, - has_panic: has_panic.to_string(), - }; - - Ok(WasmInfo { - imports, - ei_check, - memory_grow_flag, - has_format: true, - report, - }) } fn parse_export_section( export_section: ExportSectionReader, - view_endpoints: &[String], -) -> HashMap { - let mut views_data: HashMap = HashMap::new(); + view_endpoints: &mut HashMap<&str, usize>, +) { for export in export_section { let export = export.expect("Failed to read export section"); if let wasmparser::ExternalKind::Func = export.kind { - if view_endpoints.contains(&export.name.to_string()) { - views_data.insert(export.index.try_into().unwrap(), export.name.to_string()); + if let Some(endpoint_index) = view_endpoints.get_mut(export.name) { + *endpoint_index = export.index.try_into().unwrap(); } } } - views_data } fn mark_write( func: usize, - call_graph: &HashMap>, - write_functions: &mut Vec, + call_graph: &CallGraph, + write_functions: &mut HashSet, visited: &mut HashSet, ) { // Return early to prevent cycles. @@ -163,27 +157,27 @@ fn mark_write( if let Some(callees) = call_graph.get(&func) { for &callee in callees { if write_functions.contains(&callee) { - write_functions.push(func); + write_functions.insert(func); } else { mark_write(callee, call_graph, write_functions, visited); if write_functions.contains(&callee) { - write_functions.push(func); + write_functions.insert(func); } } } } } -fn create_call_graph(body: FunctionBody, call_graph: &mut HashMap>) { +fn create_call_graph(body: FunctionBody, call_graph: &mut CallGraph) { let mut instructions_reader = body .get_operators_reader() .expect("Failed to get operators reader"); - let mut call_functions = Vec::new(); + let mut call_functions = HashSet::new(); while let Ok(op) = instructions_reader.read() { if let Operator::Call { function_index } = op { let function_usize: usize = function_index.try_into().unwrap(); - call_functions.push(function_usize); + call_functions.insert(function_usize); } } @@ -239,28 +233,25 @@ fn is_panic_without_message_triggered(data_section: DataSectionReader) -> bool { false } -pub fn extract_imports( +pub fn process_imports( import_section: ImportSectionReader, import_extraction_enabled: bool, - call_graph: &mut HashMap>, - write_functions: &mut Vec, -) -> Vec { - if !import_extraction_enabled { - return Vec::new(); - } - - let mut import_names = Vec::new(); + wasm_info: &mut WasmInfo, +) -> HashSet { + let mut write_functions = HashSet::new(); for (index, import) in import_section.into_iter().flatten().enumerate() { - import_names.push(import.name.to_string()); - call_graph.insert(index, vec![]); + if import_extraction_enabled { + wasm_info.imports.push(import.name.to_string()); + } + wasm_info.call_graph.insert(index, HashSet::new()); if WRITE_OP.contains(&import.name) { - write_functions.push(index); + write_functions.insert(index); } } - import_names.sort(); + wasm_info.imports.sort(); - import_names + write_functions } fn is_ei_valid(imports: &[String], check_ei: &Option) -> bool { From 6616577997850059e2f6d7bfd5ed4f0d25fdcc0b Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Fri, 13 Sep 2024 19:28:49 +0300 Subject: [PATCH 09/12] detect write op in view storage - fix clippy --- framework/meta-lib/src/tools/wasm_extractor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index 63dad6b3ad..3f58ef1fac 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -70,9 +70,9 @@ fn populate_wasm_info( Payload::DataSection(data_section) => { wasm_info.report.has_allocator = is_fail_allocator_triggered(data_section.clone()); if is_panic_with_message_triggered(data_section.clone()) { - wasm_info.report.has_panic = WITH_MESSAGE.to_owned(); + WITH_MESSAGE.clone_into(&mut wasm_info.report.has_panic); } else if is_panic_without_message_triggered(data_section) { - wasm_info.report.has_panic = WITHOUT_MESSAGE.to_owned(); + WITHOUT_MESSAGE.clone_into(&mut wasm_info.report.has_panic); } }, Payload::CodeSectionEntry(code_section) => { From f962003084c8d7d56b3ad5834d646a4a882e4469 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 8 Oct 2024 13:22:30 +0300 Subject: [PATCH 10/12] detect write op in view storage - apply changes requested from review --- .../src/contract/sc_config/wasm_build.rs | 6 - .../meta-lib/src/tools/report_creator.rs | 2 +- .../meta-lib/src/tools/wasm_extractor.rs | 38 ++- .../meta-lib/src/tools/wasm_extractor_test.rs | 229 +++++++++++++++++- 4 files changed, 249 insertions(+), 26 deletions(-) diff --git a/framework/meta-lib/src/contract/sc_config/wasm_build.rs b/framework/meta-lib/src/contract/sc_config/wasm_build.rs index 4311bd0979..051e07d61a 100644 --- a/framework/meta-lib/src/contract/sc_config/wasm_build.rs +++ b/framework/meta-lib/src/contract/sc_config/wasm_build.rs @@ -93,12 +93,6 @@ impl ContractVariant { print_pack_mxsc_file(&output_mxsc_path); print_contract_size(compiled_bytes.len()); let mut abi = ContractAbiJson::from(&self.abi); - let mut view_endpoints = Vec::new(); - for endpoint in &abi.endpoints { - if let crate::abi_json::EndpointMutabilityAbiJson::Readonly = endpoint.mutability { - view_endpoints.push(&endpoint.name) - } - } let build_info = core::mem::take(&mut abi.build_info).unwrap(); let ei_check_json = EiCheckJson::new(&self.settings.check_ei, wasm_info.ei_check); let report = ReportInfoJson::new(&wasm_info, ei_check_json, compiled_bytes.len()); diff --git a/framework/meta-lib/src/tools/report_creator.rs b/framework/meta-lib/src/tools/report_creator.rs index 8af70ae386..c45739c594 100644 --- a/framework/meta-lib/src/tools/report_creator.rs +++ b/framework/meta-lib/src/tools/report_creator.rs @@ -13,7 +13,7 @@ impl Default for ReportCreator { ReportCreator { path: String::new(), has_allocator: false, - has_panic: "none".to_string(), + has_panic: PanicReport::None, } } } diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index b9ccc13891..36d6df037e 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -10,12 +10,19 @@ use wasmparser::{ use crate::ei::EIVersion; -use super::{panic_report::PanicReport, report_creator::ReportCreator}; +use super::report_creator::ReportCreator; type CallGraph = HashMap>; const ERROR_FAIL_ALLOCATOR: &[u8; 27] = b"memory allocation forbidden"; -const WRITE_OP: [&str; 1] = ["mBufferStorageStore"]; +const WRITE_OP: &[&str] = &[ + "mBufferStorageStore", + "storageStore", + "int64storageStore", + "bigIntStorageStoreUnsigned", + "smallIntStorageStoreUnsigned", + "smallIntStorageStoreSigned", +]; #[derive(Default)] pub struct WasmInfo { @@ -24,6 +31,7 @@ pub struct WasmInfo { pub memory_grow_flag: bool, pub report: ReportCreator, pub call_graph: CallGraph, + pub write_index_functions: HashSet, } impl WasmInfo { @@ -49,24 +57,23 @@ impl WasmInfo { pub(crate) fn populate_wasm_info( path: String, wasm_data: Vec, - extract_imports_enabled: bool, + import_extraction_enabled: bool, check_ei: &Option, mut view_endpoints: HashMap<&str, usize>, ) -> Result { let mut wasm_info = WasmInfo::default(); - let mut write_functions: HashSet = HashSet::new(); let parser = Parser::new(0); for payload in parser.parse_all(&wasm_data) { match payload? { Payload::ImportSection(import_section) => { - write_functions = - process_imports(import_section, extract_imports_enabled, &mut wasm_info); + wasm_info.write_index_functions = + process_imports(import_section, import_extraction_enabled, &mut wasm_info); wasm_info.ei_check |= is_ei_valid(&wasm_info.imports, check_ei); }, Payload::DataSection(data_section) => { - allocator_trigger |= is_fail_allocator_triggered(data_section.clone()); - has_panic.max_severity(data_section); + wasm_info.report.has_allocator |= is_fail_allocator_triggered(data_section.clone()); + wasm_info.report.has_panic.max_severity(data_section); }, Payload::CodeSectionEntry(code_section) => { wasm_info.memory_grow_flag |= is_mem_grow(&code_section); @@ -79,7 +86,11 @@ pub(crate) fn populate_wasm_info( } } - detect_write_operations_in_views(&view_endpoints, &wasm_info.call_graph, &mut write_functions); + detect_write_operations_in_views( + &view_endpoints, + &wasm_info.call_graph, + &mut wasm_info.write_index_functions, + ); let report = ReportCreator { path, @@ -93,13 +104,14 @@ pub(crate) fn populate_wasm_info( memory_grow_flag: wasm_info.memory_grow_flag, call_graph: wasm_info.call_graph, report, + write_index_functions: wasm_info.write_index_functions, }) } -fn detect_write_operations_in_views( - views_data: &HashMap<&str, usize>, - call_graph: &CallGraph, - write_functions: &mut HashSet, +fn detect_write_operations_in_views<'a>( + views_data: &'a HashMap<&'a str, usize>, + call_graph: &'a CallGraph, + write_functions: &'a mut HashSet, ) { let mut visited: HashSet = HashSet::new(); for index in views_data.values() { diff --git a/framework/meta-lib/src/tools/wasm_extractor_test.rs b/framework/meta-lib/src/tools/wasm_extractor_test.rs index 030cddc503..953acbfda8 100644 --- a/framework/meta-lib/src/tools/wasm_extractor_test.rs +++ b/framework/meta-lib/src/tools/wasm_extractor_test.rs @@ -1,9 +1,161 @@ #[cfg(test)] pub mod tests { + use std::collections::{HashMap, HashSet}; + use wat::Parser; use crate::tools::{panic_report::PanicReport, wasm_extractor::populate_wasm_info}; + const ADDER_WITH_ERR_IN_VIEW: &str = r#" +(module $adder_wasm.wasm + (type (;0;) (func (param i32 i32))) + (type (;1;) (func (result i32))) + (type (;2;) (func (param i32 i32) (result i32))) + (type (;3;) (func (param i32 i32 i32) (result i32))) + (type (;4;) (func)) + (type (;5;) (func (param i32))) + (type (;6;) (func (param i32 i32 i32))) + (type (;7;) (func (param i32) (result i32))) + (import "env" "bigIntGetUnsignedArgument" (func $bigIntGetUnsignedArgument (;0;) (type 0))) + (import "env" "getNumArguments" (func $getNumArguments (;1;) (type 1))) + (import "env" "signalError" (func $signalError (;2;) (type 0))) + (import "env" "mBufferFromBigIntUnsigned" (func $mBufferFromBigIntUnsigned (;3;) (type 2))) + (import "env" "mBufferStorageStore" (func $mBufferStorageStore (;4;) (type 2))) + (import "env" "mBufferStorageLoad" (func $mBufferStorageLoad (;5;) (type 2))) + (import "env" "mBufferToBigIntUnsigned" (func $mBufferToBigIntUnsigned (;6;) (type 2))) + (import "env" "mBufferSetBytes" (func $mBufferSetBytes (;7;) (type 3))) + (import "env" "checkNoPayment" (func $checkNoPayment (;8;) (type 4))) + (import "env" "bigIntFinishUnsigned" (func $bigIntFinishUnsigned (;9;) (type 5))) + (import "env" "bigIntAdd" (func $bigIntAdd (;10;) (type 6))) + (func $_ZN13multiversx_sc2io16arg_nested_tuple15load_single_arg17hcaef680f5560198bE (;11;) (type 1) (result i32) + (local i32) + i32.const 0 + call $_ZN26multiversx_sc_wasm_adapter3api13managed_types19static_var_api_node11next_handle17h315bf8f89178ffe1E + local.tee 0 + call $bigIntGetUnsignedArgument + local.get 0 + ) + (func $_ZN26multiversx_sc_wasm_adapter3api13managed_types19static_var_api_node11next_handle17h315bf8f89178ffe1E (;12;) (type 1) (result i32) + (local i32) + i32.const 0 + i32.const 0 + i32.load offset=131100 + i32.const -1 + i32.add + local.tee 0 + i32.store offset=131100 + local.get 0 + ) + (func $_ZN13multiversx_sc2io16arg_nested_tuple22check_num_arguments_eq17h8cbbe81aa680cf46E (;13;) (type 5) (param i32) + block ;; label = @1 + call $getNumArguments + local.get 0 + i32.ne + br_if 0 (;@1;) + return + end + i32.const 131072 + i32.const 25 + call $signalError + unreachable + ) + (func $_ZN13multiversx_sc7storage7mappers19single_value_mapper31SingleValueMapper$LT$SA$C$T$GT$3set17h00fe05a7d5154b39E (;14;) (type 0) (param i32 i32) + (local i32) + call $_ZN26multiversx_sc_wasm_adapter3api13managed_types19static_var_api_node11next_handle17h315bf8f89178ffe1E + local.tee 2 + local.get 1 + call $mBufferFromBigIntUnsigned + drop + local.get 0 + local.get 2 + call $mBufferStorageStore + drop + ) + (func $_ZN13multiversx_sc7storage7mappers19single_value_mapper35SingleValueMapper$LT$SA$C$T$C$A$GT$3get17hb9977d4c8d45f0d8E (;15;) (type 7) (param i32) (result i32) + (local i32) + local.get 0 + call $_ZN26multiversx_sc_wasm_adapter3api13managed_types19static_var_api_node11next_handle17h315bf8f89178ffe1E + local.tee 1 + call $mBufferStorageLoad + drop + local.get 1 + call $_ZN26multiversx_sc_wasm_adapter3api13managed_types19static_var_api_node11next_handle17h315bf8f89178ffe1E + local.tee 0 + call $mBufferToBigIntUnsigned + drop + local.get 0 + ) + (func $_ZN34_$LT$C$u20$as$u20$adder..Adder$GT$3sum17h7cc7cc0602a1f97fE (;16;) (type 1) (result i32) + (local i32) + call $_ZN26multiversx_sc_wasm_adapter3api13managed_types19static_var_api_node11next_handle17h315bf8f89178ffe1E + local.tee 0 + i32.const 131097 + i32.const 3 + call $mBufferSetBytes + drop + local.get 0 + ) + (func $init (;17;) (type 4) + (local i32) + call $checkNoPayment + i32.const 1 + call $_ZN13multiversx_sc2io16arg_nested_tuple22check_num_arguments_eq17h8cbbe81aa680cf46E + call $_ZN13multiversx_sc2io16arg_nested_tuple15load_single_arg17hcaef680f5560198bE + local.set 0 + call $_ZN34_$LT$C$u20$as$u20$adder..Adder$GT$3sum17h7cc7cc0602a1f97fE + local.get 0 + call $_ZN13multiversx_sc7storage7mappers19single_value_mapper31SingleValueMapper$LT$SA$C$T$GT$3set17h00fe05a7d5154b39E + ) + (func $getSum (;18;) (type 4) + call $checkNoPayment + i32.const 0 + call $_ZN13multiversx_sc2io16arg_nested_tuple22check_num_arguments_eq17h8cbbe81aa680cf46E + call $_ZN34_$LT$C$u20$as$u20$adder..Adder$GT$3sum17h7cc7cc0602a1f97fE + call $_ZN13multiversx_sc7storage7mappers19single_value_mapper35SingleValueMapper$LT$SA$C$T$C$A$GT$3get17hb9977d4c8d45f0d8E + call $bigIntFinishUnsigned + ) + (func $add (;19;) (type 4) + (local i32 i32 i32) + call $checkNoPayment + i32.const 1 + call $_ZN13multiversx_sc2io16arg_nested_tuple22check_num_arguments_eq17h8cbbe81aa680cf46E + call $_ZN13multiversx_sc2io16arg_nested_tuple15load_single_arg17hcaef680f5560198bE + local.set 0 + call $_ZN34_$LT$C$u20$as$u20$adder..Adder$GT$3sum17h7cc7cc0602a1f97fE + local.tee 1 + call $_ZN13multiversx_sc7storage7mappers19single_value_mapper35SingleValueMapper$LT$SA$C$T$C$A$GT$3get17hb9977d4c8d45f0d8E + local.tee 2 + local.get 2 + local.get 0 + call $bigIntAdd + local.get 1 + local.get 2 + call $_ZN13multiversx_sc7storage7mappers19single_value_mapper31SingleValueMapper$LT$SA$C$T$GT$3set17h00fe05a7d5154b39E + ) + (func $callBack (;20;) (type 4)) + (table (;0;) 1 1 funcref) + (memory (;0;) 3) + (global $__stack_pointer (;0;) (mut i32) i32.const 131072) + (global (;1;) i32 i32.const 131104) + (global (;2;) i32 i32.const 131104) + (export "memory" (memory 0)) + (export "init" (func $init)) + (export "getSum" (func $getSum)) + (export "add" (func $add)) + (export "callBack" (func $callBack)) + (export "upgrade" (func $init)) + (export "__data_end" (global 1)) + (export "__heap_base" (global 2)) + (data $.rodata (;0;) (i32.const 131072) "wrong number of argumentssum") + (data $.data (;1;) (i32.const 131100) "8\ff\ff\ff") + (@producers + (language "Rust" "") + (processed-by "rustc" "1.80.1 (3f5fd8dd4 2024-08-06)") + ) + (@custom "target_features" (after data) "\02+\0fmutable-globals+\08sign-ext") +) +"#; + const EMPTY_WITH_FAIL_ALLOCATOR: &str = r#" (module $empty_wasm.wasm (type (;0;) (func (result i32))) @@ -256,8 +408,14 @@ pub mod tests { #[test] fn test_empty() { if let Ok(content) = Parser::new().parse_bytes(None, EMPTY_DBG_WAT.as_bytes()) { - let wasm_info = populate_wasm_info(String::new(), content.to_vec(), false, &None) - .expect("Unable to parse WASM content."); + let wasm_info = populate_wasm_info( + String::new(), + content.to_vec(), + false, + &None, + HashMap::new(), + ) + .expect("Unable to parse WASM content."); assert!(!wasm_info.memory_grow_flag); assert!(!wasm_info.report.has_allocator); assert_eq!( @@ -270,8 +428,14 @@ pub mod tests { #[test] fn test_empty_with_mem_grow() { if let Ok(content) = Parser::new().parse_bytes(None, EMPTY_WITH_MEM_GROW.as_bytes()) { - let wasm_info = populate_wasm_info(String::new(), content.to_vec(), false, &None) - .expect("Unable to parse WASM content."); + let wasm_info = populate_wasm_info( + String::new(), + content.to_vec(), + false, + &None, + HashMap::new(), + ) + .expect("Unable to parse WASM content."); assert!(wasm_info.memory_grow_flag); assert!(!wasm_info.report.has_allocator); assert_eq!( @@ -284,8 +448,14 @@ pub mod tests { #[test] fn test_empty_with_fail_allocator() { if let Ok(content) = Parser::new().parse_bytes(None, EMPTY_WITH_FAIL_ALLOCATOR.as_bytes()) { - let wasm_info = populate_wasm_info(String::new(), content.to_vec(), false, &None) - .expect("Unable to parse WASM content."); + let wasm_info = populate_wasm_info( + String::new(), + content.to_vec(), + false, + &None, + HashMap::new(), + ) + .expect("Unable to parse WASM content."); assert!(!wasm_info.memory_grow_flag); assert!(wasm_info.report.has_allocator); assert_eq!( @@ -294,4 +464,51 @@ pub mod tests { ); } } + + #[test] + fn test_adder_with_write_op_in_view() { + let view_endpoints: HashMap<&str, usize> = HashMap::from([("sum", 0), ("add", 0)]); + + let expected_write_index_functions: HashSet = HashSet::from([4, 19, 14]); + let expected_call_graph: HashMap> = HashMap::from([ + (0, HashSet::new()), + (1, HashSet::new()), + (2, HashSet::new()), + (3, HashSet::new()), + (4, HashSet::new()), + (5, HashSet::new()), + (6, HashSet::new()), + (7, HashSet::new()), + (8, HashSet::new()), + (9, HashSet::new()), + (10, HashSet::new()), + (11, HashSet::from([12, 0])), + (12, HashSet::new()), + (13, HashSet::from([1, 2])), + (14, HashSet::from([12, 3, 4])), + (15, HashSet::from([12, 5, 6])), + (16, HashSet::from([12, 7])), + (17, HashSet::from([8, 13, 11, 16, 14])), + (18, HashSet::from([8, 13, 16, 15, 9])), + (19, HashSet::from([8, 13, 11, 16, 15, 10, 14])), + (20, HashSet::new()), + ]); + + if let Ok(content) = Parser::new().parse_bytes(None, ADDER_WITH_ERR_IN_VIEW.as_bytes()) { + let wasm_info = populate_wasm_info( + String::new(), + content.to_vec(), + false, + &None, + view_endpoints, + ) + .expect("Unable to parse WASM content."); + + assert_eq!( + expected_write_index_functions, + wasm_info.write_index_functions + ); + assert_eq!(expected_call_graph, wasm_info.call_graph); + } + } } From ed23f0c319d887274e50c2161b21e2ef58fbcf80 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 8 Oct 2024 18:08:31 +0300 Subject: [PATCH 11/12] detect write op in view storage - refactor wasm_extractor --- .../src/contract/sc_config/wasm_build.rs | 12 +- .../meta-lib/src/tools/wasm_extractor.rs | 202 +++++++++--------- .../meta-lib/src/tools/wasm_extractor_test.rs | 40 ++-- 3 files changed, 120 insertions(+), 134 deletions(-) diff --git a/framework/meta-lib/src/contract/sc_config/wasm_build.rs b/framework/meta-lib/src/contract/sc_config/wasm_build.rs index 051e07d61a..17312dbb04 100644 --- a/framework/meta-lib/src/contract/sc_config/wasm_build.rs +++ b/framework/meta-lib/src/contract/sc_config/wasm_build.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, ffi::OsStr, fs, process::Command}; +use std::{ffi::OsStr, fs, process::Command}; use super::ContractVariant; use crate::{ @@ -131,10 +131,10 @@ impl ContractVariant { let output_wasm_path = format!("{output_path}/{}", self.wasm_output_name(build_args)); let abi = ContractAbiJson::from(&self.abi); - let mut view_endpoints: HashMap<&str, usize> = HashMap::new(); + let mut view_endpoints: Vec<&str> = Vec::new(); for endpoint in &abi.endpoints { if let crate::abi_json::EndpointMutabilityAbiJson::Readonly = endpoint.mutability { - view_endpoints.insert(&endpoint.name, 0); + view_endpoints.push(&endpoint.name); } } @@ -144,8 +144,7 @@ impl ContractVariant { build_args.extract_imports, &self.settings.check_ei, view_endpoints, - ) - .expect("error occured while extracting imports from .wasm "); + ); } let output_imports_json_path = format!( @@ -160,8 +159,7 @@ impl ContractVariant { true, &self.settings.check_ei, view_endpoints, - ) - .expect("error occured while extracting imports from .wasm "); + ); write_imports_output( output_imports_json_path.as_str(), diff --git a/framework/meta-lib/src/tools/wasm_extractor.rs b/framework/meta-lib/src/tools/wasm_extractor.rs index 36d6df037e..eba84b4ada 100644 --- a/framework/meta-lib/src/tools/wasm_extractor.rs +++ b/framework/meta-lib/src/tools/wasm_extractor.rs @@ -32,6 +32,7 @@ pub struct WasmInfo { pub report: ReportCreator, pub call_graph: CallGraph, pub write_index_functions: HashSet, + pub view_endpoints: HashMap, } impl WasmInfo { @@ -39,18 +40,96 @@ impl WasmInfo { output_wasm_path: &str, extract_imports_enabled: bool, check_ei: &Option, - view_endpoints: HashMap<&str, usize>, - ) -> Result { + view_endpoints: Vec<&str>, + ) -> WasmInfo { let wasm_data = fs::read(output_wasm_path) .expect("error occured while extracting information from .wasm: file not found"); - populate_wasm_info( + let wasm_info = populate_wasm_info( output_wasm_path.to_string(), wasm_data, extract_imports_enabled, check_ei, view_endpoints, - ) + ); + + wasm_info.expect("error occured while extracting information from .wasm file") + } + + fn create_call_graph(&mut self, body: FunctionBody) { + let mut instructions_reader = body + .get_operators_reader() + .expect("Failed to get operators reader"); + + let mut call_functions = HashSet::new(); + while let Ok(op) = instructions_reader.read() { + if let Operator::Call { function_index } = op { + let function_usize: usize = function_index.try_into().unwrap(); + call_functions.insert(function_usize); + } + } + + self.call_graph + .insert(self.call_graph.len(), call_functions); + } + + pub fn process_imports( + &mut self, + import_section: ImportSectionReader, + import_extraction_enabled: bool, + ) { + for (index, import) in import_section.into_iter().flatten().enumerate() { + if import_extraction_enabled { + self.imports.push(import.name.to_string()); + } + self.call_graph.insert(index, HashSet::new()); + if WRITE_OP.contains(&import.name) { + self.write_index_functions.insert(index); + } + } + + self.imports.sort(); + } + + pub fn detect_write_operations_in_views(&mut self) { + let mut visited: HashSet = HashSet::new(); + for index in self.view_endpoints.values() { + mark_write( + *index, + &self.call_graph, + &mut self.write_index_functions, + &mut visited, + ); + } + + for (name, index) in &self.view_endpoints { + if self.write_index_functions.contains(index) { + println!( + "{} {}", + "Write storage operation in VIEW endpoint:" + .to_string() + .red() + .bold(), + name.red().bold() + ); + } + } + } + + fn parse_export_section( + &mut self, + export_section: ExportSectionReader, + view_endpoints: &[&str], + ) { + for export in export_section { + let export = export.expect("Failed to read export section"); + if let wasmparser::ExternalKind::Func = export.kind { + if view_endpoints.contains(&export.name) { + self.view_endpoints + .insert(export.name.to_owned(), export.index.try_into().unwrap()); + } + } + } } } @@ -59,7 +138,7 @@ pub(crate) fn populate_wasm_info( wasm_data: Vec, import_extraction_enabled: bool, check_ei: &Option, - mut view_endpoints: HashMap<&str, usize>, + view_endpoints: Vec<&str>, ) -> Result { let mut wasm_info = WasmInfo::default(); @@ -67,8 +146,7 @@ pub(crate) fn populate_wasm_info( for payload in parser.parse_all(&wasm_data) { match payload? { Payload::ImportSection(import_section) => { - wasm_info.write_index_functions = - process_imports(import_section, import_extraction_enabled, &mut wasm_info); + wasm_info.process_imports(import_section, import_extraction_enabled); wasm_info.ei_check |= is_ei_valid(&wasm_info.imports, check_ei); }, Payload::DataSection(data_section) => { @@ -77,20 +155,16 @@ pub(crate) fn populate_wasm_info( }, Payload::CodeSectionEntry(code_section) => { wasm_info.memory_grow_flag |= is_mem_grow(&code_section); - create_call_graph(code_section, &mut wasm_info.call_graph); + wasm_info.create_call_graph(code_section); }, Payload::ExportSection(export_section) => { - parse_export_section(export_section, &mut view_endpoints); + wasm_info.parse_export_section(export_section, &view_endpoints); }, _ => (), } } - detect_write_operations_in_views( - &view_endpoints, - &wasm_info.call_graph, - &mut wasm_info.write_index_functions, - ); + wasm_info.detect_write_operations_in_views(); let report = ReportCreator { path, @@ -105,45 +179,29 @@ pub(crate) fn populate_wasm_info( call_graph: wasm_info.call_graph, report, write_index_functions: wasm_info.write_index_functions, + view_endpoints: wasm_info.view_endpoints, }) } -fn detect_write_operations_in_views<'a>( - views_data: &'a HashMap<&'a str, usize>, - call_graph: &'a CallGraph, - write_functions: &'a mut HashSet, -) { - let mut visited: HashSet = HashSet::new(); - for index in views_data.values() { - mark_write(*index, call_graph, write_functions, &mut visited); - } - - for (name, index) in views_data { - if write_functions.contains(index) { +fn is_fail_allocator_triggered(data_section: DataSectionReader) -> bool { + for data_fragment in data_section.into_iter().flatten() { + if data_fragment + .data + .windows(ERROR_FAIL_ALLOCATOR.len()) + .any(|data| data == ERROR_FAIL_ALLOCATOR) + { println!( - "{} {}", - "Write storage operation in VIEW endpoint:" + "{}", + "FailAllocator used while memory allocation is accessible in code. Contract may fail unexpectedly when memory allocation is attempted" .to_string() .red() - .bold(), - name.red().bold() + .bold() ); + return true; } } -} -fn parse_export_section( - export_section: ExportSectionReader, - view_endpoints: &mut HashMap<&str, usize>, -) { - for export in export_section { - let export = export.expect("Failed to read export section"); - if let wasmparser::ExternalKind::Func = export.kind { - if let Some(endpoint_index) = view_endpoints.get_mut(export.name) { - *endpoint_index = export.index.try_into().unwrap(); - } - } - } + false } fn mark_write( @@ -173,64 +231,6 @@ fn mark_write( } } -fn create_call_graph(body: FunctionBody, call_graph: &mut CallGraph) { - let mut instructions_reader = body - .get_operators_reader() - .expect("Failed to get operators reader"); - - let mut call_functions = HashSet::new(); - while let Ok(op) = instructions_reader.read() { - if let Operator::Call { function_index } = op { - let function_usize: usize = function_index.try_into().unwrap(); - call_functions.insert(function_usize); - } - } - - call_graph.insert(call_graph.len(), call_functions); -} - -fn is_fail_allocator_triggered(data_section: DataSectionReader) -> bool { - for data_fragment in data_section.into_iter().flatten() { - if data_fragment - .data - .windows(ERROR_FAIL_ALLOCATOR.len()) - .any(|data| data == ERROR_FAIL_ALLOCATOR) - { - println!( - "{}", - "FailAllocator used while memory allocation is accessible in code. Contract may fail unexpectedly when memory allocation is attempted" - .to_string() - .red() - .bold() - ); - return true; - } - } - - false -} - -pub fn process_imports( - import_section: ImportSectionReader, - import_extraction_enabled: bool, - wasm_info: &mut WasmInfo, -) -> HashSet { - let mut write_functions = HashSet::new(); - for (index, import) in import_section.into_iter().flatten().enumerate() { - if import_extraction_enabled { - wasm_info.imports.push(import.name.to_string()); - } - wasm_info.call_graph.insert(index, HashSet::new()); - if WRITE_OP.contains(&import.name) { - write_functions.insert(index); - } - } - - wasm_info.imports.sort(); - - write_functions -} - fn is_ei_valid(imports: &[String], check_ei: &Option) -> bool { if let Some(ei) = check_ei { let mut num_errors = 0; diff --git a/framework/meta-lib/src/tools/wasm_extractor_test.rs b/framework/meta-lib/src/tools/wasm_extractor_test.rs index 953acbfda8..c307323a31 100644 --- a/framework/meta-lib/src/tools/wasm_extractor_test.rs +++ b/framework/meta-lib/src/tools/wasm_extractor_test.rs @@ -4,7 +4,7 @@ pub mod tests { use wat::Parser; - use crate::tools::{panic_report::PanicReport, wasm_extractor::populate_wasm_info}; + use crate::tools::{panic_report::PanicReport, wasm_extractor::populate_wasm_info, WasmInfo}; const ADDER_WITH_ERR_IN_VIEW: &str = r#" (module $adder_wasm.wasm @@ -408,14 +408,9 @@ pub mod tests { #[test] fn test_empty() { if let Ok(content) = Parser::new().parse_bytes(None, EMPTY_DBG_WAT.as_bytes()) { - let wasm_info = populate_wasm_info( - String::new(), - content.to_vec(), - false, - &None, - HashMap::new(), - ) - .expect("Unable to parse WASM content."); + let wasm_info = + populate_wasm_info(String::new(), content.to_vec(), false, &None, Vec::new()) + .expect("Unable to parse WASM content."); assert!(!wasm_info.memory_grow_flag); assert!(!wasm_info.report.has_allocator); assert_eq!( @@ -428,14 +423,9 @@ pub mod tests { #[test] fn test_empty_with_mem_grow() { if let Ok(content) = Parser::new().parse_bytes(None, EMPTY_WITH_MEM_GROW.as_bytes()) { - let wasm_info = populate_wasm_info( - String::new(), - content.to_vec(), - false, - &None, - HashMap::new(), - ) - .expect("Unable to parse WASM content."); + let wasm_info = + populate_wasm_info(String::new(), content.to_vec(), false, &None, Vec::new()) + .expect("Unable to parse WASM content."); assert!(wasm_info.memory_grow_flag); assert!(!wasm_info.report.has_allocator); assert_eq!( @@ -448,14 +438,9 @@ pub mod tests { #[test] fn test_empty_with_fail_allocator() { if let Ok(content) = Parser::new().parse_bytes(None, EMPTY_WITH_FAIL_ALLOCATOR.as_bytes()) { - let wasm_info = populate_wasm_info( - String::new(), - content.to_vec(), - false, - &None, - HashMap::new(), - ) - .expect("Unable to parse WASM content."); + let wasm_info = + populate_wasm_info(String::new(), content.to_vec(), false, &None, Vec::new()) + .expect("Unable to parse WASM content."); assert!(!wasm_info.memory_grow_flag); assert!(wasm_info.report.has_allocator); assert_eq!( @@ -467,8 +452,10 @@ pub mod tests { #[test] fn test_adder_with_write_op_in_view() { - let view_endpoints: HashMap<&str, usize> = HashMap::from([("sum", 0), ("add", 0)]); + let view_endpoints: Vec<&str> = Vec::from(["getSum", "add"]); + let expected_view_index: HashMap = + HashMap::from([("getSum".to_string(), 18), ("add".to_string(), 19)]); let expected_write_index_functions: HashSet = HashSet::from([4, 19, 14]); let expected_call_graph: HashMap> = HashMap::from([ (0, HashSet::new()), @@ -509,6 +496,7 @@ pub mod tests { wasm_info.write_index_functions ); assert_eq!(expected_call_graph, wasm_info.call_graph); + assert_eq!(expected_view_index, wasm_info.view_endpoints); } } } From 80959ed33d5e2eaffc7e59c7fcf565d2df56eca8 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 8 Oct 2024 18:16:15 +0300 Subject: [PATCH 12/12] detect write op in view storage - clippy --- framework/meta-lib/src/tools/wasm_extractor_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/meta-lib/src/tools/wasm_extractor_test.rs b/framework/meta-lib/src/tools/wasm_extractor_test.rs index c307323a31..346d0d855e 100644 --- a/framework/meta-lib/src/tools/wasm_extractor_test.rs +++ b/framework/meta-lib/src/tools/wasm_extractor_test.rs @@ -4,7 +4,7 @@ pub mod tests { use wat::Parser; - use crate::tools::{panic_report::PanicReport, wasm_extractor::populate_wasm_info, WasmInfo}; + use crate::tools::{panic_report::PanicReport, wasm_extractor::populate_wasm_info}; const ADDER_WITH_ERR_IN_VIEW: &str = r#" (module $adder_wasm.wasm