kanaka / wac Goto Github PK
View Code? Open in Web Editor NEWWebAssembly interpreter in C
License: Other
WebAssembly interpreter in C
License: Other
CFLAGS="-g -fsanitize=address" make
Hi there,
thank you for sharing your WebAssembly interpreter.
I'm planning to embed WebAssembly in a C++ program so your implementation seems like an excellent starting point.
If I understood the approach correctly, you directly expose C symbols as host imports to the WebAssembly client. This is great for quickly exposing third party libraries like SDL, but what about commands like malloc
? Won't these allocate memory in the host's address space rather than the client's linear memory? This does not go well with my idea of isolating the client from the host :)
To completely sandbox the client, I guess it would be necessary to wrap any exported host functions, mapping client to host pointers, and write custom memory management routines.
Do you have any thoughts on this topic?
Do you have further plans with this project, and would you be interested in pull requests in case my fiddling produces something useful?
Cheers,
Martin
Have you looked into targeting the GNU Arm Embedded Toolchain so that WASM can run on Arm-based microcontrollers?
Hi, I did a bit of fuzzing of and found issues that can make wac crash. I provide files to reproduce the issues.
Sample file: https://drive.google.com/open?id=1JnSjtTw6SeKQksgGa2NrzP_syM0bFG82
If a code section is parsed before imports, m->functions can be NULL and will later cause a null pointer dereference. For example:
Block *function = &m->functions[m->import_count+b];
Sample file: https://drive.google.com/open?id=1yKmr0Om_Ypg1nnz8VPnp5LuQFic2WMLc
The read functions do not make sure that the file has as least the remaining amount of data they attempt to read. For example the read_string functions reads the length of a string in str_len
and then memcpy's that length without checking that the remaining file size it at least that long.
char *read_string(uint8_t *bytes, uint32_t *pos, uint32_t *result_len) {
uint32_t str_len = read_LEB(bytes, pos, 32);
char * str = malloc(str_len+1);
memcpy(str, bytes+*pos, str_len);
The read functions should take a bytes_len
as a parameter and check the remaining size.
When running wac on sha1sum.wasm
from the vmir
project, I get the following error:
./wac ~/clones/vmir/examples/prebuilt/sha1sum.wasm
zsh: segmentation fault (core dumped) ./wac ~/clones/vmir/examples/prebuilt/sha1sum.wasm
I'm using:
When compiling with -O1 -g
and using bt full
in gdb
, this is the output:
(gdb) r ~/clones/vmir/examples/prebuilt/sha1sum.wasm
Starting program: /home/afr/clones/wac/wac ~/clones/vmir/examples/prebuilt/sha1sum.wasm
Program received signal SIGSEGV, Segmentation fault.
0xf7dae279 in __memset_sse2 () from /usr/lib32/libc.so.6
(gdb) bt full
#0 0xf7dae279 in __memset_sse2 () from /usr/lib32/libc.so.6
No symbol table info available.
#1 0x565655b0 in thunk_out_i_iii (m=0xf7b2d010, function=0x5658b2b8, type=0x5658a6dc) at thunks.c:454
res = <optimized out>
#2 0x5655fc11 in thunk_out (m=0xf7b2d010, fidx=2) at wa.c:544
func = 0x5658b2b8
type = 0x5658a6dc
thunk_mask = 8454417
p = <optimized out>
#3 0x565601e3 in interpret (m=0xf7b2d010) at wa.c:809
block = <optimized out>
prev_pages = <optimized out>
sval = <optimized out>
didx = <optimized out>
delta = <optimized out>
bytes = 0xf7fd0000 ""
stack = 0xf7b2d074
cur_pc = 492
block = <optimized out>
arg = <optimized out>
val = <optimized out>
fidx = <optimized out>
tidx = <optimized out>
cond = <optimized out>
depth = <optimized out>
count = <optimized out>
flags = <optimized out>
offset = <optimized out>
addr = <optimized out>
maddr = <optimized out>
mem_end = <optimized out>
depths = <optimized out>
opcode = 16 '\020'
a = <optimized out>
b = <optimized out>
c = 4294967104
d = <optimized out>
e = <optimized out>
f = 6221221224307818496
g = <optimized out>
h = <optimized out>
i = -1.03310949e+34
j = <optimized out>
k = <optimized out>
l = 1.3447704791445071e-313
overflow = false
#4 0x56563be8 in invoke (m=0xf7b2d010, entry=<optimized out>, argc=-1, argv=0xffffd0c0) at wa.c:1997
fidx = 6
type = 0x5658a6a0
result = <optimized out>
#5 0x5655eec7 in main (argc=<optimized out>, argv=<optimized out>) at wac.c:63
mod_path = <optimized out>
entry = <optimized out>
line = <optimized out>
repl = 0
debug = 0
res = 0
option_index = 0
c = <optimized out>
long_options = {{name = 0x5657545c "repl", has_arg = 0, flag = 0xffffcfac, val = 1}, {name = 0x56575461 "debug", has_arg = 0, flag = 0xffffcfb0, val = 1}, {name = 0x0, has_arg = 0, flag = 0x0, val = 0}}
opts = {disable_memory_bounds = false, mangle_table_index = false, dlsym_trim_underscore = false}
m = <optimized out>
(gdb)
The problematic line could be line 454 in thunks.c
?
platform_libc.c:18:53: error: format specifies type 'int' but the argument has type 'unsigned long' [-Werror,-Wformat]
FATAL("Could not allocate %d bytes for %s", (int)nmemb * size, name);
~~ ^~~~~~~~~~~~~~~~~
%lu
./util.h:20:21: note: expanded from macro 'FATAL'
fprintf(stderr, __VA_ARGS__); exit(1); \
^~~~~~~~~~~
platform_libc.c:28:53: error: format specifies type 'int' but the argument has type 'unsigned long' [-Werror,-Wformat]
FATAL("Could not allocate %d bytes for %s", (int)nmemb * size, name);
~~ ^~~~~~~~~~~~~~~~~
%lu
./util.h:20:21: note: expanded from macro 'FATAL'
fprintf(stderr, __VA_ARGS__); exit(1); \
^~~~~~~~~~~
2 errors generated.
make: *** [platform_libc.o] Error 1
I can fix the Makefile on my own but you may want to fix this. :)
It would make it easier to use and start working with. And also improve portability.
Thanks!
Hello Kanaka.
I'm inquiring about wac's performance.
Does wac also use a JIT like wasm? If not, how performant is wac as a bytecode interpreter?
Thank You
~Kevin.
CFLAGS="-g -fsanitize=address" make
root@9dc6ce043bcb:~/Ablation/wac-asan# ./wace ../wasm-fuzz/fuzz_out_wac/crashes/id\:000000\,sig\:11\,src\:000236\,op\:python\,pos\:0
=================================================================
==2066617==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf3b0046f at pc 0x5664afca bp 0xffcf5ae8 sp 0xffcf5ad8
WRITE of size 1 at 0xf3b0046f thread T0
#0 0x5664afc9 in interpret /root/Ablation/wac-asan/wa.c:993
#1 0x56658459 in load_module /root/Ablation/wac-asan/wa.c:1911
#2 0x5665a0e9 in main /root/Ablation/wac-asan/wace.c:64
#3 0xf7387ed4 in __libc_start_main ../csu/libc-start.c:308
#4 0x5663d704 in _start (/root/Ablation/wac-asan/wace+0x3704)
0xf3b0046f is located 1 bytes to the left of 1-byte region [0xf3b00470,0xf3b00471)
allocated by thread T0 here:
#0 0xf79da9f7 in __interceptor_calloc ../../../../../src/libsanitizer/asan/asan_malloc_linux.cc:153
#1 0x56659299 in acalloc /root/Ablation/wac-asan/platform_libc.c:16
#2 0x566562b4 in load_module /root/Ablation/wac-asan/wa.c:1708
#3 0x5665a0e9 in main /root/Ablation/wac-asan/wace.c:64
#4 0xf7387ed4 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: heap-buffer-overflow /root/Ablation/wac-asan/wa.c:993 in interpret
Shadow bytes around the buggy address:
0x3e760030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e760040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e760050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x3e760060: fa fa fa fa fa fa fa fa fa fa 01 fa fa fa 01 fa
0x3e760070: fa fa 01 fa fa fa 00 04 fa fa 00 04 fa fa 06 fa
=>0x3e760080: fa fa fd fd fa fa 07 fa fa fa fd fd fa[fa]01 fa
0x3e760090: fa fa 04 fa fa fa 01 fa fa fa 01 fa fa fa 04 fa
0x3e7600a0: fa fa 00 fa fa fa 04 fa fa fa 04 fa fa fa 04 fa
0x3e7600b0: fa fa 00 fa fa fa 04 fa fa fa 00 fa fa fa 00 01
0x3e7600c0: fa fa 00 02 fa fa 00 04 fa fa 00 07 fa fa 00 07
0x3e7600d0: fa fa 00 00 fa fa 00 00 fa fa 00 07 fa fa 00 04
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==2066617==ABORTING
./wace <PoC>
running examples in README.md, and each one produces an error similar to:
> root@f2b8deabf964:/wac# ./wace examples_c/hello1.wasm
> Error(platform_libc.c:47): could stat file 'examples_c/hello1.wasm'
CFLAGS="-g -fsanitize=address" make
root@9dc6ce043bcb:~/Ablation/wasm-fuzz/fuzz_out_wac/crashes# ./wace id:000207,sig:11,src:001719,op:python,pos:0
=================================================================
==6667==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf46029f4 at pc 0x56652d14 bp 0xffff6568 sp 0xffff6558
READ of size 4 at 0xf46029f4 thread T0
#0 0x56652d13 in setup_call /root/Ablation/wac-asan/wa.c:525
#1 0x566544fb in interpret /root/Ablation/wac-asan/wa.c:738
#2 0x56665459 in load_module /root/Ablation/wac-asan/wa.c:1911
#3 0x566670e9 in main /root/Ablation/wac-asan/wace.c:64
#4 0xf7472ed4 in __libc_start_main ../csu/libc-start.c:308
#5 0x5664a704 in _start (/root/Ablation/wac-asan/wace+0x3704)
0xf46029f4 is located 4 bytes to the right of 112-byte region [0xf4602980,0xf46029f0)
allocated by thread T0 here:
#0 0xf7ac59f7 in __interceptor_calloc ../../../../../src/libsanitizer/asan/asan_malloc_linux.cc:153
#1 0x56666299 in acalloc /root/Ablation/wac-asan/platform_libc.c:16
#2 0x56660a22 in load_module /root/Ablation/wac-asan/wa.c:1502
#3 0x566670e9 in main /root/Ablation/wac-asan/wace.c:64
#4 0xf7472ed4 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: heap-buffer-overflow /root/Ablation/wac-asan/wa.c:525 in setup_call
I have a bad feeling this is something dumb I'm doing,
but I cannot pull the docker the image.
Things I have tried:
setting the time with ntpdate
reconfiguring tzdata (it threw my clock off by 10min?)
docker pull kanaka/emscripten
sudo docker pull kanaka/emscripten
creating a docker hub account
docker login followed by pull
sudo docker login followed by pull
su to root, docker login, docker pull.
every single time, the downloads finish, but I get 'authentication required'.
I believe my Docker installation is correct- it's from the Jessie repos-
and pulling other images just works:
$ docker pull mono
Using default tag: latest
latest: Pulling from library/mono
5233d9aed181: Already exists
666418377e5b: Pull complete
75a87e0601e5: Pull complete
8e3dafbe502d: Pull complete
Digest: sha256:32b9d2580388688b8d57742e659f2d021d3d90f036141b1fee81ded64062dd9e
Status: Downloaded newer image for mono:latest
Managed to get the project built on windows.
Test suite has not been run so use at your own risk.
CFLAGS="-g -fsanitize=address" make
root@9dc6ce043bcb:~/Ablation/wasm-fuzz/fuzz_out_wac/crashes# ./wace id:000220,sig:11,src:001688,op:python,pos:0
=================================================================
==4631==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xf3c004d4 at pc 0x56665510 bp 0xffcd8328 sp 0xffcd8318
WRITE of size 4 at 0xf3c004d4 thread T0
#0 0x5666550f in load_module /root/Ablation/wac-asan/wa.c:1806
#1 0x566680e9 in main /root/Ablation/wac-asan/wace.c:64
#2 0xf73c7ed4 in __libc_start_main ../csu/libc-start.c:308
#3 0x5664b704 in _start (/root/Ablation/wac-asan/wace+0x3704)
0xf3c004d4 is located 0 bytes to the right of 4-byte region [0xf3c004d0,0xf3c004d4)
allocated by thread T0 here:
#0 0xf7a1a9f7 in __interceptor_calloc ../../../../../src/libsanitizer/asan/asan_malloc_linux.cc:153
#1 0x56667299 in acalloc /root/Ablation/wac-asan/platform_libc.c:16
#2 0x566640f7 in load_module /root/Ablation/wac-asan/wa.c:1694
#3 0x566680e9 in main /root/Ablation/wac-asan/wace.c:64
#4 0xf73c7ed4 in __libc_start_main ../csu/libc-start.c:308
wabt provides the wast2json
tool to parse the wast files. It then generates a .json
file, and a collection of .wasm
files for each module. This might be simpler than parsing yourself in runtest.py
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.