diff --git a/core/iwasm/interpreter/wasm_interp_fast.c b/core/iwasm/interpreter/wasm_interp_fast.c index 1368cf0387..937a7fdecf 100644 --- a/core/iwasm/interpreter/wasm_interp_fast.c +++ b/core/iwasm/interpreter/wasm_interp_fast.c @@ -7576,6 +7576,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module, } } frame->lp = frame->operand + cur_func->const_cell_num; + if ((uint8 *)(frame->lp + cur_func->param_cell_num) + > exec_env->wasm_stack.top_boundary) { + if (lp_base) + wasm_runtime_free(lp_base); + wasm_set_exception(module, "wasm operand stack overflow"); + goto got_exception; + } if (lp - lp_base > 0) { word_copy(frame->lp, lp_base, lp - lp_base); } diff --git a/tests/regression/ba-issues/build_wamr.sh b/tests/regression/ba-issues/build_wamr.sh index f48dcbe4e8..9f2b3c716f 100755 --- a/tests/regression/ba-issues/build_wamr.sh +++ b/tests/regression/ba-issues/build_wamr.sh @@ -63,4 +63,7 @@ build_iwasm "-DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_SIMD= # build default iwasm for testing wasm loader with branch hints enabled build_iwasm "-DWAMR_BUILD_BRANCH_HINTS=1" "default-branch-hints-enabled" +# build default iwasm for testing tail call with fast-interp +build_iwasm "-DWAMR_BUILD_REF_TYPES=1 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_TAIL_CALL=1 -DWAMR_BUILD_LIBC_WASI=0" "default-tail-call-wasi-disabled" + # TODO: add more version of iwasm, for example, sgx version diff --git a/tests/regression/ba-issues/issues/issue-4916/tail_call_stack_overflow.wasm b/tests/regression/ba-issues/issues/issue-4916/tail_call_stack_overflow.wasm new file mode 100644 index 0000000000..568653b556 Binary files /dev/null and b/tests/regression/ba-issues/issues/issue-4916/tail_call_stack_overflow.wasm differ diff --git a/tests/regression/ba-issues/issues/issue-4916/tail_call_stack_overflow.wat b/tests/regression/ba-issues/issues/issue-4916/tail_call_stack_overflow.wat new file mode 100644 index 0000000000..94bf70b6c6 --- /dev/null +++ b/tests/regression/ba-issues/issues/issue-4916/tail_call_stack_overflow.wat @@ -0,0 +1,282 @@ +(module + + ;; Callee has ~1000 const cells (500 unique i64 constants). + ;; When tiny_caller does a return_call to this function, the fast interpreter + ;; must stage the parameter at frame->operand + callee->const_cell_num. + ;; Without the fix, this write extends past the end of tiny_caller's small + ;; frame and corrupts adjacent heap memory. + (func $callee (param i32) (result i32) + (drop (i64.add (i64.const 100000000001) (i64.const 100000000002))) + (drop (i64.add (i64.const 100000000003) (i64.const 100000000004))) + (drop (i64.add (i64.const 100000000005) (i64.const 100000000006))) + (drop (i64.add (i64.const 100000000007) (i64.const 100000000008))) + (drop (i64.add (i64.const 100000000009) (i64.const 100000000010))) + (drop (i64.add (i64.const 100000000011) (i64.const 100000000012))) + (drop (i64.add (i64.const 100000000013) (i64.const 100000000014))) + (drop (i64.add (i64.const 100000000015) (i64.const 100000000016))) + (drop (i64.add (i64.const 100000000017) (i64.const 100000000018))) + (drop (i64.add (i64.const 100000000019) (i64.const 100000000020))) + (drop (i64.add (i64.const 100000000021) (i64.const 100000000022))) + (drop (i64.add (i64.const 100000000023) (i64.const 100000000024))) + (drop (i64.add (i64.const 100000000025) (i64.const 100000000026))) + (drop (i64.add (i64.const 100000000027) (i64.const 100000000028))) + (drop (i64.add (i64.const 100000000029) (i64.const 100000000030))) + (drop (i64.add (i64.const 100000000031) (i64.const 100000000032))) + (drop (i64.add (i64.const 100000000033) (i64.const 100000000034))) + (drop (i64.add (i64.const 100000000035) (i64.const 100000000036))) + (drop (i64.add (i64.const 100000000037) (i64.const 100000000038))) + (drop (i64.add (i64.const 100000000039) (i64.const 100000000040))) + (drop (i64.add (i64.const 100000000041) (i64.const 100000000042))) + (drop (i64.add (i64.const 100000000043) (i64.const 100000000044))) + (drop (i64.add (i64.const 100000000045) (i64.const 100000000046))) + (drop (i64.add (i64.const 100000000047) (i64.const 100000000048))) + (drop (i64.add (i64.const 100000000049) (i64.const 100000000050))) + (drop (i64.add (i64.const 100000000051) (i64.const 100000000052))) + (drop (i64.add (i64.const 100000000053) (i64.const 100000000054))) + (drop (i64.add (i64.const 100000000055) (i64.const 100000000056))) + (drop (i64.add (i64.const 100000000057) (i64.const 100000000058))) + (drop (i64.add (i64.const 100000000059) (i64.const 100000000060))) + (drop (i64.add (i64.const 100000000061) (i64.const 100000000062))) + (drop (i64.add (i64.const 100000000063) (i64.const 100000000064))) + (drop (i64.add (i64.const 100000000065) (i64.const 100000000066))) + (drop (i64.add (i64.const 100000000067) (i64.const 100000000068))) + (drop (i64.add (i64.const 100000000069) (i64.const 100000000070))) + (drop (i64.add (i64.const 100000000071) (i64.const 100000000072))) + (drop (i64.add (i64.const 100000000073) (i64.const 100000000074))) + (drop (i64.add (i64.const 100000000075) (i64.const 100000000076))) + (drop (i64.add (i64.const 100000000077) (i64.const 100000000078))) + (drop (i64.add (i64.const 100000000079) (i64.const 100000000080))) + (drop (i64.add (i64.const 100000000081) (i64.const 100000000082))) + (drop (i64.add (i64.const 100000000083) (i64.const 100000000084))) + (drop (i64.add (i64.const 100000000085) (i64.const 100000000086))) + (drop (i64.add (i64.const 100000000087) (i64.const 100000000088))) + (drop (i64.add (i64.const 100000000089) (i64.const 100000000090))) + (drop (i64.add (i64.const 100000000091) (i64.const 100000000092))) + (drop (i64.add (i64.const 100000000093) (i64.const 100000000094))) + (drop (i64.add (i64.const 100000000095) (i64.const 100000000096))) + (drop (i64.add (i64.const 100000000097) (i64.const 100000000098))) + (drop (i64.add (i64.const 100000000099) (i64.const 100000000100))) + (drop (i64.add (i64.const 100000000101) (i64.const 100000000102))) + (drop (i64.add (i64.const 100000000103) (i64.const 100000000104))) + (drop (i64.add (i64.const 100000000105) (i64.const 100000000106))) + (drop (i64.add (i64.const 100000000107) (i64.const 100000000108))) + (drop (i64.add (i64.const 100000000109) (i64.const 100000000110))) + (drop (i64.add (i64.const 100000000111) (i64.const 100000000112))) + (drop (i64.add (i64.const 100000000113) (i64.const 100000000114))) + (drop (i64.add (i64.const 100000000115) (i64.const 100000000116))) + (drop (i64.add (i64.const 100000000117) (i64.const 100000000118))) + (drop (i64.add (i64.const 100000000119) (i64.const 100000000120))) + (drop (i64.add (i64.const 100000000121) (i64.const 100000000122))) + (drop (i64.add (i64.const 100000000123) (i64.const 100000000124))) + (drop (i64.add (i64.const 100000000125) (i64.const 100000000126))) + (drop (i64.add (i64.const 100000000127) (i64.const 100000000128))) + (drop (i64.add (i64.const 100000000129) (i64.const 100000000130))) + (drop (i64.add (i64.const 100000000131) (i64.const 100000000132))) + (drop (i64.add (i64.const 100000000133) (i64.const 100000000134))) + (drop (i64.add (i64.const 100000000135) (i64.const 100000000136))) + (drop (i64.add (i64.const 100000000137) (i64.const 100000000138))) + (drop (i64.add (i64.const 100000000139) (i64.const 100000000140))) + (drop (i64.add (i64.const 100000000141) (i64.const 100000000142))) + (drop (i64.add (i64.const 100000000143) (i64.const 100000000144))) + (drop (i64.add (i64.const 100000000145) (i64.const 100000000146))) + (drop (i64.add (i64.const 100000000147) (i64.const 100000000148))) + (drop (i64.add (i64.const 100000000149) (i64.const 100000000150))) + (drop (i64.add (i64.const 100000000151) (i64.const 100000000152))) + (drop (i64.add (i64.const 100000000153) (i64.const 100000000154))) + (drop (i64.add (i64.const 100000000155) (i64.const 100000000156))) + (drop (i64.add (i64.const 100000000157) (i64.const 100000000158))) + (drop (i64.add (i64.const 100000000159) (i64.const 100000000160))) + (drop (i64.add (i64.const 100000000161) (i64.const 100000000162))) + (drop (i64.add (i64.const 100000000163) (i64.const 100000000164))) + (drop (i64.add (i64.const 100000000165) (i64.const 100000000166))) + (drop (i64.add (i64.const 100000000167) (i64.const 100000000168))) + (drop (i64.add (i64.const 100000000169) (i64.const 100000000170))) + (drop (i64.add (i64.const 100000000171) (i64.const 100000000172))) + (drop (i64.add (i64.const 100000000173) (i64.const 100000000174))) + (drop (i64.add (i64.const 100000000175) (i64.const 100000000176))) + (drop (i64.add (i64.const 100000000177) (i64.const 100000000178))) + (drop (i64.add (i64.const 100000000179) (i64.const 100000000180))) + (drop (i64.add (i64.const 100000000181) (i64.const 100000000182))) + (drop (i64.add (i64.const 100000000183) (i64.const 100000000184))) + (drop (i64.add (i64.const 100000000185) (i64.const 100000000186))) + (drop (i64.add (i64.const 100000000187) (i64.const 100000000188))) + (drop (i64.add (i64.const 100000000189) (i64.const 100000000190))) + (drop (i64.add (i64.const 100000000191) (i64.const 100000000192))) + (drop (i64.add (i64.const 100000000193) (i64.const 100000000194))) + (drop (i64.add (i64.const 100000000195) (i64.const 100000000196))) + (drop (i64.add (i64.const 100000000197) (i64.const 100000000198))) + (drop (i64.add (i64.const 100000000199) (i64.const 100000000200))) + (drop (i64.add (i64.const 100000000201) (i64.const 100000000202))) + (drop (i64.add (i64.const 100000000203) (i64.const 100000000204))) + (drop (i64.add (i64.const 100000000205) (i64.const 100000000206))) + (drop (i64.add (i64.const 100000000207) (i64.const 100000000208))) + (drop (i64.add (i64.const 100000000209) (i64.const 100000000210))) + (drop (i64.add (i64.const 100000000211) (i64.const 100000000212))) + (drop (i64.add (i64.const 100000000213) (i64.const 100000000214))) + (drop (i64.add (i64.const 100000000215) (i64.const 100000000216))) + (drop (i64.add (i64.const 100000000217) (i64.const 100000000218))) + (drop (i64.add (i64.const 100000000219) (i64.const 100000000220))) + (drop (i64.add (i64.const 100000000221) (i64.const 100000000222))) + (drop (i64.add (i64.const 100000000223) (i64.const 100000000224))) + (drop (i64.add (i64.const 100000000225) (i64.const 100000000226))) + (drop (i64.add (i64.const 100000000227) (i64.const 100000000228))) + (drop (i64.add (i64.const 100000000229) (i64.const 100000000230))) + (drop (i64.add (i64.const 100000000231) (i64.const 100000000232))) + (drop (i64.add (i64.const 100000000233) (i64.const 100000000234))) + (drop (i64.add (i64.const 100000000235) (i64.const 100000000236))) + (drop (i64.add (i64.const 100000000237) (i64.const 100000000238))) + (drop (i64.add (i64.const 100000000239) (i64.const 100000000240))) + (drop (i64.add (i64.const 100000000241) (i64.const 100000000242))) + (drop (i64.add (i64.const 100000000243) (i64.const 100000000244))) + (drop (i64.add (i64.const 100000000245) (i64.const 100000000246))) + (drop (i64.add (i64.const 100000000247) (i64.const 100000000248))) + (drop (i64.add (i64.const 100000000249) (i64.const 100000000250))) + (drop (i64.add (i64.const 100000000251) (i64.const 100000000252))) + (drop (i64.add (i64.const 100000000253) (i64.const 100000000254))) + (drop (i64.add (i64.const 100000000255) (i64.const 100000000256))) + (drop (i64.add (i64.const 100000000257) (i64.const 100000000258))) + (drop (i64.add (i64.const 100000000259) (i64.const 100000000260))) + (drop (i64.add (i64.const 100000000261) (i64.const 100000000262))) + (drop (i64.add (i64.const 100000000263) (i64.const 100000000264))) + (drop (i64.add (i64.const 100000000265) (i64.const 100000000266))) + (drop (i64.add (i64.const 100000000267) (i64.const 100000000268))) + (drop (i64.add (i64.const 100000000269) (i64.const 100000000270))) + (drop (i64.add (i64.const 100000000271) (i64.const 100000000272))) + (drop (i64.add (i64.const 100000000273) (i64.const 100000000274))) + (drop (i64.add (i64.const 100000000275) (i64.const 100000000276))) + (drop (i64.add (i64.const 100000000277) (i64.const 100000000278))) + (drop (i64.add (i64.const 100000000279) (i64.const 100000000280))) + (drop (i64.add (i64.const 100000000281) (i64.const 100000000282))) + (drop (i64.add (i64.const 100000000283) (i64.const 100000000284))) + (drop (i64.add (i64.const 100000000285) (i64.const 100000000286))) + (drop (i64.add (i64.const 100000000287) (i64.const 100000000288))) + (drop (i64.add (i64.const 100000000289) (i64.const 100000000290))) + (drop (i64.add (i64.const 100000000291) (i64.const 100000000292))) + (drop (i64.add (i64.const 100000000293) (i64.const 100000000294))) + (drop (i64.add (i64.const 100000000295) (i64.const 100000000296))) + (drop (i64.add (i64.const 100000000297) (i64.const 100000000298))) + (drop (i64.add (i64.const 100000000299) (i64.const 100000000300))) + (drop (i64.add (i64.const 100000000301) (i64.const 100000000302))) + (drop (i64.add (i64.const 100000000303) (i64.const 100000000304))) + (drop (i64.add (i64.const 100000000305) (i64.const 100000000306))) + (drop (i64.add (i64.const 100000000307) (i64.const 100000000308))) + (drop (i64.add (i64.const 100000000309) (i64.const 100000000310))) + (drop (i64.add (i64.const 100000000311) (i64.const 100000000312))) + (drop (i64.add (i64.const 100000000313) (i64.const 100000000314))) + (drop (i64.add (i64.const 100000000315) (i64.const 100000000316))) + (drop (i64.add (i64.const 100000000317) (i64.const 100000000318))) + (drop (i64.add (i64.const 100000000319) (i64.const 100000000320))) + (drop (i64.add (i64.const 100000000321) (i64.const 100000000322))) + (drop (i64.add (i64.const 100000000323) (i64.const 100000000324))) + (drop (i64.add (i64.const 100000000325) (i64.const 100000000326))) + (drop (i64.add (i64.const 100000000327) (i64.const 100000000328))) + (drop (i64.add (i64.const 100000000329) (i64.const 100000000330))) + (drop (i64.add (i64.const 100000000331) (i64.const 100000000332))) + (drop (i64.add (i64.const 100000000333) (i64.const 100000000334))) + (drop (i64.add (i64.const 100000000335) (i64.const 100000000336))) + (drop (i64.add (i64.const 100000000337) (i64.const 100000000338))) + (drop (i64.add (i64.const 100000000339) (i64.const 100000000340))) + (drop (i64.add (i64.const 100000000341) (i64.const 100000000342))) + (drop (i64.add (i64.const 100000000343) (i64.const 100000000344))) + (drop (i64.add (i64.const 100000000345) (i64.const 100000000346))) + (drop (i64.add (i64.const 100000000347) (i64.const 100000000348))) + (drop (i64.add (i64.const 100000000349) (i64.const 100000000350))) + (drop (i64.add (i64.const 100000000351) (i64.const 100000000352))) + (drop (i64.add (i64.const 100000000353) (i64.const 100000000354))) + (drop (i64.add (i64.const 100000000355) (i64.const 100000000356))) + (drop (i64.add (i64.const 100000000357) (i64.const 100000000358))) + (drop (i64.add (i64.const 100000000359) (i64.const 100000000360))) + (drop (i64.add (i64.const 100000000361) (i64.const 100000000362))) + (drop (i64.add (i64.const 100000000363) (i64.const 100000000364))) + (drop (i64.add (i64.const 100000000365) (i64.const 100000000366))) + (drop (i64.add (i64.const 100000000367) (i64.const 100000000368))) + (drop (i64.add (i64.const 100000000369) (i64.const 100000000370))) + (drop (i64.add (i64.const 100000000371) (i64.const 100000000372))) + (drop (i64.add (i64.const 100000000373) (i64.const 100000000374))) + (drop (i64.add (i64.const 100000000375) (i64.const 100000000376))) + (drop (i64.add (i64.const 100000000377) (i64.const 100000000378))) + (drop (i64.add (i64.const 100000000379) (i64.const 100000000380))) + (drop (i64.add (i64.const 100000000381) (i64.const 100000000382))) + (drop (i64.add (i64.const 100000000383) (i64.const 100000000384))) + (drop (i64.add (i64.const 100000000385) (i64.const 100000000386))) + (drop (i64.add (i64.const 100000000387) (i64.const 100000000388))) + (drop (i64.add (i64.const 100000000389) (i64.const 100000000390))) + (drop (i64.add (i64.const 100000000391) (i64.const 100000000392))) + (drop (i64.add (i64.const 100000000393) (i64.const 100000000394))) + (drop (i64.add (i64.const 100000000395) (i64.const 100000000396))) + (drop (i64.add (i64.const 100000000397) (i64.const 100000000398))) + (drop (i64.add (i64.const 100000000399) (i64.const 100000000400))) + (drop (i64.add (i64.const 100000000401) (i64.const 100000000402))) + (drop (i64.add (i64.const 100000000403) (i64.const 100000000404))) + (drop (i64.add (i64.const 100000000405) (i64.const 100000000406))) + (drop (i64.add (i64.const 100000000407) (i64.const 100000000408))) + (drop (i64.add (i64.const 100000000409) (i64.const 100000000410))) + (drop (i64.add (i64.const 100000000411) (i64.const 100000000412))) + (drop (i64.add (i64.const 100000000413) (i64.const 100000000414))) + (drop (i64.add (i64.const 100000000415) (i64.const 100000000416))) + (drop (i64.add (i64.const 100000000417) (i64.const 100000000418))) + (drop (i64.add (i64.const 100000000419) (i64.const 100000000420))) + (drop (i64.add (i64.const 100000000421) (i64.const 100000000422))) + (drop (i64.add (i64.const 100000000423) (i64.const 100000000424))) + (drop (i64.add (i64.const 100000000425) (i64.const 100000000426))) + (drop (i64.add (i64.const 100000000427) (i64.const 100000000428))) + (drop (i64.add (i64.const 100000000429) (i64.const 100000000430))) + (drop (i64.add (i64.const 100000000431) (i64.const 100000000432))) + (drop (i64.add (i64.const 100000000433) (i64.const 100000000434))) + (drop (i64.add (i64.const 100000000435) (i64.const 100000000436))) + (drop (i64.add (i64.const 100000000437) (i64.const 100000000438))) + (drop (i64.add (i64.const 100000000439) (i64.const 100000000440))) + (drop (i64.add (i64.const 100000000441) (i64.const 100000000442))) + (drop (i64.add (i64.const 100000000443) (i64.const 100000000444))) + (drop (i64.add (i64.const 100000000445) (i64.const 100000000446))) + (drop (i64.add (i64.const 100000000447) (i64.const 100000000448))) + (drop (i64.add (i64.const 100000000449) (i64.const 100000000450))) + (drop (i64.add (i64.const 100000000451) (i64.const 100000000452))) + (drop (i64.add (i64.const 100000000453) (i64.const 100000000454))) + (drop (i64.add (i64.const 100000000455) (i64.const 100000000456))) + (drop (i64.add (i64.const 100000000457) (i64.const 100000000458))) + (drop (i64.add (i64.const 100000000459) (i64.const 100000000460))) + (drop (i64.add (i64.const 100000000461) (i64.const 100000000462))) + (drop (i64.add (i64.const 100000000463) (i64.const 100000000464))) + (drop (i64.add (i64.const 100000000465) (i64.const 100000000466))) + (drop (i64.add (i64.const 100000000467) (i64.const 100000000468))) + (drop (i64.add (i64.const 100000000469) (i64.const 100000000470))) + (drop (i64.add (i64.const 100000000471) (i64.const 100000000472))) + (drop (i64.add (i64.const 100000000473) (i64.const 100000000474))) + (drop (i64.add (i64.const 100000000475) (i64.const 100000000476))) + (drop (i64.add (i64.const 100000000477) (i64.const 100000000478))) + (drop (i64.add (i64.const 100000000479) (i64.const 100000000480))) + (drop (i64.add (i64.const 100000000481) (i64.const 100000000482))) + (drop (i64.add (i64.const 100000000483) (i64.const 100000000484))) + (drop (i64.add (i64.const 100000000485) (i64.const 100000000486))) + (drop (i64.add (i64.const 100000000487) (i64.const 100000000488))) + (drop (i64.add (i64.const 100000000489) (i64.const 100000000490))) + (drop (i64.add (i64.const 100000000491) (i64.const 100000000492))) + (drop (i64.add (i64.const 100000000493) (i64.const 100000000494))) + (drop (i64.add (i64.const 100000000495) (i64.const 100000000496))) + (drop (i64.add (i64.const 100000000497) (i64.const 100000000498))) + (drop (i64.add (i64.const 100000000499) (i64.const 100000000500))) + (local.get 0) + ) + + ;; Tiny caller: no locals, no constants. Does a return_call to $callee. + ;; This is the vulnerable site: tiny_caller's frame has const_cell_num=0 + ;; but $callee has const_cell_num~=1000, so without the fix the fast + ;; interpreter writes the staged parameter ~4000 bytes past the end of + ;; tiny_caller's frame. + (func $tiny_caller (result i32) + (return_call $callee (i32.const 42)) + ) + + ;; Builds up 1000 normal call frames then tail-calls through tiny_caller. + (func $fill (param i32) (result i32) + (if (result i32) (i32.gt_s (local.get 0) (i32.const 0)) + (then (call $fill (i32.sub (local.get 0) (i32.const 1)))) + (else (call $tiny_caller)) + ) + ) + + (func (export "test") (result i32) + (call $fill (i32.const 1000)) + ) +) diff --git a/tests/regression/ba-issues/running_config.json b/tests/regression/ba-issues/running_config.json index 4b84a152c4..9083af9014 100644 --- a/tests/regression/ba-issues/running_config.json +++ b/tests/regression/ba-issues/running_config.json @@ -1852,6 +1852,22 @@ "description": "" } + }, + { + "deprecated": false, + "ids": [ + 4916 + ], + "runtime": "iwasm-default-tail-call-wasi-disabled", + "file": "tail_call_stack_overflow.wasm", + "mode": "fast-interp", + "options": "--stack-size=131072 --heap-size=0 -f test", + "argument": "", + "expected return": { + "ret code": 0, + "stdout content": "0x2a:i32", + "description": "no heap buffer overflow from return_call when callee has a larger const pool than caller" + } } ] }