* WebAssembly: impose a limit on the br_table instruction length, when generating the invoke helper

This commit is contained in:
Nikolay Nikolov 2025-02-09 18:36:42 +02:00
parent f3ded5e82e
commit 8790c4303a

View File

@ -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 }