From dd54c143803c1af79634e1781ed307d67cb5ec0c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Thu, 30 Jan 2020 18:01:52 +0200 Subject: [PATCH] - 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 --- src/scripting/backend/codegen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 5637b8b4f..702f2b8f1 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -10278,6 +10278,7 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) { ExpEmit v; size_t jumpspot = ~0u; + bool whenTrueReturns = false; TArray yes, no; Condition->EmitCompare(build, WhenTrue == nullptr, yes, no); @@ -10285,13 +10286,14 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build) if (WhenTrue != nullptr) { build->BackpatchListToHere(yes); + whenTrueReturns = WhenTrue->CheckReturn(); WhenTrue->EmitStatement(build); } if (WhenFalse != 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); } WhenFalse->EmitStatement(build);