diff --git a/nix/sources.json b/nix/sources.json index 806ea8273fc..10a7ada6a6c 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -6,10 +6,10 @@ "homepage": "", "owner": "dfinity", "repo": "candid", - "rev": "331217bae379cbebfa531a140f2186c99fae1425", - "sha256": "095w2a4lxy2gd7vfjxn7jszm4x3srw8xlxb1zzd096y6h047rxlj", + "rev": "34b4eb0b581bbf04902e20bf1370e3a293d1956f", + "sha256": "1gr49p938hzm8fq4r3n7j2lzfj0hmah5sb411sma24plnmwy7ljx", "type": "tarball", - "url": "https://github.com/dfinity/candid/archive/331217bae379cbebfa531a140f2186c99fae1425.tar.gz", + "url": "https://github.com/dfinity/candid/archive/34b4eb0b581bbf04902e20bf1370e3a293d1956f.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "esm": { diff --git a/rts/motoko-rts/src/idl.rs b/rts/motoko-rts/src/idl.rs index 21378c4a384..856e1926201 100644 --- a/rts/motoko-rts/src/idl.rs +++ b/rts/motoko-rts/src/idl.rs @@ -11,6 +11,11 @@ use core::cmp::min; use motoko_rts_macros::ic_mem_fn; +extern "C" { + // check instruction decoding limit, exported by moc + pub fn idl_limit_check(); +} + // // IDL constants // @@ -314,6 +319,9 @@ unsafe fn skip_any_vec(buf: *mut Buf, typtbl: *mut *mut u8, t: i32, count: u32) // makes no progress. No point in calling it over and over again. // (This is easier to detect this way than by analyzing the type table, // where we’d have to chase single-field-records.) + for _ in 1..count { + idl_limit_check(); + } return; } for _ in 1..count { @@ -332,6 +340,8 @@ unsafe extern "C" fn skip_any(buf: *mut Buf, typtbl: *mut *mut u8, t: i32, depth idl_trap_with("skip_any: too deeply nested record"); } + idl_limit_check(); //check decoding limits + if t < 0 { // Primitive type match t { @@ -525,9 +535,9 @@ unsafe extern "C" fn skip_fields(tb: *mut Buf, buf: *mut Buf, typtbl: *mut *mut } } -unsafe fn is_opt_reserved(typtbl: *mut *mut u8, end: *mut u8, t: i32) -> bool { +unsafe fn is_null_opt_reserved(typtbl: *mut *mut u8, end: *mut u8, t: i32) -> bool { if is_primitive_type(false, t) { - return t == IDL_PRIM_reserved; + return t == IDL_PRIM_null || t == IDL_PRIM_reserved; } // unfold t @@ -629,7 +639,7 @@ unsafe fn sub( for _ in 0..in1 { let t11 = sleb128_decode(&mut tb1); if in2 == 0 { - if !is_opt_reserved(typtbl1, end1, t11) { + if !is_null_opt_reserved(typtbl1, end1, t11) { break 'return_false; } } else { @@ -651,7 +661,7 @@ unsafe fn sub( for _ in 0..out2 { let t21 = sleb128_decode(&mut tb2); if out1 == 0 { - if !is_opt_reserved(typtbl2, end2, t21) { + if !is_null_opt_reserved(typtbl2, end2, t21) { break 'return_false; } } else { @@ -709,7 +719,7 @@ unsafe fn sub( let t21 = sleb128_decode(&mut tb2); if n1 == 0 { // check all remaining fields optional - if !is_opt_reserved(typtbl2, end2, t21) { + if !is_null_opt_reserved(typtbl2, end2, t21) { break 'return_false; } continue; @@ -725,7 +735,7 @@ unsafe fn sub( } }; if tag1 > tag2 { - if !is_opt_reserved(typtbl2, end2, t21) { + if !is_null_opt_reserved(typtbl2, end2, t21) { // missing, non_opt field break 'return_false; } diff --git a/src/codegen/compile.ml b/src/codegen/compile.ml index 29f2f8a857b..2a95e223c31 100644 --- a/src/codegen/compile.ml +++ b/src/codegen/compile.ml @@ -6341,7 +6341,12 @@ module RTS_Exports = struct E.add_export env (nr { name = Lib.Utf8.decode "moc_stable_mem_set_version"; edesc = nr (FuncExport (nr moc_stable_mem_set_version_fi)) - }) + }); + + E.add_export env (nr { + name = Lib.Utf8.decode "idl_limit_check"; + edesc = nr (FuncExport (nr (E.built_in env "idl_limit_check"))) + }) end (* RTS_Exports *) @@ -6531,14 +6536,6 @@ module MakeSerialization (Strm : Stream) = struct G.i (GlobalGet (nr (E.get_global env "__typtbl_idltyps"))) module Registers = struct - let register_globals env = - E.add_global32 env "@@rel_buf_opt" Mutable 0l; - E.add_global32 env "@@data_buf" Mutable 0l; - E.add_global32 env "@@ref_buf" Mutable 0l; - E.add_global32 env "@@typtbl" Mutable 0l; - E.add_global32 env "@@typtbl_end" Mutable 0l; - E.add_global32 env "@@typtbl_size" Mutable 0l - let get_rel_buf_opt env = G.i (GlobalGet (nr (E.get_global env "@@rel_buf_opt"))) let set_rel_buf_opt env = @@ -6568,6 +6565,154 @@ module MakeSerialization (Strm : Stream) = struct G.i (GlobalGet (nr (E.get_global env "@@typtbl_size"))) let set_typtbl_size env = G.i (GlobalSet (nr (E.get_global env "@@typtbl_size"))) + + let get_pseudo_instruction_counter env = + G.i (GlobalGet (nr (E.get_global env "@@pseudo_instruction_counter"))) + let set_pseudo_instruction_counter env = + G.i (GlobalSet (nr (E.get_global env "@@pseudo_instruction_counter"))) + + let get_limit_counter env = + G.i (GlobalGet (nr (E.get_global env "@@limit_counter"))) + let set_limit_counter env = + G.i (GlobalSet (nr (E.get_global env "@@limit_counter"))) + + let get_instruction_limit env = + G.i (GlobalGet (nr (E.get_global env "@@instruction_limit"))) + let set_instruction_limit env = + G.i (GlobalSet (nr (E.get_global env "@@instruction_limit"))) + + let get_instruction_factor env = + G.i (GlobalGet (nr (E.get_global env "@@instruction_factor"))) + let set_instruction_factor env = + G.i (GlobalSet (nr (E.get_global env "@@instruction_factor"))) + + let get_instruction_bias env = + G.i (GlobalGet (nr (E.get_global env "@@instruction_bias"))) + let set_instruction_bias env = + G.i (GlobalSet (nr (E.get_global env "@@instruction_bias"))) + + let get_allocation_limit env = + G.i (GlobalGet (nr (E.get_global env "@@allocation_limit"))) + let set_allocation_limit env = + G.i (GlobalSet (nr (E.get_global env "@@allocation_limit"))) + + let get_allocation_factor env = + G.i (GlobalGet (nr (E.get_global env "@@allocation_factor"))) + let set_allocation_factor env = + G.i (GlobalSet (nr (E.get_global env "@@allocation_factor"))) + + let get_allocation_bias env = + G.i (GlobalGet (nr (E.get_global env "@@allocation_bias"))) + let set_allocation_bias env = + G.i (GlobalSet (nr (E.get_global env "@@allocation_bias"))) + + (* interval for checking instruction counter *) + let idl_limit_interval = 32l (* TUNE *) + let idl_instruction_factor = 1000L (* TUNE *) + let idl_instruction_bias = 10_000_000L (* TUNE *) + let idl_pseudo_cost = 100L (* TUNE *) + let scale bytes = Int64.mul bytes (Int64.of_int32(Int32.div Heap.word_size 4l)) + let idl_allocation_factor = scale(64L) (* TUNE *) + let idl_allocation_bias = scale(1_000_000L) (* TUNE *) + + let idl_instruction_counter env = + match E.mode env with + | Flags.ICMode | Flags.RefMode -> + compile_unboxed_const 0l ^^ + IC.performance_counter env + | Flags.WASIMode | Flags.WasmMode -> + get_pseudo_instruction_counter env + + let simulate_instruction_counter env = + match E.mode env with + | Flags.ICMode | Flags.RefMode -> + G.nop + | Flags.WASIMode | Flags.WasmMode -> + get_pseudo_instruction_counter env ^^ + compile_const_64 idl_pseudo_cost ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + set_pseudo_instruction_counter env + + let reset_instruction_limit env get_blob get_rel_buf_opt = + get_rel_buf_opt ^^ + G.if0 begin (* Candid deserialization *) + (* set instruction limit *) + idl_instruction_counter env ^^ + get_blob ^^ + Blob.len env ^^ + G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + get_instruction_factor env ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ + get_instruction_bias env ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + set_instruction_limit env ^^ + (* set allocation limit *) + Heap.get_total_allocation env ^^ + get_blob ^^ + Blob.len env ^^ + G.i (Convert (Wasm.Values.I64 I64Op.ExtendUI32)) ^^ + get_allocation_factor env ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Mul)) ^^ + get_allocation_bias env ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + G.i (Binary (Wasm.Values.I64 I64Op.Add)) ^^ + set_allocation_limit env + end + begin (* Extended candid/ Destabilization *) + G.nop + end + + let idl_limit_check env = + G.i (Call (nr (E.built_in env "idl_limit_check"))) + + let register_globals env = + E.add_global32 env "@@rel_buf_opt" Mutable 0l; + E.add_global32 env "@@data_buf" Mutable 0l; + E.add_global32 env "@@ref_buf" Mutable 0l; + E.add_global32 env "@@typtbl" Mutable 0l; + E.add_global32 env "@@typtbl_end" Mutable 0l; + E.add_global32 env "@@typtbl_size" Mutable 0l; + E.add_global32 env "@@limit_counter" Mutable idl_limit_interval; + E.add_global64 env "@@instruction_factor" Mutable idl_instruction_factor; + E.add_global64 env "@@instruction_bias" Mutable idl_instruction_bias; + E.add_global64 env "@@allocation_factor" Mutable idl_allocation_factor; + E.add_global64 env "@@allocation_bias" Mutable idl_allocation_bias; + (match E.mode env with + | Flags.ICMode | Flags.RefMode -> + () + | Flags.WASIMode | Flags.WasmMode -> + E.add_global64 env "@@pseudo_instruction_counter" Mutable 0L); + E.add_global64 env "@@instruction_limit" Mutable 0L; + E.add_global64 env "@@allocation_limit" Mutable 0L; + Func.define_built_in env "idl_limit_check" [] [] (fun env -> + get_rel_buf_opt env ^^ + G.if0 begin (* Candid deserialization *) + get_limit_counter env ^^ + G.if0 + begin (* non-zero: Decrement counter *) + get_limit_counter env ^^ + compile_sub_const 1l ^^ + set_limit_counter env + end + begin (* zero: Check limit and reset counter *) + idl_instruction_counter env ^^ + get_instruction_limit env ^^ + G.i (Compare (Wasm.Values.I64 I64Op.LeU)) ^^ + E.else_trap_with env "IDL error: exceeded instruction limit" ^^ + Heap.get_total_allocation env ^^ + get_allocation_limit env ^^ + G.i (Compare (Wasm.Values.I64 I64Op.LeU)) ^^ + E.else_trap_with env "IDL error: exceeded allocation limit" ^^ + (* Reset counter *) + compile_unboxed_const idl_limit_interval ^^ + set_limit_counter env + end ^^ + simulate_instruction_counter env + end begin (* Extended Candid/Destabilization *) + G.nop + end) + end open Typ_hash @@ -7224,6 +7369,10 @@ module MakeSerialization (Strm : Stream) = struct let get_typtbl_end = Registers.get_typtbl_end env in let get_typtbl_size = Registers.get_typtbl_size env in + (* Check instruction limit *) + + Registers.idl_limit_check env ^^ + (* Check recursion depth (protects against empty record etc.) *) (* Factor 2 because at each step, the expected type could go through one level of opt that is not present in the value type @@ -7642,7 +7791,7 @@ module MakeSerialization (Strm : Stream) = struct end begin match normalize t with - | Opt _ | Any -> Opt.null_lit env + | Prim Null | Opt _ | Any -> Opt.null_lit env | _ -> coercion_failed "IDL error: did not find tuple field in record" end ) ts ^^ @@ -7671,7 +7820,7 @@ module MakeSerialization (Strm : Stream) = struct end begin match normalize f.typ with - | Opt _ | Any -> Opt.null_lit env + | Prim Null | Opt _ | Any -> Opt.null_lit env | _ -> coercion_failed (Printf.sprintf "IDL error: did not find field %s in record" f.lab) end ) (sort_by_hash fs)) ^^ @@ -7978,6 +8127,16 @@ module MakeSerialization (Strm : Stream) = struct (* Allocate memo table, if necessary *) with_rel_buf_opt env extended (get_typtbl_size_ptr ^^ load_unskewed_ptr) (fun get_rel_buf_opt -> + begin + (* set up invariant register arguments *) + get_rel_buf_opt ^^ Registers.set_rel_buf_opt env ^^ + get_data_buf ^^ Registers.set_data_buf env ^^ + get_ref_buf ^^ Registers.set_ref_buf env ^^ + get_typtbl_ptr ^^ load_unskewed_ptr ^^ Registers.set_typtbl env ^^ + get_maintyps_ptr ^^ load_unskewed_ptr ^^ Registers.set_typtbl_end env ^^ + get_typtbl_size_ptr ^^ load_unskewed_ptr ^^ Registers.set_typtbl_size env ^^ + Registers.reset_instruction_limit env get_blob get_rel_buf_opt + end ^^ (* set up a dedicated read buffer for the list of main types *) ReadBuf.alloc env (fun get_main_typs_buf -> @@ -7988,7 +8147,7 @@ module MakeSerialization (Strm : Stream) = struct G.concat_map (fun t -> let can_recover, default_or_trap = Type.( match normalize t with - | Opt _ | Any -> + | Prim Null | Opt _ | Any -> (Bool.lit true, fun msg -> Opt.null_lit env) | _ -> (get_can_recover, fun msg -> @@ -8002,15 +8161,6 @@ module MakeSerialization (Strm : Stream) = struct G.if1 I32Type (default_or_trap ("IDL error: too few arguments " ^ ts_name)) (begin - begin - (* set up invariant register arguments *) - get_rel_buf_opt ^^ Registers.set_rel_buf_opt env ^^ - get_data_buf ^^ Registers.set_data_buf env ^^ - get_ref_buf ^^ Registers.set_ref_buf env ^^ - get_typtbl_ptr ^^ load_unskewed_ptr ^^ Registers.set_typtbl env ^^ - get_maintyps_ptr ^^ load_unskewed_ptr ^^ Registers.set_typtbl_end env ^^ - get_typtbl_size_ptr ^^ load_unskewed_ptr ^^ Registers.set_typtbl_size env - end ^^ (* set up variable frame arguments *) Stack.with_frame env "frame_ptr" 3l (fun () -> (* idltyp *) @@ -11730,6 +11880,28 @@ and compile_prim_invocation (env : E.t) ae p es at = | OtherPrim "btstInt64", [_;_] -> const_sr (SR.UnboxedWord64 Type.Int64) (Word64.btst_kernel env) + | OtherPrim "setCandidLimits", [e1; e2; e3; e4] -> + SR.unit, + compile_exp_as env ae (SR.UnboxedWord64 Type.Nat64) e1 ^^ + Serialization.Registers.set_instruction_factor env ^^ + compile_exp_as env ae (SR.UnboxedWord64 Type.Nat64) e2 ^^ + Serialization.Registers.set_instruction_bias env ^^ + compile_exp_as env ae (SR.UnboxedWord64 Type.Nat64) e3 ^^ + Serialization.Registers.set_allocation_factor env ^^ + compile_exp_as env ae (SR.UnboxedWord64 Type.Nat64) e4 ^^ + Serialization.Registers.set_allocation_bias env + + | OtherPrim "getCandidLimits", [] -> + SR.UnboxedTuple 4, + Serialization.Registers.get_instruction_factor env ^^ + BoxedWord64.box env Type.Nat64 ^^ + Serialization.Registers.get_instruction_bias env ^^ + BoxedWord64.box env Type.Nat64 ^^ + Serialization.Registers.get_allocation_factor env ^^ + BoxedWord64.box env Type.Nat64 ^^ + Serialization.Registers.get_allocation_bias env ^^ + BoxedWord64.box env Type.Nat64 + (* Coercions for abstract types *) | CastPrim (_,_), [e] -> compile_exp env ae e diff --git a/src/mo_values/prim.ml b/src/mo_values/prim.ml index 64a1ac0e4e2..7830bd3f015 100644 --- a/src/mo_values/prim.ml +++ b/src/mo_values/prim.ml @@ -382,4 +382,12 @@ let prim trap = | "canister_version" -> fun _ v k -> as_unit v; k (Nat64 (Numerics.Nat64.of_int 42)) + (* fake *) + | "setCandidLimits" -> + fun _ v k -> k unit + | "getCandidLimits" -> + fun _ v k -> k (Tup [ + Nat64 Numerics.Nat64.zero; Nat64 Numerics.Nat64.zero; + Nat64 Numerics.Nat64.zero; Nat64 Numerics.Nat64.zero]) + | s -> trap.trap ("Value.prim: " ^ s) diff --git a/src/prelude/prim.mo b/src/prelude/prim.mo index b750b75dfad..f14a4a6cdb4 100644 --- a/src/prelude/prim.mo +++ b/src/prelude/prim.mo @@ -501,6 +501,24 @@ let call_raw = @call_raw; func performanceCounter(counter : Nat32) : Nat64 = (prim "performanceCounter" : (Nat32) -> Nat64) counter; + +// Candid configuration +func setCandidLimits ( + { instructions: { factor: Nat64; bias : Nat64 }; + allocations: { factor: Nat64; bias : Nat64 } } + ) { + (prim "setCandidLimits" : (Nat64, Nat64, Nat64, Nat64) -> ()) + (instructions.factor, instructions.bias, allocations.factor, allocations.bias) +}; + +func getCandidLimits() : + { instructions: { factor: Nat64; bias : Nat64}; + allocations: { factor: Nat64; bias : Nat64 } } { + let (f1, b1, f2, b2) = (prim "getCandidLimits" : () -> (Nat64, Nat64, Nat64, Nat64)) (); + { instructions = { factor = f1; bias = b1 }; + allocations = { factor = f2; bias = b2 } } +}; + // predicates for motoko-san func forall(f: T -> Bool): Bool { diff --git a/test/bench/ok/bignum.drun-run-opt.ok b/test/bench/ok/bignum.drun-run-opt.ok index 007530eef47..f0b9658043d 100644 --- a/test/bench/ok/bignum.drun-run-opt.ok +++ b/test/bench/ok/bignum.drun-run-opt.ok @@ -2,5 +2,5 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a000000000000000001 ingress Completed: Reply: 0x4449444c0000 debug.print: {cycles = 2_512_723; size = +59_652} ingress Completed: Reply: 0x4449444c0000 -debug.print: {cycles = 107_695_051; size = +1_817_872} +debug.print: {cycles = 107_695_562; size = +1_817_872} ingress Completed: Reply: 0x4449444c0000 diff --git a/test/bench/ok/bignum.drun-run.ok b/test/bench/ok/bignum.drun-run.ok index b037729f278..ba5072c106a 100644 --- a/test/bench/ok/bignum.drun-run.ok +++ b/test/bench/ok/bignum.drun-run.ok @@ -2,5 +2,5 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a000000000000000001 ingress Completed: Reply: 0x4449444c0000 debug.print: {cycles = 2_619_856; size = +59_652} ingress Completed: Reply: 0x4449444c0000 -debug.print: {cycles = 107_890_020; size = +1_817_872} +debug.print: {cycles = 107_890_554; size = +1_817_872} ingress Completed: Reply: 0x4449444c0000 diff --git a/test/bench/ok/heap-32.drun-run-opt.ok b/test/bench/ok/heap-32.drun-run-opt.ok index faf3bfb29da..f5ae73261f4 100644 --- a/test/bench/ok/heap-32.drun-run-opt.ok +++ b/test/bench/ok/heap-32.drun-run-opt.ok @@ -1,5 +1,5 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 ingress Completed: Reply: 0x4449444c0000 debug.print: (50_227, +29_863_068, 708_174_952) -debug.print: (50_070, +32_992_212, 766_613_680) +debug.print: (50_070, +32_992_212, 766_613_760) ingress Completed: Reply: 0x4449444c0000 diff --git a/test/bench/ok/heap-32.drun-run.ok b/test/bench/ok/heap-32.drun-run.ok index f51bd0ff0c3..b67b6f2e41b 100644 --- a/test/bench/ok/heap-32.drun-run.ok +++ b/test/bench/ok/heap-32.drun-run.ok @@ -1,5 +1,5 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 ingress Completed: Reply: 0x4449444c0000 debug.print: (50_227, +29_863_068, 769_000_085) -debug.print: (50_070, +32_992_212, 830_427_376) +debug.print: (50_070, +32_992_212, 830_427_500) ingress Completed: Reply: 0x4449444c0000 diff --git a/test/fail/ok/no-timer-canc.tc.ok b/test/fail/ok/no-timer-canc.tc.ok index 945c0494309..774d4c52078 100644 --- a/test/fail/ok/no-timer-canc.tc.ok +++ b/test/fail/ok/no-timer-canc.tc.ok @@ -114,6 +114,12 @@ no-timer-canc.mo:3.10-3.21: type error [M0119], object field cancelTimer is not floatToText : Float -> Text; floatTrunc : Float -> Float; forall : (T -> Bool) -> Bool; + getCandidLimits : + () -> + { + allocations : {bias : Nat64; factor : Nat64}; + instructions : {bias : Nat64; factor : Nat64} + }; getCertificate : () -> ?Blob; hashBlob : Blob -> Nat32; idlHash : Text -> Nat32; @@ -214,6 +220,12 @@ no-timer-canc.mo:3.10-3.21: type error [M0119], object field cancelTimer is not rts_stable_memory_size : () -> Nat; rts_total_allocation : () -> Nat; rts_version : () -> Text; + setCandidLimits : + { + allocations : {bias : Nat64; factor : Nat64}; + instructions : {bias : Nat64; factor : Nat64} + } -> + (); setCertifiedData : Blob -> (); shiftLeft : (Nat, Nat32) -> Nat; shiftRight : (Nat, Nat32) -> Nat; diff --git a/test/fail/ok/no-timer-set.tc.ok b/test/fail/ok/no-timer-set.tc.ok index 5b4762cf378..9368bfdbb95 100644 --- a/test/fail/ok/no-timer-set.tc.ok +++ b/test/fail/ok/no-timer-set.tc.ok @@ -114,6 +114,12 @@ no-timer-set.mo:3.10-3.18: type error [M0119], object field setTimer is not cont floatToText : Float -> Text; floatTrunc : Float -> Float; forall : (T -> Bool) -> Bool; + getCandidLimits : + () -> + { + allocations : {bias : Nat64; factor : Nat64}; + instructions : {bias : Nat64; factor : Nat64} + }; getCertificate : () -> ?Blob; hashBlob : Blob -> Nat32; idlHash : Text -> Nat32; @@ -214,6 +220,12 @@ no-timer-set.mo:3.10-3.18: type error [M0119], object field setTimer is not cont rts_stable_memory_size : () -> Nat; rts_total_allocation : () -> Nat; rts_version : () -> Text; + setCandidLimits : + { + allocations : {bias : Nat64; factor : Nat64}; + instructions : {bias : Nat64; factor : Nat64} + } -> + (); setCertifiedData : Blob -> (); shiftLeft : (Nat, Nat32) -> Nat; shiftRight : (Nat, Nat32) -> Nat; diff --git a/test/run-drun/idl-candid-config.mo b/test/run-drun/idl-candid-config.mo new file mode 100644 index 00000000000..2df14222a74 --- /dev/null +++ b/test/run-drun/idl-candid-config.mo @@ -0,0 +1,16 @@ +import { setCandidLimits; getCandidLimits } = "mo:⛔"; + +actor { + + let limits = { instructions = { factor = 1 : Nat64 ; bias = 3 : Nat64 }; + allocations = { factor = 2 : Nat64; bias = 4 : Nat64 } }; + + setCandidLimits(limits); + assert getCandidLimits() == limits; + +} + +//SKIP run-low +//SKIP run +//SKIP run-ir +//SKIP ic-ref-run diff --git a/test/run-drun/idl-limits-fine.mo b/test/run-drun/idl-limits-fine.mo new file mode 100644 index 00000000000..fbaf9eaa328 --- /dev/null +++ b/test/run-drun/idl-limits-fine.mo @@ -0,0 +1,40 @@ +import Region "stable-region/Region"; +import Prim "mo:prim"; + +// shows that we can decode up to 15MB of coarse grained data before +// exceeding the candid decoding limit +actor { + + let page : [Nat16] = + Prim.Array_tabulate(65536/4, func i { + Prim.natToNat16(i)}); + + var cnt = 0; + label l while (cnt < 64) { + let a = Prim.Array_tabulate<[Nat16]>(cnt*16, func i {page}); + let b = to_candid (a); + if (b.size() > 10_000_000) break l; + Prim.debugPrint(debug_show {bytes=b.size()}); + let c1 = Prim.performanceCounter(0); + let ?_ = from_candid b : ?[[Nat16]]; + let c2 = Prim.performanceCounter(0); + let diff = c2 - c1; + Prim.debugPrint(debug_show { + bytes = b.size(); + MB = cnt; +// too noisy for tests +// instrs = diff; +// instr_per_byte = Prim.nat64ToNat diff / b.size() + }); + cnt += 1; + }; + +} + +//SKIP run-low +//SKIP run-ir +//SKIP run +//SKIP ic-ref + + + diff --git a/test/run-drun/idl-limits.mo b/test/run-drun/idl-limits.mo new file mode 100644 index 00000000000..a05d74441b2 --- /dev/null +++ b/test/run-drun/idl-limits.mo @@ -0,0 +1,41 @@ +import Region "stable-region/Region"; +import Prim "mo:prim"; + +// shows that we can decode up to 15MB of coarse grained data before +// exceeding the candid decoding limit +actor { + + let r = Region.new(); + let pages : Nat64 = 1; + let 0 = Region.grow(r, pages); + let page = Region.loadBlob(r, 0, Prim.nat64ToNat(pages*65536-1)); + + var cnt = 0; + label l while (cnt < 256) { + let a = Prim.Array_tabulate(cnt*16, func i {page}); + let b = to_candid (a); + if (b.size() > 10_000_000) break l; + Prim.debugPrint(debug_show {bytes=b.size()}); + let c1 = Prim.performanceCounter(0); + let ?_ = from_candid b : ?[Blob]; + let c2 = Prim.performanceCounter(0); + let diff = c2 - c1; + Prim.debugPrint(debug_show { + bytes = b.size(); + MB = cnt; +// too noisy for tests +// instrs = diff ; +// instr_per_byte = Prim.nat64ToNat diff / b.size() + }); + cnt += 1; + }; + +} + +//SKIP run-low +//SKIP run-ir +//SKIP run +//SKIP ic-ref + + + diff --git a/test/run-drun/idl-spacebomb.mo b/test/run-drun/idl-spacebomb.mo new file mode 100644 index 00000000000..997f414a743 --- /dev/null +++ b/test/run-drun/idl-spacebomb.mo @@ -0,0 +1,224 @@ +import { debugPrint; errorMessage; call_raw; principalOfActor; charToText; performanceCounter } "mo:⛔"; + +// Space bomb tests + +// Messages in this test all take a lot of time, memory and stack space to decode. +// With infinite resources, these are all valid Candid messages. +// When using Candid in a resource limited environment, for example one consensus round in a blockchain, +// an implementation with self-metering should reject these messages relatively early +// without going through the whole deserialisation process. + +// \80\94\eb\dc\03 is 1000_000_000 +// \80\ad\e2\04 is 10_000_000 +// \ff\ff\3f is 1_048_575 +// \80\b5\18 is 400_000 + +// Tests manually ported from Candid test suite +// https://github.com/dfinity/candid/blob/master/test/spacebomb.test.did + +// Currently we cannot run this particular Candid test suite +// because we rely on IC performance_counter(0) to limit execution. +// and the test suite is run on wasmtime (sans perf counter). + +actor this { + + func toHex(b : Blob) : Text { + let s = debug_show b; + var t = ""; + for (c in s.chars()) { + if (not (c == '\"' or c == '\\')) { + t #= charToText(c) + } + }; + t + }; + + func assert_low_cost() { + let limit : Nat64 = 50_000; + let c = performanceCounter(0); + if (c > limit) debugPrint (debug_show c); + assert performanceCounter(0) < limit; + debugPrint("decoded at low cost"); + }; + + public func vec_null_extra_argument() : async () { + assert_low_cost(); + }; + + public func vec_reserved_extra_argument() : async () { + assert_low_cost(); + }; + + public func zero_sized_record_extra_argument() : async () { + assert_low_cost(); + }; + + public func vec_vec_null_extra_argument() : async () { + assert_low_cost(); + }; + + public func vec_record_emp_extra_argument() : async () { + assert_low_cost(); + }; + + public func vec_opt_record_with_2_20_null_extra_argument() : async () { + assert_low_cost(); + }; + + public func vec_null_not_ignored(_ : [?Nat]) : async () { + assert_low_cost(); + }; + + public func vec_reserved_not_ignored(_ : [Any]) : async () { + assert_low_cost(); + }; + + // this test may be broken + public func zero_sized_record_not_ignored(_ : [{_0_: Null; _1_: {_0_:Any}; _2_: {}}]) : async () { + assert_low_cost(); + }; + + public func vec_vec_null_not_ignored(_ : [[Null]]) : async () { + assert_low_cost(); + }; + + // this test may be broken + public func vec_record_emp_not_ignored(_ : [{}]) : async () { + assert_low_cost(); + }; + + public func vec_null_subtyping(_ : ?Nat) : async () { + assert_low_cost(); + }; + + public func vec_reserved_subtyping(_ : ?Nat) : async () { + assert_low_cost(); + }; + + public func zero_sized_record_subtyping(_ : ?Nat) : async () { + assert_low_cost(); + }; + + public func vec_vec_null_subtyping(_ : [?Nat]) : async () { + assert_low_cost(); + }; + + public func vec_record_emp_subtyping(_ : ?Nat) : async () { + assert_low_cost(); + }; + + public func vec_opt_record_with_2_20_null_subtyping(_ : [?{}]) : async () { + assert_low_cost(); + }; + + func test(m : Text, blobs : [Blob]) : async* () { + let p = principalOfActor(this); + for (blob in blobs.vals()) { + debugPrint (debug_show { function = m; hex = toHex blob}); + try { + ignore await call_raw(p, m, blob); + } + catch e { + debugPrint(errorMessage(e)); + } + } + }; + + public func go() : async () { + + // Plain decoding (unused arguments) + await* test("vec_null_extra_argument", [ + "DIDL\01\6d\7f\01\00\80\94\eb\dc\03" + ]); + + await* test("vec_reserved_extra_argument", [ + "DIDL\01\6d\70\01\00\80\94\eb\dc\03" + ]); + + await* test("zero_sized_record_extra_argument", [ + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\94\eb\dc\03" + ]); + + await* test("vec_vec_null_extra_argument", [ + "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" + ]); + + await* test("vec_record_emp_extra_argument", [ + "DIDL\02\6d\01\6c\00\01\00\80\ad\e2\04" + ]); + + await* test("vec_opt_record_with_2_20_null_extra_argument", [ + "DIDL\17\6c\02\01\7f\02\7f\6c\02\01\00\02\00\6c\02\00\01\01\01\6c\02\00\02\01\02\6c\02\00\03\01\03\6c\02\00\04\01\04\6c\02\00\05\01\05\6c\02\00\06\01\06\6c\02\00\07\01\07\6c\02\00\08\01\08\6c\02\00\09\01\09\6c\02\00\0a\01\0a\6c\02\00\0b\01\0b\6c\02\00\0c\01\0c\6c\02\00\0d\02\0d\6c\02\00\0e\01\0e\6c\02\00\0f\01\0f\6c\02\00\10\01\10\6c\02\00\11\01\11\6c\02\00\12\01\12\6c\02\00\13\01\13\6e\14\6d\15\01\16\05\01\01\01\01\01" + ]); + + // Decoding to actual type + await* test("vec_null_not_ignored", [ + "DIDL\01\6d\7f\01\00\80\94\eb\dc\03", + "DIDL\01\6d\7f\01\00\80\ad\e2\04", + "DIDL\01\6d\7f\01\00\ff\ff\3f", + "DIDL\01\6d\7f\01\00\80\bf\18" + ]); + + await* test("vec_reserved_not_ignored", [ + "DIDL\01\6d\70\01\00\80\94\eb\dc\03" : Blob, + "DIDL\01\6d\70\01\00\80\ad\e2\04" : Blob, + "DIDL\01\6d\70\01\00\ff\ff\3f" : Blob, + "DIDL\01\6d\70\01\00\80\bf\18" : Blob, + ]); + + await* test("zero_sized_record_not_ignored", [ + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\94\eb\dc\03", + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\ad\e2\04", + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\ff\ff\3f", + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\b5\18", + ]); + + await* test("vec_vec_null_not_ignored", [ + "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" + ]); + + await* test("vec_record_emp_not_ignored", [ + "DIDL\02\6d\01\6c\00\01\00\80\ad\e2\04" + ]); + + // Decoding under opt + await* test("vec_null_subtyping", [ + "DIDL\01\6d\7f\01\00\80\94\eb\dc\03" : Blob, + "DIDL\01\6d\7f\01\00\80\ad\e2\04" : Blob, + "DIDL\01\6d\7f\01\00\ff\ff\3f" : Blob, + "DIDL\01\6d\7f\01\00\80\bf\18" : Blob, + ]); + + await* test("vec_reserved_subtyping", [ + "DIDL\01\6d\70\01\00\80\94\eb\dc\03" : Blob, + "DIDL\01\6d\70\01\00\80\ad\e2\04" : Blob, + "DIDL\01\6d\70\01\00\ff\ff\3f" : Blob, + "DIDL\01\6d\70\01\00\80\bf\18" : Blob, + ]); + + await* test("zero_sized_record_subtyping", [ + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\94\eb\dc\03", + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\ad\e2\04", + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\ff\ff\3f", + "DIDL\04\6c\03\00\7f\01\01\02\02\6c\01\00\70\6c\00\6d\00\01\03\80\b5\18", + ]); + + await* test("vec_vec_null_subtyping", [ + "DIDL\02\6d\01\6d\7f\01\00\05\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f\ff\ff\3f" + ]); + + await* test("vec_record_emp_subtyping", [ + "DIDL\02\6d\01\6c\00\01\00\80\ad\e2\04" + ]); + + await* test("vec_opt_record_with_2_20_null_subtyping", [ + "DIDL\17\6c\02\01\7f\02\7f\6c\02\01\00\02\00\6c\02\00\01\01\01\6c\02\00\02\01\02\6c\02\00\03\01\03\6c\02\00\04\01\04\6c\02\00\05\01\05\6c\02\00\06\01\06\6c\02\00\07\01\07\6c\02\00\08\01\08\6c\02\00\09\01\09\6c\02\00\0a\01\0a\6c\02\00\0b\01\0b\6c\02\00\0c\01\0c\6c\02\00\0d\02\0d\6c\02\00\0e\01\0e\6c\02\00\0f\01\0f\6c\02\00\10\01\10\6c\02\00\11\01\11\6c\02\00\12\01\12\6c\02\00\13\01\13\6e\14\6d\15\01\16\05\01\01\01\01\01" + ]); + +} + +} +//CALL ingress go "DIDL\x00\x00" +//SKIP run +//SKIP run-ir +//SKIP run-low diff --git a/test/run-drun/idl-sub-opt-any-record.mo b/test/run-drun/idl-sub-opt-any-record.mo index 47b32168d47..b32407ded2c 100644 --- a/test/run-drun/idl-sub-opt-any-record.mo +++ b/test/run-drun/idl-sub-opt-any-record.mo @@ -19,17 +19,17 @@ actor this { public func go() : async () { let t = debug_show (Prim.principalOfActor(this)); - // appending Null not ok + // appending Null ok do { let this = actor (t) : actor { send_f0 : (shared {a : Int; n : Null } -> async {b : Bool; x : Null}) -> async (); }; try { await this.send_f0(f0_1_a); - Prim.debugPrint "wrong_0_1_a"; + Prim.debugPrint "ok_0_1_a"; } catch e { - Prim.debugPrint "ok_0_1_a"; + Prim.debugPrint "wrong_0_1_a"; } }; diff --git a/test/run-drun/idl-sub-opt-any.mo b/test/run-drun/idl-sub-opt-any.mo index b614db34734..881ef8b1da1 100644 --- a/test/run-drun/idl-sub-opt-any.mo +++ b/test/run-drun/idl-sub-opt-any.mo @@ -21,17 +21,17 @@ actor this { public func go() : async () { let t = debug_show (Prim.principalOfActor(this)); - // appending Null not ok + // appending Null ok do { let this = actor (t) : actor { send_f0 : (shared (a : Int, n : Null) -> async (Bool, Null)) -> async (); }; try { await this.send_f0(f0_1_a); - Prim.debugPrint "wrong_0_1_a"; + Prim.debugPrint "ok_0_1_a"; } catch e { - Prim.debugPrint "ok_0_1_a"; + Prim.debugPrint "wrong_0_1_a"; } }; diff --git a/test/run-drun/max-stack-variant.mo b/test/run-drun/max-stack-variant.mo index 692a8e0f431..a5c21dde983 100644 --- a/test/run-drun/max-stack-variant.mo +++ b/test/run-drun/max-stack-variant.mo @@ -1,9 +1,10 @@ //MOC-FLAG --compacting-gc --rts-stack-pages 32 -measure-rts-stack -import { errorMessage; debugPrint; } = "mo:⛔"; +import { errorMessage; debugPrint; setCandidLimits} = "mo:⛔"; actor { let expectedMinimumSize = 31_000; - + setCandidLimits{ instructions = {factor = 0; bias = 5_000_000_000 }; + allocations = {factor = 0; bias = 5_000_000_000 } }; public func ser() : async () { await go(false) }; public func deser() : async () { await go(true) }; @@ -37,9 +38,9 @@ actor { done := true } }; - + assert(i > expectedMinimumSize); - + let b = to_candid(l); debugPrint("serialized"); diff --git a/test/run-drun/max-stack.mo b/test/run-drun/max-stack.mo index 74775b0e191..12c0c802628 100644 --- a/test/run-drun/max-stack.mo +++ b/test/run-drun/max-stack.mo @@ -1,9 +1,10 @@ //MOC-FLAG --compacting-gc --rts-stack-pages 32 -measure-rts-stack -import { errorMessage; debugPrint; } = "mo:⛔"; +import { errorMessage; debugPrint; setCandidLimits } = "mo:⛔"; actor { let expectedMinimumSize = 35_000; - + setCandidLimits{ instructions = {factor = 0; bias = 5_000_000_000 }; + allocations = {factor = 0; bias = 5_000_000_000 } }; public func ser() : async () { await go(false) }; public func deser() : async () { await go(true) }; @@ -27,7 +28,6 @@ actor { if deserialize from_candid(b) else null; - () }; } catch e { @@ -37,7 +37,7 @@ actor { }; assert i > expectedMinimumSize; - + let b = to_candid(l); debugPrint("serialized"); diff --git a/test/run-drun/ok/idl-candid-config.drun-run.ok b/test/run-drun/ok/idl-candid-config.drun-run.ok new file mode 100644 index 00000000000..a6f776f43c6 --- /dev/null +++ b/test/run-drun/ok/idl-candid-config.drun-run.ok @@ -0,0 +1,2 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-limits-fine.drun-run.ok b/test/run-drun/ok/idl-limits-fine.drun-run.ok new file mode 100644 index 00000000000..095161ef2b0 --- /dev/null +++ b/test/run-drun/ok/idl-limits-fine.drun-run.ok @@ -0,0 +1,42 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +debug.print: {bytes = 12} +debug.print: {MB = 0; bytes = 12} +debug.print: {bytes = 524_348} +debug.print: {MB = 1; bytes = 524_348} +debug.print: {bytes = 1_048_684} +debug.print: {MB = 2; bytes = 1_048_684} +debug.print: {bytes = 1_573_020} +debug.print: {MB = 3; bytes = 1_573_020} +debug.print: {bytes = 2_097_356} +debug.print: {MB = 4; bytes = 2_097_356} +debug.print: {bytes = 2_621_692} +debug.print: {MB = 5; bytes = 2_621_692} +debug.print: {bytes = 3_146_028} +debug.print: {MB = 6; bytes = 3_146_028} +debug.print: {bytes = 3_670_364} +debug.print: {MB = 7; bytes = 3_670_364} +debug.print: {bytes = 4_194_701} +debug.print: {MB = 8; bytes = 4_194_701} +debug.print: {bytes = 4_719_037} +debug.print: {MB = 9; bytes = 4_719_037} +debug.print: {bytes = 5_243_373} +debug.print: {MB = 10; bytes = 5_243_373} +debug.print: {bytes = 5_767_709} +debug.print: {MB = 11; bytes = 5_767_709} +debug.print: {bytes = 6_292_045} +debug.print: {MB = 12; bytes = 6_292_045} +debug.print: {bytes = 6_816_381} +debug.print: {MB = 13; bytes = 6_816_381} +debug.print: {bytes = 7_340_717} +debug.print: {MB = 14; bytes = 7_340_717} +debug.print: {bytes = 7_865_053} +debug.print: {MB = 15; bytes = 7_865_053} +debug.print: {bytes = 8_389_389} +debug.print: {MB = 16; bytes = 8_389_389} +debug.print: {bytes = 8_913_725} +debug.print: {MB = 17; bytes = 8_913_725} +debug.print: {bytes = 9_438_061} +debug.print: {MB = 18; bytes = 9_438_061} +debug.print: {bytes = 9_962_397} +debug.print: {MB = 19; bytes = 9_962_397} +ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-limits-fine.tc.ok b/test/run-drun/ok/idl-limits-fine.tc.ok new file mode 100644 index 00000000000..d4531d70cce --- /dev/null +++ b/test/run-drun/ok/idl-limits-fine.tc.ok @@ -0,0 +1,6 @@ +idl-limits-fine.mo:19.10-19.12: warning [M0145], this pattern of type + ?[[Nat16]] +does not cover value + null +idl-limits-fine.mo:1.8-1.14: warning [M0194], unused identifier Region (delete or rename to wildcard `_` or `_Region`) +idl-limits-fine.mo:21.10-21.14: warning [M0194], unused identifier diff (delete or rename to wildcard `_` or `_diff`) diff --git a/test/run-drun/ok/idl-limits.drun-run.ok b/test/run-drun/ok/idl-limits.drun-run.ok new file mode 100644 index 00000000000..da997ad8ee3 --- /dev/null +++ b/test/run-drun/ok/idl-limits.drun-run.ok @@ -0,0 +1,22 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +debug.print: {bytes = 12} +debug.print: {MB = 0; bytes = 12} +debug.print: {bytes = 1_048_620} +debug.print: {MB = 1; bytes = 1_048_620} +debug.print: {bytes = 2_097_228} +debug.print: {MB = 2; bytes = 2_097_228} +debug.print: {bytes = 3_145_836} +debug.print: {MB = 3; bytes = 3_145_836} +debug.print: {bytes = 4_194_444} +debug.print: {MB = 4; bytes = 4_194_444} +debug.print: {bytes = 5_243_052} +debug.print: {MB = 5; bytes = 5_243_052} +debug.print: {bytes = 6_291_660} +debug.print: {MB = 6; bytes = 6_291_660} +debug.print: {bytes = 7_340_268} +debug.print: {MB = 7; bytes = 7_340_268} +debug.print: {bytes = 8_388_877} +debug.print: {MB = 8; bytes = 8_388_877} +debug.print: {bytes = 9_437_485} +debug.print: {MB = 9; bytes = 9_437_485} +ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-limits.tc.ok b/test/run-drun/ok/idl-limits.tc.ok new file mode 100644 index 00000000000..e405e161ca2 --- /dev/null +++ b/test/run-drun/ok/idl-limits.tc.ok @@ -0,0 +1,9 @@ +idl-limits.mo:10.8-10.9: warning [M0145], this pattern of type + Nat64 +does not cover value + 1 or 2 or _ +idl-limits.mo:20.10-20.12: warning [M0145], this pattern of type + ?[Blob] +does not cover value + null +idl-limits.mo:22.10-22.14: warning [M0194], unused identifier diff (delete or rename to wildcard `_` or `_diff`) diff --git a/test/run-drun/ok/idl-spacebomb.drun-run.ok b/test/run-drun/ok/idl-spacebomb.drun-run.ok new file mode 100644 index 00000000000..58ed0fbdfc2 --- /dev/null +++ b/test/run-drun/ok/idl-spacebomb.drun-run.ok @@ -0,0 +1,73 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +ingress Completed: Reply: 0x4449444c0000 +debug.print: {function = "vec_null_extra_argument"; hex = "4449444C016D7F01008094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_reserved_extra_argument"; hex = "4449444C016D7001008094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "zero_sized_record_extra_argument"; hex = "4449444C046C03007F010102026C0100706C006D0001038094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_vec_null_extra_argument"; hex = "4449444C026D016D7F010005FFFF3FFFFF3FFFFF3FFFFF3FFFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_record_emp_extra_argument"; hex = "4449444C026D016C00010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_opt_record_with_2_20_null_extra_argument"; hex = "4449444C176C02017F027F6C02010002006C02000101016C02000201026C02000301036C02000401046C02000501056C02000601066C02000701076C02000801086C02000901096C02000A010A6C02000B010B6C02000C010C6C02000D020D6C02000E010E6C02000F010F6C02001001106C02001101116C02001201126C02001301136E146D150116050101010101"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_null_not_ignored"; hex = "4449444C016D7F01008094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Array allocation too large +debug.print: {function = "vec_null_not_ignored"; hex = "4449444C016D7F010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_null_not_ignored"; hex = "4449444C016D7F0100FFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_null_not_ignored"; hex = "4449444C016D7F010080BF18"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_reserved_not_ignored"; hex = "4449444C016D7001008094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Array allocation too large +debug.print: {function = "vec_reserved_not_ignored"; hex = "4449444C016D70010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_reserved_not_ignored"; hex = "4449444C016D700100FFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_reserved_not_ignored"; hex = "4449444C016D70010080BF18"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "zero_sized_record_not_ignored"; hex = "4449444C046C03007F010102026C0100706C006D0001038094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: RTS error: Array allocation too large +debug.print: {function = "zero_sized_record_not_ignored"; hex = "4449444C046C03007F010102026C0100706C006D00010380ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "zero_sized_record_not_ignored"; hex = "4449444C046C03007F010102026C0100706C006D000103FFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "zero_sized_record_not_ignored"; hex = "4449444C046C03007F010102026C0100706C006D00010380B518"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_vec_null_not_ignored"; hex = "4449444C026D016D7F010005FFFF3FFFFF3FFFFF3FFFFF3FFFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_record_emp_not_ignored"; hex = "4449444C026D016C00010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded allocation limit +debug.print: {function = "vec_null_subtyping"; hex = "4449444C016D7F01008094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_null_subtyping"; hex = "4449444C016D7F010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_null_subtyping"; hex = "4449444C016D7F0100FFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_null_subtyping"; hex = "4449444C016D7F010080BF18"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_reserved_subtyping"; hex = "4449444C016D7001008094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_reserved_subtyping"; hex = "4449444C016D70010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_reserved_subtyping"; hex = "4449444C016D700100FFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_reserved_subtyping"; hex = "4449444C016D70010080BF18"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "zero_sized_record_subtyping"; hex = "4449444C046C03007F010102026C0100706C006D0001038094EBDC03"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "zero_sized_record_subtyping"; hex = "4449444C046C03007F010102026C0100706C006D00010380ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "zero_sized_record_subtyping"; hex = "4449444C046C03007F010102026C0100706C006D000103FFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "zero_sized_record_subtyping"; hex = "4449444C046C03007F010102026C0100706C006D00010380B518"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_vec_null_subtyping"; hex = "4449444C026D016D7F010005FFFF3FFFFF3FFFFF3FFFFF3FFFFF3F"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_record_emp_subtyping"; hex = "4449444C026D016C00010080ADE204"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +debug.print: {function = "vec_opt_record_with_2_20_null_subtyping"; hex = "4449444C176C02017F027F6C02010002006C02000101016C02000201026C02000301036C02000401046C02000501056C02000601066C02000701076C02000801086C02000901096C02000A010A6C02000B010B6C02000C010C6C02000D020D6C02000E010E6C02000F010F6C02001001106C02001101116C02001201126C02001301136E146D150116050101010101"} +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run-drun/ok/idl-sub-opt-any-record.drun-run.ok b/test/run-drun/ok/idl-sub-opt-any-record.drun-run.ok index 4eed30d4928..027584112ce 100644 --- a/test/run-drun/ok/idl-sub-opt-any-record.drun-run.ok +++ b/test/run-drun/ok/idl-sub-opt-any-record.drun-run.ok @@ -1,5 +1,6 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 ingress Completed: Reply: 0x4449444c0000 +debug.print: ok_0 debug.print: ok_0_1_a debug.print: ok_0 debug.print: ok_0_1_b diff --git a/test/run-drun/ok/idl-sub-opt-any.drun-run.ok b/test/run-drun/ok/idl-sub-opt-any.drun-run.ok index 3eccfc5383f..c3ca7c39455 100644 --- a/test/run-drun/ok/idl-sub-opt-any.drun-run.ok +++ b/test/run-drun/ok/idl-sub-opt-any.drun-run.ok @@ -1,5 +1,6 @@ ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 ingress Completed: Reply: 0x4449444c0000 +debug.print: ok_0 debug.print: ok_0_1_a debug.print: ok_0 debug.print: ok_0_1_b diff --git a/test/run-drun/ok/vec-any-bomb.drun-run.ok b/test/run-drun/ok/vec-any-bomb.drun-run.ok new file mode 100644 index 00000000000..be26dc8a6f6 --- /dev/null +++ b/test/run-drun/ok/vec-any-bomb.drun-run.ok @@ -0,0 +1,4 @@ +ingress Completed: Reply: 0x4449444c016c01b3c4b1f204680100010a00000000000000000101 +ingress Completed: Reply: 0x4449444c0000 +debug.print: IC0503: Canister rwlgt-iiaaa-aaaaa-aaaaa-cai trapped explicitly: IDL error: exceeded instruction limit +ingress Completed: Reply: 0x4449444c0000 diff --git a/test/run-drun/vec-any-bomb.mo b/test/run-drun/vec-any-bomb.mo new file mode 100644 index 00000000000..c2cff8aa13c --- /dev/null +++ b/test/run-drun/vec-any-bomb.mo @@ -0,0 +1,22 @@ +//MOC-ENV MOC_UNLOCK_PRIM=yesplease +import Prim "mo:⛔"; + +actor { + + func deserUnit(x : Blob) : () = (prim "deserialize" : Blob -> ()) x; + + public func go () : async () { + try { + await async { deserUnit "DIDL\01\6d\70\01\00\f0\f0\f0\f0\08"; }; + assert false + } + catch e { + Prim.debugPrint(Prim.errorMessage(e)); + } + } +} +//SKIP run +//SKIP run-ir +//SKIP run-low +//SKIP ic-ref +//CALL ingress go "DIDL\x00\x00" diff --git a/test/run/ok/vec-any-bomb.tc.ok b/test/run/ok/vec-any-bomb.tc.ok deleted file mode 100644 index 78529ff2c1f..00000000000 --- a/test/run/ok/vec-any-bomb.tc.ok +++ /dev/null @@ -1 +0,0 @@ -vec-any-bomb.mo:2.8-2.12: warning [M0194], unused identifier Prim (delete or rename to wildcard `_` or `_Prim`) diff --git a/test/run/vec-any-bomb.mo b/test/run/vec-any-bomb.mo deleted file mode 100644 index d790b38caf9..00000000000 --- a/test/run/vec-any-bomb.mo +++ /dev/null @@ -1,9 +0,0 @@ -//MOC-ENV MOC_UNLOCK_PRIM=yesplease -import Prim "mo:⛔"; - -func deserUnit(x : Blob) : () = (prim "deserialize" : Blob -> ()) x; -deserUnit "DIDL\01\6d\70\01\00\f0\f0\f0\f0\08"; - -//SKIP run -//SKIP run-ir -//SKIP run-low