- fixed code generation for very special if+switch combination

CheckReturn() must be called before emitting code, otherwise it will always return false for switch statements
Redundant jump instruction added because of that will point right after the end of function's code when if statement is the last one in the given function
This wasn't a problem for VM because bytecode in question was unreachable
JIT compiler tries to generate native code for a bogus jump destination, and this leads to out-of-bounds read from labels array

https://forum.zdoom.org/viewtopic.php?t=67149
This commit is contained in:
alexey.lysiuk 2020-01-30 18:01:52 +02:00 committed by drfrag
parent dbaaf88bc6
commit 36cb6b7050

View file

@ -10282,6 +10282,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
{ {
ExpEmit v; ExpEmit v;
size_t jumpspot = ~0u; size_t jumpspot = ~0u;
bool whenTrueReturns = false;
TArray<size_t> yes, no; TArray<size_t> yes, no;
Condition->EmitCompare(build, WhenTrue == nullptr, yes, no); Condition->EmitCompare(build, WhenTrue == nullptr, yes, no);
@ -10289,13 +10290,14 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
if (WhenTrue != nullptr) if (WhenTrue != nullptr)
{ {
build->BackpatchListToHere(yes); build->BackpatchListToHere(yes);
whenTrueReturns = WhenTrue->CheckReturn();
WhenTrue->EmitStatement(build); WhenTrue->EmitStatement(build);
} }
if (WhenFalse != nullptr) if (WhenFalse != nullptr)
{ {
if (WhenTrue != nullptr) if (WhenTrue != nullptr)
{ {
if (!WhenTrue->CheckReturn()) jumpspot = build->Emit(OP_JMP, 0); // no need to emit a jump if the block returns. if (!whenTrueReturns) jumpspot = build->Emit(OP_JMP, 0); // no need to emit a jump if the block returns.
build->BackpatchListToHere(no); build->BackpatchListToHere(no);
} }
WhenFalse->EmitStatement(build); WhenFalse->EmitStatement(build);