Search code examples
dynamicanalysiswebassembly

Pywasm runtime erorr


I tried loading a web assembly program using pywasm (a interpreter for web assembly written entirely in python : https://github.com/mohanson/pywasm ) using the following code

    import pywasm
vm = pywasm.load('out.wasm')
r = vm.exec('fib', [10])
print(r) 

where out.wasm was generated using emscripten on the following C code by running emcc out.c on the following out.c code

int fib(int n) {
    if (n <= 1) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}

which generated a js and a wasm file . Loading the wasm file by pywasm by the above code gave the error

global import env.emscripten_resize_heap not found

Upon inspection I found that the function the wasm file tried to load was actually in the js file generated by emcc hence I thought of generating only a standalone wasm file which I generated using the following command

emcc out.c -o out.wasm

which gave a single out.wasm . I again tried loading this standalone wasm file but it showed a different error this time

global import wasi_unstable.args_sizes_get not found

This suggests that the wasm file wants to import wasi_unstable module which I googled and found to be available here https://www.npmjs.com/package/wasi_unstable . I installed it using the npm install command , however the error persists . Is there a way to convert a c code to a standalone wasm file using emscripten and then load it with pywasm without any error .


Solution

  • Standalone emscripten mode now seems to emit basic WASI API integration. So in order to run code compiled with emscripten you will either need to provide the bare minimum WASI stubs in your JavaScript loader or pywasm will need to implement them. It appears that the minimum set is args_sizes_get, args_get, and proc_exit. For the simple fib case, those functions don't get called so they just need to be defined in the imports. Here is an update to your code that provides the basic defintions:

    import sys
    import pywasm
    wasi_unstable = {
        'args_sizes_get': lambda x: 0,
        'args_get': lambda x: 0,
        'proc_exit': lambda x: 0
    }
    vm = pywasm.load(sys.argv[1], {'wasi_unstable': wasi_unstable})
    r = vm.exec('fib', [10])
    print(r) 
    

    You will also need to compile the fib.c code so that the fib function doesn't get optimized away by emscripten (because emscripten thinks it's not called):

    emcc -s "EXPORTED_FUNCTIONS=['_fib']" fib.c -o fib.wasm
    

    With those changes it works for me:

    python3.8 run.py ./fib.wasm
    55