wasm file loader and header validation

This commit is contained in:
hrigar committed 2026-03-19 23:56:55 +05:30
commit 174bfd1d46
7 files changed
+269

No files matched your search

+210
View File
@@ -0,0 +1,210 @@
format ELF executable 3
entry start
SYS_EXIT = 1
SYS_READ = 3
SYS_WRITE = 4
SYS_OPEN = 5
SYS_CLOSE = 6
STDOUT = 1
O_RDONLY = 0
WASM_MAGIC = 0x6D736100 ; "\0asm"
WASM_VERSION = 0x00000001
WASM_HEADER_SZ = 8
FILE_BUF_SIZE = 4 * 1024 * 1024
segment readable executable
start:
mov eax, [esp]
cmp eax, 2
jl .no_arg
mov eax, SYS_OPEN
mov ebx, [esp + 8]
mov ecx, O_RDONLY
xor edx, edx
int 0x80
test eax, eax
js .open_err
mov [file_fd], eax
mov eax, SYS_READ
mov ebx, [file_fd]
mov ecx, file_buf
mov edx, FILE_BUF_SIZE
int 0x80
test eax, eax
js .read_err
mov [file_size], eax
mov eax, SYS_CLOSE
mov ebx, [file_fd]
int 0x80
cmp dword [file_size], WASM_HEADER_SZ
jl .too_small
mov eax, dword [file_buf]
cmp eax, WASM_MAGIC
jne .bad_magic
mov eax, dword [file_buf + 4]
cmp eax, WASM_VERSION
jne .bad_version
mov esi, msg_ok
call print_str
mov esi, msg_size
call print_str
mov eax, [file_size]
call print_dec
mov esi, msg_bytes
call print_str
xor ebx, ebx
jmp .exit
.no_arg:
mov esi, msg_usage
call print_str
mov ebx, 1
jmp .exit
.open_err:
mov esi, msg_open_err
call print_str
mov ebx, 1
jmp .exit
.read_err:
mov esi, msg_read_err
call print_str
mov ebx, 1
jmp .exit
.too_small:
mov esi, msg_too_small
call print_str
mov ebx, 1
jmp .exit
.bad_magic:
mov esi, msg_bad_magic
call print_str
mov ebx, 1
jmp .exit
.bad_version:
mov esi, msg_bad_ver
call print_str
mov esi, msg_got_ver
call print_str
mov eax, dword [file_buf + 4]
call print_hex32
mov esi, msg_newline
call print_str
mov ebx, 1
jmp .exit
.exit:
mov eax, SYS_EXIT
int 0x80
; esi = null-terminated string
print_str:
push eax ebx ecx edx esi
mov edx, esi
@@:
cmp byte [edx], 0
je @f
inc edx
jmp @b
@@:
sub edx, esi
mov ecx, esi
mov ebx, STDOUT
mov eax, SYS_WRITE
int 0x80
pop esi edx ecx ebx eax
ret
; eax = unsigned 32-bit integer
print_dec:
push eax ebx ecx edx esi
mov ecx, 10
lea esi, [dec_buf + 11]
mov byte [esi], 0
.loop:
dec esi
xor edx, edx
div ecx
add dl, '0'
mov [esi], dl
test eax, eax
jnz .loop
push eax ebx ecx edx
mov edx, esi
@@:
cmp byte [edx], 0
je @f
inc edx
jmp @b
@@:
sub edx, esi
mov ecx, esi
mov ebx, STDOUT
mov eax, SYS_WRITE
int 0x80
pop edx ecx ebx eax
pop esi edx ecx ebx eax
ret
; eax = 32-bit value printed as 0xHHHHHHHH
print_hex32:
push eax ebx ecx edx esi
lea esi, [hex_buf]
mov byte [esi], '0'
mov byte [esi+1], 'x'
mov ecx, 8
add esi, 2
.hex_loop:
rol eax, 4
mov edx, eax
and edx, 0x0F
mov dl, [hex_chars + edx]
mov [esi], dl
inc esi
dec ecx
jnz .hex_loop
mov byte [esi], 0
lea esi, [hex_buf]
call print_str
pop esi edx ecx ebx eax
ret
segment readable writeable
msg_usage db 'Usage: wasm <file.wasm>', 10, 0
msg_open_err db 'Error: cannot open file', 10, 0
msg_read_err db 'Error: cannot read file', 10, 0
msg_too_small db 'Error: file too small (less than 8 bytes)', 10, 0
msg_bad_magic db 'Error: invalid wasm magic number (expected \0asm)', 10, 0
msg_bad_ver db 'Error: unsupported wasm version', 10, 0
msg_got_ver db ' got version: ', 0
msg_ok db 'Valid wasm file', 10, 0
msg_size db 'File size: ', 0
msg_bytes db ' bytes', 10, 0
msg_newline db 10, 0
hex_chars db '0123456789ABCDEF'
hex_buf rb 12
dec_buf rb 12
file_fd dd 0
file_size dd 0
file_buf rb FILE_BUF_SIZE
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh
# Compile all .wat files to .wasm
# Run from the test/ directory
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
WAT_DIR="$SCRIPT_DIR/wat"
WASM_DIR="$SCRIPT_DIR/wasm"
mkdir -p "$WASM_DIR"
for f in "$WAT_DIR"/*.wat; do
base=$(basename "$f" .wat)
wat2wasm "$f" -o "$WASM_DIR/$base.wasm"
echo " $base.wat -> $base.wasm"
done
# edge cases
/usr/bin/printf '\x00asm\x02\x00\x00\x00' > "$WASM_DIR/badver.wasm"
/usr/bin/printf '\x00bad\x01\x00\x00\x00' > "$WASM_DIR/badmagic.wasm"
+34
View File
@@ -0,0 +1,34 @@
#!/bin/sh
# Run from the repo root
WASM=./src/wasm
PASS=0
FAIL=0
TESTS=0
check() {
TESTS=$((TESTS + 1))
desc="$1"; shift
expected="$1"; shift
output=$("$@" 2>&1)
if echo "$output" | grep -q "$expected"; then
PASS=$((PASS + 1))
echo " OK $desc"
else
FAIL=$((FAIL + 1))
echo " FAIL $desc"
echo " expected: $expected"
echo " got: $output"
fi
}
echo "=== wasm runtime tests ==="
check "no arguments" "Usage:" $WASM
check "valid wasm" "Valid wasm file" $WASM test/wasm/valid.wasm
check "bad magic" "invalid wasm magic" $WASM test/wasm/badmagic.wasm
check "bad version" "unsupported wasm" $WASM test/wasm/badver.wasm
echo ""
echo "Results: $PASS/$TESTS passed, $FAIL failed"
[ "$FAIL" -eq 0 ] && exit 0 || exit 1
Binary file not shown.
Binary file not shown.
Binary file not shown.
+5
View File
@@ -0,0 +1,5 @@
(module
(func (export "getSomething") (result i32)
i32.const 42
)
)