soundandform / m3

A high performance WebAssembly interpreter in C. Moved here:
https://github.com/wasm3/wasm3
MIT License
17 stars 1 forks source link

Bug runtime out of memory #1

Open porky11 opened 5 years ago

porky11 commented 5 years ago

I tried to run a minimal example to open a glfw window using this library.

I started the program using ./m3 glfw.wasm

The file glfw.wasm converted to glfw.wat looks like this:

(module
  (type (;0;) (func (result i32)))
  (type (;1;) (func (param i32 i32 i32 i32 i32) (result i32)))
  (type (;2;) (func))
  (type (;3;) (func (param i32) (result i32)))
  (type (;4;) (func (param i32)))
  (import "env" "glfwInit" (func $glfwInit (type 0)))
  (import "env" "glfwCreateWindow" (func $glfwCreateWindow (type 1)))
  (import "env" "glfwTerminate" (func $glfwTerminate (type 2)))
  (import "env" "glfwWindowShouldClose" (func $glfwWindowShouldClose (type 3)))
  (import "env" "glfwSwapBuffers" (func $glfwSwapBuffers (type 4)))
  (import "env" "glfwPollEvents" (func $glfwPollEvents (type 2)))
  (func $__wasm_call_ctors (type 2))
  (func $startGlfw (type 2)
    (local i32 i32)
    global.get 0
    i32.const 16
    i32.sub
    local.tee 0
    global.set 0
    block  ;; label = @1
      call $glfwInit
      i32.eqz
      br_if 0 (;@1;)
      block  ;; label = @2
        i32.const 640
        i32.const 480
        i32.const 1024
        i32.const 0
        i32.const 0
        call $glfwCreateWindow
        local.tee 1
        br_if 0 (;@2;)
        call $glfwTerminate
        local.get 0
        i32.const 16
        i32.add
        global.set 0
        return
      end
      block  ;; label = @2
        loop  ;; label = @3
          local.get 1
          call $glfwWindowShouldClose
          br_if 1 (;@2;)
          local.get 1
          call $glfwSwapBuffers
          call $glfwPollEvents
          br 0 (;@3;)
        end
      end
      call $glfwTerminate
      local.get 0
      i32.const 16
      i32.add
      global.set 0
      return
    end
    local.get 0
    i32.const 16
    i32.add
    global.set 0)
  (table (;0;) 1 1 funcref)
  (memory (;0;) 2)
  (global (;0;) (mut i32) (i32.const 66576))
  (global (;1;) i32 (i32.const 66576))
  (global (;2;) i32 (i32.const 1036))
  (global (;3;) i32 (i32.const 1024))
  (export "memory" (memory 0))
  (export "__heap_base" (global 1))
  (export "__data_end" (global 2))
  (export "startGlfw" (func $startGlfw))
  (export "__unnamed_1" (global 3))
  (data (;0;) (i32.const 1024) "Hello World\00"))

The error message I get looks like this:

-- m3 configuration --------------------------------------------
 sizeof M3MemPage     : 65536 bytes              
 sizeof M3Compilation : 8592 bytes              
----------------------------------------------------------------

    parse  |  load module: 1052 bytes
    parse  |  found magic + version
    parse  |  ** Type [5]
    parse  |  () -> i32
    parse  |  (i32, i32, i32, i32, i32) -> i32
    parse  |  () -> nil
    parse  |  (i32) -> i32
    parse  |  (i32) -> nil
    parse  |  ** Import [6]
    parse  |    - kind: 0; 'env.glfwInit' 
    parse  |    - kind: 0; 'env.glfwCreateWindow' 
    parse  |    - kind: 0; 'env.glfwTerminate' 
    parse  |    - kind: 0; 'env.glfwWindowShouldClose' 
    parse  |    - kind: 0; 'env.glfwSwapBuffers' 
    parse  |    - kind: 0; 'env.glfwPollEvents' 
    parse  |  ** Function [2]
    parse  |  <skipped (id: 4)>
    parse  |  <skipped (id: 5)>
    parse  |  ** Global [4]
    parse  |    - add global: [0] i32
  compile  |     0 | 0x01  .. nop
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 66576)
  compile  |     2 | 0x0b   end
    parse  |    - add global: [1] i32
  compile  |     0 | 0x00  .. unreachable
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 66576)
  compile  |     2 | 0x0b   end
    parse  |    - add global: [2] i32
  compile  |     0 | 0x00  .. unreachable
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 1036)
  compile  |     2 | 0x0b   end
    parse  |    - add global: [3] i32
  compile  |     0 | 0x00  .. unreachable
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 1024)
  compile  |     2 | 0x0b   end
    parse  |  ** Export [5]
    parse  |    - index:    0; kind: 2; export: 'memory'; 
    parse  |    - index:    1; kind: 3; export: '__heap_base'; 
    parse  |    - index:    2; kind: 3; export: '__data_end'; 
    parse  |    - index:    7; kind: 0; export: 'startGlfw'; 
    parse  |    - index:    3; kind: 3; export: '__unnamed_1'; 
    parse  |  ** Code [2]
    parse  |    - func size: 2; locals: 0
    parse  |    - func size: 141; locals: 1
    parse  |      - 2 locals; type: 'i32'
    parse  |  ** Data [1]
  compile  |     0 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 1024)
  compile  |     1 | 0x0b   end
    parse  |      segment [0]  memory: 0;  expr-size: 4;  size: 12
    parse  |  ** Custom: '.debug_info'
    parse  |  ** Custom: '.debug_macinfo'
    parse  |  ** Custom: '.debug_pubtypes'
    parse  |  ** Custom: '.debug_abbrev'
    parse  |  ** Custom: '.debug_line'
    parse  |  ** Custom: '.debug_str'
    parse  |  ** Custom: '.debug_pubnames'
    parse  |  ** Custom: 'name'
    parse  |  naming function [6]: __wasm_call_ctors

-- m3 configuration --------------------------------------------
 sizeof M3MemPage     : 65536 bytes              
 sizeof M3Compilation : 8592 bytes              
----------------------------------------------------------------

  runtime  |  initializing global: 0
  compile  |     0 | 0x01  .. nop
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 66576)
  compile  |     2 | 0x0b   end
  runtime  |  initializing global: 1
  compile  |     0 | 0x00  .. unreachable
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 66576)
  compile  |     2 | 0x0b   end
     exec  |  *** trapping ***
  runtime  |  initializing global: 2
  compile  |     0 | 0x00  .. unreachable
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 1036)
  compile  |     2 | 0x0b   end
     exec  |  *** trapping ***
  runtime  |  initializing global: 3
  compile  |     0 | 0x00  .. unreachable
  compile  |     1 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 1024)
  compile  |     2 | 0x0b   end
     exec  |  *** trapping ***
  compile  |     0 | 0x41  .. i32.const
  compile  |       | .......... (const i32 = 1024)
  compile  |     1 | 0x0b   end
  runtime  |  loading data segment: 0  offset: 1024
result: runtime ran out of memory ()

The bug happens when calling m3_LoadModule.

Any idea what's going on here? Is it a bug or may there be some problem with my wasm?

vshymanskyy commented 4 years ago

The bug is caused by some (incomplete) logic in module initialization. As a side note, M3 engine currently lacks a lot of things, and memory management is one of them. I've spent some time fixing different things as you can see in #2 and in my fork here: https://github.com/vshymanskyy/wasm3 So I hope to get to this particular issue soon

vshymanskyy commented 4 years ago

@porky11 please check out #3