From 8790c4303a6836ed7f21d0fa71c2111a9e6f8599 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov Date: Sun, 9 Feb 2025 18:36:42 +0200 Subject: [PATCH] * WebAssembly: impose a limit on the br_table instruction length, when generating the invoke helper --- compiler/ogwasm.pas | 67 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/compiler/ogwasm.pas b/compiler/ogwasm.pas index a65ee712e6..f87d7a269d 100644 --- a/compiler/ogwasm.pas +++ b/compiler/ogwasm.pas @@ -5999,6 +5999,7 @@ implementation procedure TWasmExeOutput.GenerateCode_InvokeHelper; var Sec: TObjSection; + IndirectFunctionTableMap: array of Integer; procedure InvokeFuncType(typidx: Integer); var @@ -6140,11 +6141,65 @@ implementation end; end; + procedure WriteBrTable(l,h: Integer; addend: Integer=0); + const + { max len of br_table instruction } + MaxLen=1000; + var + i, len, m: Integer; + begin + { local.get 0 } + Sec.writeUInt16BE($2000); + len:=h-l+1; + if len<=MaxLen then + begin + if l>0 then + begin + { i32.const l } + Sec.writeUInt8($41); + WriteSleb(sec,l); + { i32.sub } + Sec.writeUInt8($6B); + end; + { br_table } + Sec.writeUInt8($0E); + if h=high(IndirectFunctionTableMap) then + begin + WriteUleb(Sec,len); + for i:=l to h do + WriteUleb(Sec,IndirectFunctionTableMap[i]+addend); + WriteUleb(Sec,addend); + end + else + begin + WriteUleb(Sec,len-1); + for i:=l to h do + WriteUleb(Sec,IndirectFunctionTableMap[i]+addend); + end; + end + else + begin + m:=(l+h) div 2; + { i32.const m } + Sec.writeUInt8($41); + WriteSleb(sec,m); + { i32.lt_u } + Sec.writeUInt8($49); + { if } + Sec.writeUInt16BE($0440); + WriteBrTable(l,m-1,addend+1); + { else } + Sec.writeUInt8($05); + WriteBrTable(m,h,addend+1); + { end } + Sec.writeUInt8($0B); + end; + end; + var exesym: TExeSymbol; objsym: TObjSymbol; i, j, TypIdx: Integer; - IndirectFunctionTableMap: array of Integer; InvokableTypeIndices: array of Integer; begin exesym:=TExeSymbol(ExeSymbolList.Find('fpc_wasm_invoke_helper')); @@ -6186,14 +6241,8 @@ implementation { block } Sec.writeUInt16BE($0240); - { local.get 0 } - Sec.writeUInt16BE($2000); - { br_table <0, 1, 2, 3, 4, 5, 6, ..., High>, 0 } - Sec.writeUInt8($0E); - WriteUleb(Sec,Length(FIndirectFunctionTable)); - for i:=0 to Length(FIndirectFunctionTable)-1 do - WriteUleb(Sec,IndirectFunctionTableMap[i]); - Sec.writeUInt8($00); + { local.get 0 + br_table } + WriteBrTable(low(IndirectFunctionTableMap),high(IndirectFunctionTableMap)); { end } Sec.writeUInt8($0B); { unreachable }