perlin-network / life

A secure WebAssembly VM catered for decentralized applications.
MIT License
1.7k stars 119 forks source link

Invalid assumption of stack pointer in compiled .wasm. #48

Closed helperShang closed 5 years ago

helperShang commented 5 years ago
#include <stdio.h>
#include <string.h>
#include <cstdlib>
extern "C" {
extern void logi(int);
extern void logs(char *);
extern void logl(long);
}
int main() {
    int a[3];
    a[0]=134;
    a[1]=13;
    a[2]=52;
    for (const auto &item : a)
    {
        logi(item);
    }
    return 0;
}
(module
 (type $FUNCSIG$vi (func (param i32)))
 (import "env" "logi" (func $logi (param i32)))
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "main" (func $main))
 (func $main (; 1 ;) (result i32)
  (local $0 i32)
  (local $1 i32)
  (local $2 i32)
  (i32.store offset=4
   (i32.const 0)
   (tee_local $2
    (i32.sub
     (i32.load offset=4
      (i32.const 0)
     )
     (i32.const 16)
    )
   )
  )
  (i32.store offset=12
   (get_local $2)
   (i32.const 52)
  )
  (i64.store offset=4 align=4
   (get_local $2)
   (i64.const 55834574982)
  )
  (call $logi
   (i32.const 134)
  )
  (set_local $0
   (i32.add
    (i32.add
     (get_local $2)
     (i32.const 4)
    )
    (i32.const 4)
   )
  )
  (set_local $1
   (i32.const 0)
  )
  (loop $label$0
   (call $logi
    (i32.load
     (i32.add
      (get_local $0)
      (get_local $1)
     )
    )
   )
   (br_if $label$0
    (i32.ne
     (tee_local $1
      (i32.add
       (get_local $1)
       (i32.const 4)
      )
     )
     (i32.const 8)
    )
   )
  )
  (i32.store offset=4
   (i32.const 0)
   (i32.add
    (get_local $2)
    (i32.const 16)
   )
  )
  (i32.const 0)
 )
)

i64.const 55834574982

=== RUN   TestWasmRun
--- Begin stack trace ---
<0> [1] 
--- End stack trace ---
--- FAIL: TestWasmRun (0.00s)
panic: runtime error: slice bounds out of range [recovered]
    panic: runtime error: slice bounds out of range
iwasaki-kenta commented 5 years ago

By using optimization level 3, we get a far more straightforward *.wat.

(module
 (type $FUNCSIG$vi (func (param i32)))
 (import "env" "logi" (func $logi (param i32)))
 (table 0 anyfunc)
 (memory $0 1)
 (data (i32.const 12) "\04\00\00\00")
 (export "memory" (memory $0))
 (export "main" (func $main))
 (func $main (; 1 ;) (result i32)
  (call $logi
   (i32.const 134)
  )
  (call $logi
   (i32.const 13)
  )
  (call $logi
   (i32.const 52)
  )
  (i32.const 0)
 )
)

If you are using the online compiler https://mbebenita.github.io/WasmExplorer/, note that binaries produced by that compiler (alongside others such as Emscripten) that assumes memory is pre-allocated, and that a stack pointer is specified at offset 4.

Would recommend directly compiling w/ LLVM and clang, or otherwise use an option that we've been testing with which is creating WebAssembly modules in Rust and thereafter compiling them down to *.wasm with cargo.