From a067982c301856b8e36c0e3c8de9abf77f5e9347 Mon Sep 17 00:00:00 2001 From: dcode Date: Wed, 27 Mar 2019 23:23:53 +0100 Subject: [PATCH] validate struct layout --- std/assembly/bindings/wasi_unstable.ts | 22 +- tests/compiler/wasi.optimized.wat | 7 +- tests/compiler/wasi.ts | 51 ++- tests/compiler/wasi.untouched.wat | 495 ++++++++++++++++++++++++- 4 files changed, 562 insertions(+), 13 deletions(-) diff --git a/std/assembly/bindings/wasi_unstable.ts b/std/assembly/bindings/wasi_unstable.ts index 2d5255ee..b40370e7 100644 --- a/std/assembly/bindings/wasi_unstable.ts +++ b/std/assembly/bindings/wasi_unstable.ts @@ -143,13 +143,14 @@ export type dircookie_t = u64; /** A directory entry. */ @unmanaged export class dirent { /** The offset of the next directory entry stored in this directory. */ - next: dircookie_t; + next: dircookie_t; // 0 /** The serial number of the file referred to by this directory entry. */ - ino: inode_t; + ino: inode_t; // 8 /** The length of the name of the directory entry. */ - namlen: u32; + namlen: u32; // 16 /** The type of the file referred to by this directory entry. */ type: filetype_t; + private __padding0: u16; } /** Error codes returned by functions. */ @@ -312,16 +313,23 @@ export const enum errno { export type errno_t = u16; /** An event that occurred. */ -@unmanaged export class event { +@unmanaged export abstract class event { + /** User-provided value that got attached to `subscription#userdata`. */ userdata: userdata_t; + /** If non-zero, an error that occurred while processing the subscription request. */ error: errno_t; + /* The type of the event that occurred. */ type: eventtype_t; + private __padding0: u16; } /** An event that occurred when type is `eventtype.FD_READ` or `eventtype.FD_WRITE`. */ @unmanaged export class rwevent extends event { + /* The number of bytes available for reading or writing. */ nbytes: filesize_t; + /* The state of the file descriptor. */ flags: eventrwflags_t; + private __padding1: u32; } /** The state of the file descriptor subscribed to with `eventtype.FD_READ` or `eventtype.FD_WRITE`. */ @@ -632,11 +640,12 @@ export const enum subclockflags { export type subclockflags_t = u16; /** Subscription to an event. */ -@unmanaged export class subscription { +@unmanaged export abstract class subscription { /** User-provided value that is attached to the subscription. */ userdata: userdata_t; /** The type of the event to which to subscribe. */ type: eventtype_t; + private __padding0: u32; } /* Subscription to an event of type `eventtype.CLOCK`.**/ @@ -651,12 +660,13 @@ export type subclockflags_t = u16; precision: timestamp_t; /** Flags specifying whether the timeout is absolute or relative. */ flags: subclockflags_t; + private __padding1: u32; } /* Subscription to an event of type `eventtype.FD_READ` or `eventtype.FD_WRITE`.**/ @unmanaged export class fdsubscription extends subscription { /** The file descriptor on which to wait for it to become ready for reading or writing. */ - fd_readwrite: fd_t; + fd: fd_t; } /** Timestamp in nanoseconds. */ diff --git a/tests/compiler/wasi.optimized.wat b/tests/compiler/wasi.optimized.wat index 587c7142..d478ff33 100644 --- a/tests/compiler/wasi.optimized.wat +++ b/tests/compiler/wasi.optimized.wat @@ -1,11 +1,12 @@ (module (type $FUNCSIG$v (func)) - (memory $0 0) + (memory $0 1) + (data (i32.const 8) "\07\00\00\00w\00a\00s\00i\00.\00t\00s") (table $0 1 funcref) - (elem (i32.const 0) $null) + (elem (i32.const 0) $start) (export "memory" (memory $0)) (export "table" (table $0)) - (func $null (; 0 ;) (type $FUNCSIG$v) + (func $start (; 0 ;) (type $FUNCSIG$v) nop ) ) diff --git a/tests/compiler/wasi.ts b/tests/compiler/wasi.ts index 11fee06d..fbcb0e96 100644 --- a/tests/compiler/wasi.ts +++ b/tests/compiler/wasi.ts @@ -1 +1,50 @@ -import "bindings/wasi"; +import { dirent, rwevent, fdstat, filestat, iovec, clocksubscription, fdsubscription } from "bindings/wasi"; + +// TODO: WASM64 + +assert(offsetof("next") == 0); +assert(offsetof("ino") == 8); +assert(offsetof("namlen") == 16); +assert(offsetof("type") == 20); +assert(offsetof() == 24); + +assert(offsetof("userdata") == 0); +assert(offsetof("error") == 8); +assert(offsetof("type") == 10); +assert(offsetof("nbytes") == 16); +assert(offsetof("flags") == 24); +assert(offsetof() == 32); + +assert(offsetof("filetype") == 0); +assert(offsetof("flags") == 2); +assert(offsetof("rights_base") == 8); +assert(offsetof("rights_inheriting") == 16); +assert(offsetof() == 24); + +assert(offsetof("dev") == 0); +assert(offsetof("ino") == 8); +assert(offsetof("filetype") == 16); +assert(offsetof("nlink") == 20); +assert(offsetof("size") == 24); +assert(offsetof("atim") == 32); +assert(offsetof("mtim") == 40); +assert(offsetof("ctim") == 48); +assert(offsetof() == 56); + +assert(offsetof("buf") == 0); +assert(offsetof("buf_len") == 4); +assert(offsetof() == 8); + +assert(offsetof("userdata") == 0); +assert(offsetof("type") == 8); +assert(offsetof("identifier") == 16); +assert(offsetof("clock_id") == 24); +assert(offsetof("timeout") == 32); +assert(offsetof("precision") == 40); +assert(offsetof("flags") == 48); +assert(offsetof() == 56); + +assert(offsetof("userdata") == 0); +assert(offsetof("type") == 8); +assert(offsetof("fd") == 16); +assert(offsetof() == 20); diff --git a/tests/compiler/wasi.untouched.wat b/tests/compiler/wasi.untouched.wat index 4560a6a1..0f81081e 100644 --- a/tests/compiler/wasi.untouched.wat +++ b/tests/compiler/wasi.untouched.wat @@ -1,11 +1,500 @@ (module + (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) (type $FUNCSIG$v (func)) - (memory $0 0) + (import "env" "abort" (func $~lib/env/abort (param i32 i32 i32 i32))) + (memory $0 1) + (data (i32.const 8) "\07\00\00\00w\00a\00s\00i\00.\00t\00s\00") (table $0 1 funcref) (elem (i32.const 0) $null) - (global $~lib/memory/HEAP_BASE i32 (i32.const 8)) + (global $~lib/memory/HEAP_BASE i32 (i32.const 28)) (export "memory" (memory $0)) (export "table" (table $0)) - (func $null (; 0 ;) (type $FUNCSIG$v) + (start $start) + (func $start:wasi (; 1 ;) (type $FUNCSIG$v) + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 5 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 6 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 16 + i32.const 16 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 7 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 20 + i32.const 20 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 8 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 24 + i32.const 24 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 9 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 11 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 12 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 10 + i32.const 10 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 13 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 16 + i32.const 16 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 14 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 24 + i32.const 24 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 15 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 32 + i32.const 32 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 16 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 18 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 2 + i32.const 2 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 19 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 20 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 16 + i32.const 16 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 21 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 24 + i32.const 24 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 22 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 24 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 25 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 16 + i32.const 16 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 26 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 20 + i32.const 20 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 27 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 24 + i32.const 24 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 28 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 32 + i32.const 32 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 29 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 40 + i32.const 40 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 30 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 48 + i32.const 48 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 31 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 56 + i32.const 56 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 32 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 34 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 4 + i32.const 4 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 35 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 36 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 38 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 39 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 16 + i32.const 16 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 40 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 24 + i32.const 24 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 41 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 32 + i32.const 32 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 42 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 40 + i32.const 40 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 43 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 48 + i32.const 48 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 44 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 56 + i32.const 56 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 45 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 0 + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 47 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 8 + i32.const 8 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 48 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 16 + i32.const 16 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 49 + i32.const 0 + call $~lib/env/abort + unreachable + end + i32.const 20 + i32.const 20 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 50 + i32.const 0 + call $~lib/env/abort + unreachable + end + ) + (func $start (; 2 ;) (type $FUNCSIG$v) + call $start:wasi + ) + (func $null (; 3 ;) (type $FUNCSIG$v) ) )