From 5adec3ca98120bc2c4110ebe354dfc50d7095ebe Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sun, 3 Oct 2021 03:16:34 +0300 Subject: [PATCH] + workaround for WebAssembly treating the stack parameter of the store and load instructions as unsigned. This caused an 'out of bounds memory access' trap when accessing arrays with negative offset index, e.g. in test/cg/tvec.pp --- compiler/wasm32/hlcgcpu.pas | 64 ++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/compiler/wasm32/hlcgcpu.pas b/compiler/wasm32/hlcgcpu.pas index 35b2d3222f..2beaba0e8b 100644 --- a/compiler/wasm32/hlcgcpu.pas +++ b/compiler/wasm32/hlcgcpu.pas @@ -1072,12 +1072,26 @@ implementation incstack(list,1); list.Concat(taicpu.op_none(a_i32_add)); decstack(list,1); + if assigned(ref.symbol) then + begin + list.Concat(taicpu.op_sym(a_i32_const,ref.symbol)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); + end; if ref.offset<0 then begin list.Concat(taicpu.op_const(a_i32_const,-ref.offset)); incstack(list,1); list.Concat(taicpu.op_none(a_i32_sub)); decstack(list,1); + end + else if ref.offset>0 then + begin + list.Concat(taicpu.op_const(a_i32_const,ref.offset)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); end; if dup then begin @@ -1087,18 +1101,32 @@ implementation incstack(list,1); list.Concat(taicpu.op_none(a_i32_add)); decstack(list,1); + if assigned(ref.symbol) then + begin + list.Concat(taicpu.op_sym(a_i32_const,ref.symbol)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); + end; if ref.offset<0 then begin list.Concat(taicpu.op_const(a_i32_const,-ref.offset)); incstack(list,1); list.Concat(taicpu.op_none(a_i32_sub)); decstack(list,1); + end + else if ref.offset>0 then + begin + list.Concat(taicpu.op_const(a_i32_const,ref.offset)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); end; end; ref.base:=NR_NO; ref.index:=NR_NO; - if ref.offset<0 then - ref.offset:=0; + ref.offset:=0; + ref.symbol:=nil; result:=1; end else if (ref.base<>NR_NO) then @@ -1107,26 +1135,54 @@ implementation begin { regular field -> load self on the stack } a_load_reg_stack(list,voidpointertype,ref.base); + if assigned(ref.symbol) then + begin + list.Concat(taicpu.op_sym(a_i32_const,ref.symbol)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); + end; if ref.offset<0 then begin list.Concat(taicpu.op_const(a_i32_const,-ref.offset)); incstack(list,1); list.Concat(taicpu.op_none(a_i32_sub)); decstack(list,1); + end + else if ref.offset>0 then + begin + list.Concat(taicpu.op_const(a_i32_const,ref.offset)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); end; if dup then begin a_load_reg_stack(list,voidpointertype,ref.base); + if assigned(ref.symbol) then + begin + list.Concat(taicpu.op_sym(a_i32_const,ref.symbol)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); + end; if ref.offset<0 then begin list.Concat(taicpu.op_const(a_i32_const,-ref.offset)); incstack(list,1); list.Concat(taicpu.op_none(a_i32_sub)); decstack(list,1); + end + else if ref.offset>0 then + begin + list.Concat(taicpu.op_const(a_i32_const,ref.offset)); + incstack(list,1); + list.Concat(taicpu.op_none(a_i32_add)); + decstack(list,1); end; end; - if ref.offset<0 then - ref.offset:=0; + ref.offset:=0; + ref.symbol:=nil; ref.base:=NR_NO; result:=1; end