diff --git a/src/lib_scoru_wasm/constants.ml b/src/lib_scoru_wasm/constants.ml index 5e5a3d356e2a367b8ca11e28cf39f51abd662b2a..3f51cf9c497ee21108784f4772f20f75bb2d66f9 100644 --- a/src/lib_scoru_wasm/constants.ml +++ b/src/lib_scoru_wasm/constants.ml @@ -64,3 +64,5 @@ let too_many_reboot_flag_key = kernel can do with a given inbox. *) let reboot_counter_key = Durable.key_of_string_exn "/readonly/kernel/env/reboot_counter" + +let stack_size_limit = 300 diff --git a/src/lib_scoru_wasm/wasm_vm.ml b/src/lib_scoru_wasm/wasm_vm.ml index aef0ca026461edf701967f2f5c0d542fadce0d8d..0b241153ed66150d5190e52df315c508da1c4b45 100644 --- a/src/lib_scoru_wasm/wasm_vm.ml +++ b/src/lib_scoru_wasm/wasm_vm.ml @@ -115,7 +115,7 @@ let save_fallback_kernel durable = Constants.kernel_fallback_key else Lwt.return durable -let unsafe_next_tick_state host_function_registry +let unsafe_next_tick_state ~stack_size_limit host_function_registry ({buffers; durable; tick_state; _} as pvm_state) = let open Lwt_syntax in let return ?(status = Running) ?(durable = durable) state = @@ -234,6 +234,7 @@ let unsafe_next_tick_state host_function_registry (* Clear the values and the locals in the frame. *) let config = Wasm.Eval.config + ~stack_size_limit host_function_registry self (Tezos_lazy_containers.Lazy_vector.Int32Vector.empty ()) @@ -257,6 +258,7 @@ let unsafe_next_tick_state host_function_registry | Init {self; ast_module; init_kont; module_reg} -> let* init_kont = Wasm.Eval.init_step + ~stack_size_limit ~filter_exports:true ~check_module_exports:Exports_memory_0 ~module_reg @@ -307,10 +309,11 @@ let exn_to_stuck pvm_state exn = in Lwt.return (Stuck wasm_error) -let next_tick_state host_function_registry pvm_state = +let next_tick_state ~stack_size_limit host_function_registry pvm_state = let open Lwt_syntax in Lwt.catch - (fun () -> unsafe_next_tick_state host_function_registry pvm_state) + (fun () -> + unsafe_next_tick_state ~stack_size_limit host_function_registry pvm_state) (fun exn -> let+ tick_state = exn_to_stuck pvm_state exn in (pvm_state.durable, tick_state, Failing)) @@ -395,10 +398,12 @@ let clean_up_input_buffer buffers = (** [compute_step pvm_state] does one computation step on [pvm_state]. Returns the new state. *) -let compute_step_with_host_functions registry pvm_state = +let compute_step_with_host_functions ~stack_size_limit registry pvm_state = let open Lwt_syntax in (* Calculate the next tick state. *) - let* durable, tick_state, status = next_tick_state registry pvm_state in + let* durable, tick_state, status = + next_tick_state ~stack_size_limit registry pvm_state + in let current_tick = Z.succ pvm_state.current_tick in let last_top_level_call = next_last_top_level_call pvm_state status in let reboot_counter = next_reboot_counter pvm_state status in @@ -419,7 +424,10 @@ let compute_step_with_host_functions registry pvm_state = return pvm_state let compute_step pvm_state = - compute_step_with_host_functions Host_funcs.all pvm_state + compute_step_with_host_functions + ~stack_size_limit:Constants.stack_size_limit + Host_funcs.all + pvm_state let compute_step_with_debug ~write_debug pvm_state = let registry = @@ -427,7 +435,10 @@ let compute_step_with_debug ~write_debug pvm_state = | Builtins.Printer _ -> Host_funcs.all_debug ~write_debug | Noop -> Host_funcs.all in - compute_step_with_host_functions registry pvm_state + compute_step_with_host_functions + ~stack_size_limit:Constants.stack_size_limit + registry + pvm_state let input_request pvm_state = match pvm_state.tick_state with @@ -499,6 +510,7 @@ let compute_step_many_until ?(max_steps = 1L) ?reveal_builtins ?(write_debug = Builtins.Noop) should_continue = let open Lwt.Syntax in assert (max_steps > 0L) ; + let stack_size_limit = Constants.stack_size_limit in let host_function_registry = match write_debug with | Builtins.Printer _ -> Host_funcs.all_debug ~write_debug @@ -517,8 +529,14 @@ let compute_step_many_until ?(max_steps = 1L) ?reveal_builtins let* res = reveal_builtins.reveal_metadata () in reveal_step (Bytes.of_string res) pvm_state | _ -> - compute_step_with_host_functions host_function_registry pvm_state) - | None -> compute_step_with_host_functions host_function_registry + compute_step_with_host_functions + ~stack_size_limit + host_function_registry + pvm_state) + | None -> + compute_step_with_host_functions + ~stack_size_limit + host_function_registry in let rec go steps_left pvm_state = let* continue = should_continue pvm_state in @@ -547,7 +565,10 @@ let compute_step_many_until ?(max_steps = 1L) ?reveal_builtins (* Make sure we perform at least 1 step. The assertion above ensures that we were asked to perform at least 1. *) let* pvm_state = - compute_step_with_host_functions host_function_registry pvm_state + compute_step_with_host_functions + ~stack_size_limit + host_function_registry + pvm_state in go (Int64.pred max_steps) pvm_state in diff --git a/src/lib_webassembly/exec/eval.ml b/src/lib_webassembly/exec/eval.ml index 3fba1c6e559ae35914c350c5a2dbccb796c9ebdf..735d2a56320a180bf44dac875c59f8bb334b0f6b 100644 --- a/src/lib_webassembly/exec/eval.ml +++ b/src/lib_webassembly/exec/eval.ml @@ -432,7 +432,7 @@ let buffers ?(input = Input_buffer.alloc ()) ?(output = default_output_buffer ()) () = {input; output} -let config host_funcs ?frame_arity inst vs es = +let config ~stack_size_limit host_funcs ?frame_arity inst vs es = let frame = frame inst (Vector.empty ()) in let label_kont = label_kont @@ -444,7 +444,7 @@ let config host_funcs ?frame_arity inst vs es = { step_kont = SK_Start (frame_stack, Vector.empty ()); host_funcs; - stack_size_limit = 300; + stack_size_limit; } let plain e = Plain e.it @@ e.at @@ -1630,9 +1630,10 @@ let reveal_step reveal module_reg payload = (* Functions & Constants *) -let invoke ~module_reg ~caller ?(input = Input_buffer.alloc ()) - ?(output = default_output_buffer ()) ?(durable = Durable_storage.empty) - ?(init = false) host_funcs (func : func_inst) (vs : value list) : +let invoke ?(stack_size_limit = 300) ~module_reg ~caller + ?(input = Input_buffer.alloc ()) ?(output = default_output_buffer ()) + ?(durable = Durable_storage.empty) ?(init = false) host_funcs + (func : func_inst) (vs : value list) : (Durable_storage.t * value list) Lwt.t = let at = match func with Func.AstFunc (_, _, f) -> f.at | _ -> no_region in let (FuncType (ins, out)) = Func.type_of func in @@ -1652,6 +1653,7 @@ let invoke ~module_reg ~caller ?(input = Input_buffer.alloc ()) let n = Vector.num_elements out in let c = config + ~stack_size_limit host_funcs ~frame_arity:n inst @@ -1669,9 +1671,10 @@ let invoke ~module_reg ~caller ?(input = Input_buffer.alloc ()) type eval_const_kont = EC_Next of config | EC_Stop of value -let eval_const_kont inst (const : const) = +let eval_const_kont ~stack_size_limit inst (const : const) = let c = config + ~stack_size_limit (Host_funcs.empty ()) inst (Vector.empty ()) @@ -1711,8 +1714,8 @@ let create_memory (mem : memory) : memory_inst = type create_global_kont = global_type * eval_const_kont -let create_global_kont inst glob = - (glob.it.gtype, eval_const_kont inst glob.it.ginit) +let create_global_kont ~stack_size_limit inst glob = + (glob.it.gtype, eval_const_kont ~stack_size_limit inst glob.it.ginit) let create_global_completed (gtype, kont) = match eval_const_completed kont with @@ -1972,11 +1975,11 @@ let create_elem_completed : create_elem_kont -> elem_inst option = fun kont -> if tick_map_completed kont then Some (ref kont.map.destination) else None -let create_elem_step ~module_reg buffers inst : +let create_elem_step ~stack_size_limit ~module_reg buffers inst : create_elem_kont -> create_elem_kont Lwt.t = fun tick -> tick_map_step - (eval_const_kont inst) + (eval_const_kont ~stack_size_limit inst) (fun x -> match eval_const_completed x with | Some x -> Some (as_ref x) @@ -2026,11 +2029,13 @@ let section_next_init_kont : {exports = NameMap.create (); exports_memory_0 = false} ) let section_inner_kont : - type kont a b. module_key -> (kont, a, b) init_section -> a -> kont = - fun self sec x -> + type kont a b. + stack_size_limit:int -> module_key -> (kont, a, b) init_section -> a -> kont + = + fun ~stack_size_limit self sec x -> match sec with | Func -> Either.Left x - | Global -> create_global_kont self x + | Global -> create_global_kont ~stack_size_limit self x | Table -> Left x | Memory -> Left x @@ -2086,8 +2091,9 @@ type memory_export_rules = Exports_memory_0 | No_memory_export_rules exception Missing_memory_0_export -let init_step ~filter_exports ?(check_module_exports = No_memory_export_rules) - ~module_reg ~self buffers host_funcs (m : module_) = function +let init_step ~stack_size_limit ~filter_exports + ?(check_module_exports = No_memory_export_rules) ~module_reg ~self buffers + host_funcs (m : module_) = function | IK_Start exts -> (* Initialize as empty module. *) update_module_ref module_reg self empty_module_inst ; @@ -2124,7 +2130,7 @@ let init_step ~filter_exports ?(check_module_exports = No_memory_export_rules) | IK_Aggregate (inst0, sec, tick) -> let+ tick = tick_map_step - (section_inner_kont self sec) + (section_inner_kont ~stack_size_limit self sec) (section_inner_completed sec) (section_inner_step module_reg self buffers sec) tick @@ -2169,7 +2175,7 @@ let init_step ~filter_exports ?(check_module_exports = No_memory_export_rules) tick_map_step create_elem_kont create_elem_completed - (create_elem_step ~module_reg buffers self) + (create_elem_step ~stack_size_limit ~module_reg buffers self) tick in IK_Elems (inst0, tick) @@ -2216,7 +2222,9 @@ let init_step ~filter_exports ?(check_module_exports = No_memory_export_rules) | IK_Join_admin (inst0, tick) -> ( match join_completed tick with | Some res -> - Lwt.return (IK_Eval (config host_funcs self (Vector.empty ()) res)) + Lwt.return + (IK_Eval + (config ~stack_size_limit host_funcs self (Vector.empty ()) res)) | None -> let+ tick = join_step tick in IK_Join_admin (inst0, tick)) @@ -2230,14 +2238,15 @@ let init_step ~filter_exports ?(check_module_exports = No_memory_export_rules) IK_Eval config | IK_Stop -> raise (Init_step_error Init_step) -let init ~module_reg ~self buffers host_funcs (m : module_) (exts : extern list) - : module_inst Lwt.t = +let init ?(stack_size_limit = 300) ~module_reg ~self buffers host_funcs + (m : module_) (exts : extern list) : module_inst Lwt.t = let open Lwt.Syntax in let rec go = function | IK_Stop -> resolve_module_ref module_reg self | kont -> let* kont = init_step + ~stack_size_limit ~filter_exports:false ~module_reg ~self diff --git a/src/lib_webassembly/exec/eval.mli b/src/lib_webassembly/exec/eval.mli index 743fb626358b64dc790faa75dde76b73fda543bd..b2b9e851b266efc8bcac182be99c26cc6b957ba4 100644 --- a/src/lib_webassembly/exec/eval.mli +++ b/src/lib_webassembly/exec/eval.mli @@ -239,6 +239,7 @@ exception Missing_memory_0_export @raise Invalid_argument if called with [IK_Stop]. There is no transition from the terminal state. *) val init_step : + stack_size_limit:int -> filter_exports:bool -> ?check_module_exports:memory_export_rules -> module_reg:module_reg -> @@ -250,6 +251,7 @@ val init_step : init_kont Lwt.t val init : + ?stack_size_limit:int -> module_reg:module_reg -> self:module_key -> buffers -> @@ -259,6 +261,7 @@ val init : module_inst Lwt.t (* raises Link, Trap *) val invoke : + ?stack_size_limit:int -> module_reg:module_reg -> caller:module_key -> ?input:Input_buffer.t -> @@ -313,6 +316,7 @@ val reveal_step : config Lwt.t val config : + stack_size_limit:int -> Host_funcs.registry -> ?frame_arity:int32 (* The number of values returned by the computation *) -> module_key ->