Skip to content

Commit 2652fd5

Browse files
author
Meghana Gupta
committed
[MERGE #1823 @meg-gupta] Add out of bound error for wasm array access in interpreter
Merge pull request #1823 from meg-gupta:indexwasm Closes #1877
2 parents 8f4fcb5 + 2699947 commit 2652fd5

25 files changed

+426
-36
lines changed

lib/Backend/IRBuilderAsmJs.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,8 @@ IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint3
14261426
{
14271427
IRType type = TyInt32;
14281428
bool isLd = newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::LdArrWasm || newOpcode == Js::OpCodeAsmJs::LdArrConst;
1429-
Js::OpCode op = isLd ? Js::OpCode::LdArrViewElem : Js::OpCode::StArrViewElem;
1429+
Js::OpCode op = isLd ? (this->m_func->GetJITFunctionBody()->IsWasmFunction() ?
1430+
Js::OpCode::LdArrViewElemWasm : Js::OpCode::LdArrViewElem) : Js::OpCode::StArrViewElem;
14301431
ValueType arrayType;
14311432
WAsmJs::Types valueRegType = WAsmJs::INT32;
14321433

@@ -1494,7 +1495,7 @@ IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint3
14941495
IR::IndirOpnd * indirOpnd = nullptr;
14951496

14961497
// Get the index
1497-
if (newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::StArr || newOpcode == Js::OpCodeAsmJs::LdArrWasm || newOpcode == Js::OpCodeAsmJs::StArrWasm)
1498+
if (newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::StArr)
14981499
{
14991500
uint32 mask = Js::ArrayBufferView::ViewMask[viewType];
15001501
Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
@@ -1512,6 +1513,13 @@ IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint3
15121513
indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), maskedOpnd, type, m_func);
15131514
indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
15141515
}
1516+
else if (newOpcode == Js::OpCodeAsmJs::LdArrWasm || newOpcode == Js::OpCodeAsmJs::StArrWasm)
1517+
{
1518+
Js::RegSlot indexRegSlot = GetRegSlotFromInt64Reg(slotIndex);
1519+
IR::RegOpnd * maskedOpnd = BuildSrcOpnd(indexRegSlot, TyUint64);
1520+
indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), maskedOpnd, type, m_func);
1521+
indirOpnd->GetBaseOpnd()->SetValueType(arrayType);
1522+
}
15151523
else
15161524
{
15171525
Assert(newOpcode == Js::OpCodeAsmJs::LdArrConst || newOpcode == Js::OpCodeAsmJs::StArrConst);
@@ -1552,6 +1560,11 @@ IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint3
15521560

15531561
#if _M_IX86 || !_WIN32
15541562
instr->SetSrc2(BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32));
1563+
#else
1564+
if (this->m_func->GetJITFunctionBody()->IsWasmFunction())
1565+
{
1566+
instr->SetSrc2(BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32));
1567+
}
15551568
#endif
15561569
AddInstr(instr, offset);
15571570
}
@@ -3108,11 +3121,11 @@ IRBuilderAsmJs::BuildLong1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::Reg
31083121
IR::RegOpnd * srcOpnd = nullptr;
31093122
switch (newOpcode)
31103123
{
3111-
case Js::OpCodeAsmJs::Conv_ITD:
3124+
case Js::OpCodeAsmJs::Conv_ITL:
31123125
srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
31133126
break;
31143127

3115-
case Js::OpCodeAsmJs::Conv_UTD:
3128+
case Js::OpCodeAsmJs::Conv_UTL:
31163129
srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint32);
31173130
break;
31183131

lib/Backend/Lower.cpp

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,10 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
15591559
instrPrev = LowerStArrViewElem(instr);
15601560
break;
15611561

1562+
case Js::OpCode::LdArrViewElemWasm:
1563+
instrPrev = LowerLdArrViewElemWasm(instr);
1564+
break;
1565+
15621566
case Js::OpCode::Memset:
15631567
case Js::OpCode::Memcopy:
15641568
{
@@ -1914,6 +1918,21 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
19141918
m_lowererMD.EmitFloat32ToFloat64(instr->GetDst(), instr->GetSrc1(), instr);
19151919
}
19161920
}
1921+
else if (instr->GetDst()->IsInt64())
1922+
{
1923+
if (instr->GetSrc1()->IsInt32())
1924+
{
1925+
m_lowererMD.EmitIntToLong(instr->GetDst(), instr->GetSrc1(), instr);
1926+
}
1927+
else if (instr->GetSrc1()->IsUInt32())
1928+
{
1929+
m_lowererMD.EmitUIntToLong(instr->GetDst(), instr->GetSrc1(), instr);
1930+
}
1931+
else
1932+
{
1933+
Assert(0);
1934+
}
1935+
}
19171936
else
19181937
{
19191938
Assert(instr->GetDst()->IsInt32());
@@ -8870,6 +8889,44 @@ Lowerer::LowerLdArrViewElem(IR::Instr * instr)
88708889
#endif
88718890
}
88728891

8892+
IR::Instr *
8893+
Lowerer::LowerLdArrViewElemWasm(IR::Instr * instr)
8894+
{
8895+
#ifdef ASMJS_PLAT
8896+
Assert(m_func->GetJITFunctionBody()->IsWasmFunction());
8897+
Assert(instr);
8898+
Assert(instr->m_opcode == Js::OpCode::LdArrViewElemWasm);
8899+
8900+
IR::Instr * instrPrev = instr->m_prev;
8901+
8902+
IR::Opnd * dst = instr->GetDst();
8903+
IR::Opnd * src1 = instr->GetSrc1();
8904+
8905+
IR::Instr * done;
8906+
8907+
Assert(!dst->IsFloat32() || src1->IsFloat32());
8908+
Assert(!dst->IsFloat64() || src1->IsFloat64());
8909+
done = m_lowererMD.LowerWasmMemOp(instr, src1);
8910+
8911+
if (dst->IsInt64())
8912+
{
8913+
IR::Instr* movInt64 = IR::Instr::New(Js::OpCode::Ld_I4, dst, src1, m_func);
8914+
done->InsertBefore(movInt64);
8915+
m_lowererMD.LowerInt64Assign(movInt64);
8916+
}
8917+
else
8918+
{
8919+
InsertMove(dst, src1, done);
8920+
}
8921+
8922+
instr->Remove();
8923+
return instrPrev;
8924+
#else
8925+
Assert(UNREACHED);
8926+
return instr;
8927+
#endif
8928+
}
8929+
88738930
IR::Instr *
88748931
Lowerer::LowerMemset(IR::Instr * instr, IR::RegOpnd * helperRet)
88758932
{
@@ -9045,7 +9102,12 @@ Lowerer::LowerStArrViewElem(IR::Instr * instr)
90459102
Assert(!dst->IsInt64() || src1->IsInt64());
90469103

90479104
IR::Instr * done;
9048-
if (indexOpnd || m_func->GetJITFunctionBody()->GetAsmJsInfo()->AccessNeedsBoundCheck((uint32)dst->AsIndirOpnd()->GetOffset()))
9105+
9106+
if (m_func->GetJITFunctionBody()->IsWasmFunction())
9107+
{
9108+
done = m_lowererMD.LowerWasmMemOp(instr, dst);
9109+
}
9110+
else if (indexOpnd || m_func->GetJITFunctionBody()->GetAsmJsInfo()->AccessNeedsBoundCheck((uint32)dst->AsIndirOpnd()->GetOffset()))
90499111
{
90509112
// CMP indexOpnd, src2(arrSize)
90519113
// JA $helper
@@ -9055,7 +9117,6 @@ Lowerer::LowerStArrViewElem(IR::Instr * instr)
90559117
// $store:
90569118
// MOV dst([arrayBuffer + indexOpnd]), src1
90579119
// $done:
9058-
90599120
done = m_lowererMD.LowerAsmJsStElemHelper(instr);
90609121
}
90619122
else

lib/Backend/Lower.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class Lowerer
174174

175175
IR::Instr * LowerLdArrViewElem(IR::Instr * instr);
176176
IR::Instr * LowerStArrViewElem(IR::Instr * instr);
177+
IR::Instr * LowerLdArrViewElemWasm(IR::Instr * instr);
177178
IR::Instr * LowerArrayDetachedCheck(IR::Instr * instr);
178179
IR::Instr * LowerDeleteElemI(IR::Instr *instr, bool strictMode);
179180
IR::Instr * LowerStElemC(IR::Instr *instr);

lib/Backend/LowerMDShared.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,12 @@ LowererMD::LowerAsmJsCallE(IR::Instr * callInstr)
267267
return this->lowererMDArch.LowerAsmJsCallE(callInstr);
268268
}
269269

270+
IR::Instr *
271+
LowererMD::LowerWasmMemOp(IR::Instr * instr, IR::Opnd *addrOpnd)
272+
{
273+
return this->lowererMDArch.LowerWasmMemOp(instr, addrOpnd);
274+
}
275+
270276
IR::Instr *
271277
LowererMD::LowerAsmJsLdElemHelper(IR::Instr * callInstr)
272278
{
@@ -7899,6 +7905,18 @@ LowererMD::EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
78997905
this->lowererMDArch.EmitUIntToFloat(dst, src, instrInsert);
79007906
}
79017907

7908+
void
7909+
LowererMD::EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
7910+
{
7911+
this->lowererMDArch.EmitIntToLong(dst, src, instrInsert);
7912+
}
7913+
7914+
void
7915+
LowererMD::EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
7916+
{
7917+
this->lowererMDArch.EmitUIntToLong(dst, src, instrInsert);
7918+
}
7919+
79027920
void
79037921
LowererMD::EmitFloat32ToFloat64(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
79047922
{

lib/Backend/LowerMDShared.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class LowererMD
104104
IR::Instr * LoadFunctionObjectOpnd(IR::Instr *instr, IR::Opnd *&functionObjOpnd);
105105
IR::Instr * LowerLdSuper(IR::Instr *instr, IR::JnHelperMethod helperOpCode);
106106
IR::Instr * LowerNewScObject(IR::Instr *newObjInstr);
107+
IR::Instr * LowerWasmMemOp(IR::Instr *instr, IR::Opnd *addrOpnd);
107108
void ForceDstToReg(IR::Instr *instr);
108109

109110
public:
@@ -208,6 +209,8 @@ class LowererMD
208209
bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed);
209210
void EmitIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
210211
void EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
212+
void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
213+
void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
211214
void EmitFloatToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
212215
void EmitFloat32ToFloat64(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
213216
static IR::Instr *InsertConvertFloat64ToInt32(const RoundMode roundMode, IR::Opnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr);

lib/Backend/amd64/LowererMDArch.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,30 @@ LowererMDArch::LowerAsmJsCallI(IR::Instr * callInstr)
11171117
return ret;
11181118
}
11191119

1120+
IR::Instr *
1121+
LowererMDArch::LowerWasmMemOp(IR::Instr * instr, IR::Opnd *addrOpnd)
1122+
{
1123+
Assert(instr->GetSrc2());
1124+
1125+
IR::LabelInstr * helperLabel = Lowerer::InsertLabel(true, instr);
1126+
IR::LabelInstr * loadLabel = Lowerer::InsertLabel(false, instr);
1127+
IR::LabelInstr * doneLabel = Lowerer::InsertLabel(false, instr);
1128+
1129+
// Find array buffer length
1130+
IR::RegOpnd * indexOpnd = addrOpnd->AsIndirOpnd()->GetIndexOpnd();
1131+
IR::Opnd *arrayLenOpnd = instr->GetSrc2();
1132+
1133+
// Compare index + memop access length and array buffer length, and generate RuntimeError if greater
1134+
IR::Opnd *cmpOpnd = IR::RegOpnd::New(TyUint64, m_func);
1135+
Lowerer::InsertAdd(true, cmpOpnd, indexOpnd, IR::IntConstOpnd::New(addrOpnd->GetSize(), TyUint64, m_func), helperLabel);
1136+
lowererMD->m_lowerer->InsertCompareBranch(cmpOpnd, arrayLenOpnd, Js::OpCode::BrGt_A, true, helperLabel, helperLabel);
1137+
1138+
// MGTODO : call RuntimeError once implemented
1139+
lowererMD->m_lowerer->GenerateRuntimeError(loadLabel, JSERR_InvalidTypedArrayIndex, IR::HelperOp_RuntimeRangeError);
1140+
Lowerer::InsertBranch(Js::OpCode::Br, loadLabel, helperLabel);
1141+
return doneLabel;
1142+
}
1143+
11201144
IR::Instr*
11211145
LowererMDArch::LowerAsmJsLdElemHelper(IR::Instr * instr, bool isSimdLoad /*= false*/, bool checkEndOffset /*= false*/)
11221146
{
@@ -2541,6 +2565,36 @@ LowererMDArch::EmitIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInse
25412565
}
25422566
}
25432567

2568+
void
2569+
LowererMDArch::EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
2570+
{
2571+
Assert(dst->IsRegOpnd() && dst->IsInt64());
2572+
Assert(src->IsInt32());
2573+
2574+
if (src->IsIntConstOpnd())
2575+
{
2576+
Lowerer::InsertMove(dst, src, instrInsert);
2577+
return;
2578+
}
2579+
Assert(src->IsRegOpnd());
2580+
instrInsert->InsertBefore(IR::Instr::New(Js::OpCode::MOVSXD, dst, src, this->m_func));
2581+
}
2582+
2583+
void
2584+
LowererMDArch::EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
2585+
{
2586+
Assert(dst->IsRegOpnd() && dst->IsInt64());
2587+
Assert(src->IsUInt32());
2588+
2589+
if (src->IsIntConstOpnd())
2590+
{
2591+
Lowerer::InsertMove(dst, src, instrInsert);
2592+
return;
2593+
}
2594+
Assert(src->IsRegOpnd());
2595+
instrInsert->InsertBefore(IR::Instr::New(Js::OpCode::MOV, dst, src, this->m_func));
2596+
}
2597+
25442598
void
25452599
LowererMDArch::EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
25462600
{

lib/Backend/amd64/LowererMDArch.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class LowererMDArch
6969
IR::Instr * LowerStartCall(IR::Instr * instr);
7070
IR::Instr * LowerAsmJsCallI(IR::Instr * callInstr);
7171
IR::Instr * LowerAsmJsCallE(IR::Instr * callInstr);
72-
72+
IR::Instr * LowerWasmMemOp(IR::Instr * instr, IR::Opnd *addrOpnd);
7373
IR::Instr * LowerAsmJsLdElemHelper(IR::Instr * instr, bool isSimdLoad = false, bool checkEndOffset = false);
7474
IR::Instr * LowerAsmJsStElemHelper(IR::Instr * instr, bool isSimdStore = false, bool checkEndOffset = false);
7575

@@ -94,6 +94,8 @@ class LowererMDArch
9494
void EmitLoadVar(IR::Instr *instrLoad, bool isFromUint32 = false, bool isHelper = false);
9595
void EmitIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
9696
void EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
97+
void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
98+
void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
9799
bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed);
98100

99101
IR::Instr * LoadCheckedFloat(IR::RegOpnd *opndOrig, IR::RegOpnd *opndFloat, IR::LabelInstr *labelInline, IR::LabelInstr *labelHelper, IR::Instr *instrInsert, const bool checkForNullInLoopBody = false);

lib/Backend/arm/LowerMD.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8842,6 +8842,18 @@ void LowererMD::ConvertFloatToInt32(IR::Opnd* intOpnd, IR::Opnd* floatOpnd, IR::
88428842
this->CheckOverflowOnFloatToInt32(instrInsert, intOpnd, labelHelper, labelDone);
88438843
}
88448844

8845+
void
8846+
LowererMD::EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
8847+
{
8848+
Assert(UNREACHED);
8849+
}
8850+
8851+
void
8852+
LowererMD::EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert)
8853+
{
8854+
Assert(UNREACHED);
8855+
}
8856+
88458857
void
88468858
LowererMD::CheckOverflowOnFloatToInt32(IR::Instr* instrInsert, IR::Opnd* intOpnd, IR::LabelInstr * labelHelper, IR::LabelInstr * labelDone)
88478859
{

lib/Backend/arm/LowerMD.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ class LowererMD
205205
void EmitFloatToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
206206
void EmitFloat32ToFloat64(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert) { Assert(UNREACHED); }
207207
static IR::Instr * InsertConvertFloat64ToInt32(const RoundMode roundMode, IR::Opnd *const dst, IR::Opnd *const src, IR::Instr *const insertBeforeInstr);
208+
void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
209+
void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
208210
void EmitLoadFloatFromNumber(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr);
209211
IR::LabelInstr* EmitLoadFloatCommon(IR::Opnd *dst, IR::Opnd *src, IR::Instr *insertInstr, bool needHelperLabel);
210212
static IR::Instr * LoadFloatZero(IR::Opnd * opndDst, IR::Instr * instrInsert);

0 commit comments

Comments
 (0)