Skip to content

Check all segment bounds beforehand #399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions interpreter/spec/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -359,19 +359,23 @@ let init_closure (inst : instance) (clos : closure) =
| _ -> assert false

let init_table (inst : instance) (seg : table_segment) =
let {index; offset; init} = seg.it in
let {index; offset = const; init} = seg.it in
let tab = table inst index in
let offset = i32 (eval_const inst offset) offset.at in
try Table.blit tab offset (List.map (fun x -> Func (func inst x)) init)
with Table.Bounds -> Link.error seg.at "elements segment does not fit table"
let offset = i32 (eval_const inst const) const.at in
let bound = Table.size tab in
if I32.lt_u bound Int32.(add offset (of_int (List.length init))) then
Link.error seg.at "elements segment does not fit table";
fun () -> Table.blit tab offset (List.map (fun x -> Func (func inst x)) init)

let init_memory (inst : instance) (seg : memory_segment) =
let {index; offset; init} = seg.it in
let {index; offset = const; init} = seg.it in
let mem = memory inst index in
let offset = i32 (eval_const inst offset) offset.at in
let offset64 = Int64.(logand (of_int32 offset) 0xffffffffL) in
try Memory.blit mem offset64 init
with Memory.Bounds -> Link.error seg.at "data segment does not fit memory"
let offset' = i32 (eval_const inst const) const.at in
let offset = I64_convert.extend_u_i32 offset' in
let bound = Memory.bound mem in
if I64.lt_u bound Int64.(add offset (of_int (String.length init))) then
Link.error seg.at "data segment does not fit memory";
fun () -> Memory.blit mem offset init

let init_global (inst : instance) (ref : value ref) (glob : global) =
let {value; _} = glob.it in
Expand Down Expand Up @@ -436,7 +440,9 @@ let init (m : module_) (exts : extern list) : instance =
in
List.iter2 (init_global inst) gs globals;
List.iter (init_closure inst) fs;
List.iter (init_table inst) elems;
List.iter (init_memory inst) data;
let init_elems = List.map (init_table inst) elems in
let init_datas = List.map (init_memory inst) data in
List.iter (fun f -> f ()) init_elems;
List.iter (fun f -> f ()) init_datas;
Lib.Option.app (fun x -> ignore (invoke (func inst x) [])) start;
{inst with exports = List.fold_right (add_export inst) exports inst.exports}
2 changes: 1 addition & 1 deletion interpreter/spec/eval.mli
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ exception Link of Source.region * string
exception Trap of Source.region * string
exception Crash of Source.region * string

val init : Ast.module_ -> extern list -> instance
val init : Ast.module_ -> extern list -> instance (* raises Link, Trap *)
val invoke : closure -> value list -> value list (* raises Trap *)
5 changes: 4 additions & 1 deletion interpreter/spec/memory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,11 @@ let create {min; max} =
assert (within_limits min max);
{content = create' min; max}

let bound mem =
Array1_64.dim mem.content

let size mem =
Int64.(to_int32 (div (Array1_64.dim mem.content) page_size))
Int64.(to_int32 (div (bound mem) page_size))

let limits mem =
{min = size mem; max = mem.max}
Expand Down
1 change: 1 addition & 0 deletions interpreter/spec/memory.mli
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ val mem_size : mem_size -> int

val create : size limits -> memory (* raise SizeOverflow, OutOfMemory *)
val size : memory -> size
val bound : memory -> address
val limits : memory -> size limits
val grow : memory -> size -> unit
(* raise SizeLimit, SizeOverflow, OutOfMemory *)
Expand Down
52 changes: 48 additions & 4 deletions interpreter/test/linking.wast
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,39 @@

(assert_unlinkable
(module
(func $host (import "spectest" "print"))
(table (import "Mt" "tab") 10 anyfunc)
(memory (import "Mt" "mem") 1) ;; does not exist
(elem (i32.const 7) $own)
(elem (i32.const 9) $host)
(func $own (result i32) (i32.const 666))
(func $f (result i32) (i32.const 0))
(elem (i32.const 7) $f)
(elem (i32.const 9) $f)
)
"unknown import"
)
(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized")

(assert_unlinkable
(module
(table (import "Mt" "tab") 10 anyfunc)
(func $f (result i32) (i32.const 0))
(elem (i32.const 7) $f)
(elem (i32.const 12) $f) ;; out of bounds
)
"elements segment does not fit"
)
(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized")

(assert_unlinkable
(module
(table (import "Mt" "tab") 10 anyfunc)
(func $f (result i32) (i32.const 0))
(elem (i32.const 7) $f)
(memory 1)
(data (i32.const 0x10000) "d") ;; out of bounds
)
"data segment does not fit"
)
(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized")


;; Memories

Expand Down Expand Up @@ -239,3 +261,25 @@
"unknown import"
)
(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0))

(assert_unlinkable
(module
(memory (import "Mm" "mem") 1)
(data (i32.const 0) "abc")
(data (i32.const 0x50000) "d") ;; out of bounds
)
"data segment does not fit"
)
(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0))

(assert_unlinkable
(module
(memory (import "Mm" "mem") 1)
(data (i32.const 0) "abc")
(table 0 anyfunc)
(func)
(elem (i32.const 0) 0) ;; out of bounds
)
"elements segment does not fit"
)
(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0))
10 changes: 9 additions & 1 deletion interpreter/test/memory.wast
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@
(module (memory 1 2) (data (i32.const 0) "a") (data (i32.const 98304) "b"))
"data segment does not fit"
)
(assert_unlinkable
(module (memory 0 0) (data (i32.const 1) ""))
"data segment does not fit"
)
(assert_unlinkable
(module (memory 1) (data (i32.const 0x12000) ""))
"data segment does not fit"
)
;; This seems to cause a time-out on Travis.
(;assert_unlinkable
(module (memory 0x10000) (data (i32.const 0xffffffff) "ab"))
Expand All @@ -64,7 +72,7 @@
)

(module (memory 0 0) (data (i32.const 0) ""))
(module (memory 0 0) (data (i32.const 1) ""))
(module (memory 1 1) (data (i32.const 0x10000) ""))
(module (memory 1 2) (data (i32.const 0) "abc") (data (i32.const 0) "def"))
(module (memory 1 2) (data (i32.const 3) "ab") (data (i32.const 0) "de"))
(module
Expand Down