From 36cb6b7050536355045197ef3717e104ee50053b 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 e41b4b1e8..f126f288e 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -10282,6 +10282,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); @@ -10289,13 +10290,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);