From a48d2222cd4cfed0fda609fc8b5bdff39a24a22a Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 10 Apr 2025 16:20:52 +0100 Subject: [PATCH 1/4] [cppia] Add missing exception checks In interp mode, we need to stop immediately if a jit exception has been thrown. --- src/hx/cppia/Cppia.cpp | 27 ++++++++++++++++----------- src/hx/cppia/Cppia.h | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/hx/cppia/Cppia.cpp b/src/hx/cppia/Cppia.cpp index ad37f40d8..6f1a09a17 100644 --- a/src/hx/cppia/Cppia.cpp +++ b/src/hx/cppia/Cppia.cpp @@ -1744,6 +1744,7 @@ struct CallHaxe : public CppiaExpr { unsigned char *pointer = ctx->pointer; ctx->pushObject(isStatic ? 0: thisExpr ? thisExpr->runObject(ctx) : ctx->getThis(false)); + BCR_VCHECK; const char *s = function.signature+1; for(int a=0;apushObject( arg->runObject(ctx) ); break; default: ;// huh? } + BCR_VCHECK; } AutoStack a(ctx,pointer); @@ -2148,8 +2150,9 @@ struct CallMemberVTable : public CppiaExpr ExprType getType() { return returnType; } // ScriptCallable **vtable = (ScriptCallable **)thisVal->__GetScriptVTable(); - #define CALL_VTABLE_SETUP \ + #define CALL_VTABLE_SETUP(errorValue) \ hx::Object *thisVal = thisExpr ? thisExpr->runObject(ctx) : ctx->getThis(); \ + BCR_CHECK_RET(errorValue); \ CPPIA_CHECK(thisVal); \ ScriptCallable **vtable = (!isInterfaceCall ? (*(ScriptCallable ***)((char *)thisVal +scriptVTableOffset)) : (ScriptCallable **) thisVal->__GetScriptVTable()); \ unsigned char *pointer = ctx->pointer; \ @@ -2160,29 +2163,29 @@ struct CallMemberVTable : public CppiaExpr void runVoid(CppiaCtx *ctx) { - CALL_VTABLE_SETUP + CALL_VTABLE_SETUP() ctx->runVoid(func); } int runInt(CppiaCtx *ctx) { - CALL_VTABLE_SETUP - return runContextConvertInt(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); + CALL_VTABLE_SETUP(BCRReturn()) + return runContextConvertInt(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); } - + Float runFloat(CppiaCtx *ctx) { - CALL_VTABLE_SETUP - return runContextConvertFloat(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); + CALL_VTABLE_SETUP(BCRReturn()) + return runContextConvertFloat(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); } String runString(CppiaCtx *ctx) { - CALL_VTABLE_SETUP - return runContextConvertString(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); + CALL_VTABLE_SETUP(BCRReturn()) + return runContextConvertString(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); } hx::Object *runObject(CppiaCtx *ctx) { - CALL_VTABLE_SETUP - return runContextConvertObject(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); + CALL_VTABLE_SETUP(BCRReturn()) + return runContextConvertObject(ctx, checkInterfaceReturnType ? func->getReturnType() : returnType, func); } bool isBoolInt() { return boolResult; } @@ -3088,6 +3091,8 @@ struct Call : public CppiaDynamicExpr hx::Object *runObject(CppiaCtx *ctx) { hx::Object *funcVal = func->runObject(ctx); + BCR_CHECK; + CPPIA_CHECK_FUNC(funcVal); int size = args.size(); switch(size) diff --git a/src/hx/cppia/Cppia.h b/src/hx/cppia/Cppia.h index b8361537c..f8d862a07 100644 --- a/src/hx/cppia/Cppia.h +++ b/src/hx/cppia/Cppia.h @@ -835,7 +835,7 @@ struct BCRReturn #define BCR_CHECK if (ctx->breakContReturn || ctx->exception) return BCRReturn(); -#define BCR_CHECK_RET(x) if (ctx->breakContReturn) return x; +#define BCR_CHECK_RET(x) if (ctx->breakContReturn || ctx->exception) return x; #define BCR_VCHECK if (ctx->breakContReturn || ctx->exception) return; From c85576efaf09cece22fff998a6e02d765beb2e4b Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 10 Apr 2025 16:41:01 +0100 Subject: [PATCH 2/4] [cppia] Test for method on exception throwing expr --- test/cppia/Client.hx | 14 +++++++++ test/cppia/LocalFunctionExceptions.hx | 42 ++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/test/cppia/Client.hx b/test/cppia/Client.hx index 67842a75a..27462e88b 100644 --- a/test/cppia/Client.hx +++ b/test/cppia/Client.hx @@ -189,6 +189,20 @@ class Client default: } + switch LocalFunctionExceptions.testObjMethodOnReturn() { + case Error(message): + Common.status = 'Failed test for running object method on returned value: ' + message; + return; + default: + } + + switch LocalFunctionExceptions.testClassMethodOnReturn() { + case Error(message): + Common.status = 'Failed test for running class method on returned value: ' + message; + return; + default: + } + final extending = new ClientExtendedExtendedRoot(); extending.addValue(); diff --git a/test/cppia/LocalFunctionExceptions.hx b/test/cppia/LocalFunctionExceptions.hx index 3caae76bc..a5519ec0a 100644 --- a/test/cppia/LocalFunctionExceptions.hx +++ b/test/cppia/LocalFunctionExceptions.hx @@ -3,8 +3,12 @@ enum Status { Error(message:String); } +class DummyClass { + public function run() {} +} + class LocalFunctionExceptions { - static function staticFunction() { + static function staticFunction():Dynamic { throw 'Thrown from static'; } @@ -65,4 +69,40 @@ class LocalFunctionExceptions { return Error("No exception caught"); } + + public static function testObjMethodOnReturn():Status { + function localFunction() { + (staticFunction() : Dynamic).run(); + } + + try { + localFunction(); + } catch (e:String) { + if (e == 'Thrown from static') { + return Ok; + } else { + return Error("Incorrect exception caught from local function call: " + e); + } + } + + return Error("No exception caught"); + } + + public static function testClassMethodOnReturn():Status { + function localFunction() { + (staticFunction() : DummyClass).run(); + } + + try { + localFunction(); + } catch (e:String) { + if (e == 'Thrown from static') { + return Ok; + } else { + return Error("Incorrect exception caught from local function call: " + e); + } + } + + return Error("No exception caught"); + } } From 1333ad56da5b2049595b8af1338a6be777a8d963 Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 10 Apr 2025 21:13:51 +0100 Subject: [PATCH 3/4] [cppia] Add test for host class method call This covers the CallHaxe bug --- test/cppia/Client.hx | 7 +++++++ test/cppia/Common.hx | 1 + test/cppia/LocalFunctionExceptions.hx | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/test/cppia/Client.hx b/test/cppia/Client.hx index 27462e88b..2b3feb1b2 100644 --- a/test/cppia/Client.hx +++ b/test/cppia/Client.hx @@ -203,6 +203,13 @@ class Client default: } + switch LocalFunctionExceptions.testHostClassMethodOnHostReturn() { + case Error(message): + Common.status = 'Failed test for running host class method on returned value: ' + message; + return; + default: + } + final extending = new ClientExtendedExtendedRoot(); extending.addValue(); diff --git a/test/cppia/Common.hx b/test/cppia/Common.hx index 99f80f815..e547881b6 100644 --- a/test/cppia/Common.hx +++ b/test/cppia/Common.hx @@ -8,4 +8,5 @@ class Common public static var callbackSet:Int = 0; public static var callback: Void->Void; + public function dummyMethod() {} } diff --git a/test/cppia/LocalFunctionExceptions.hx b/test/cppia/LocalFunctionExceptions.hx index a5519ec0a..0b6ce174b 100644 --- a/test/cppia/LocalFunctionExceptions.hx +++ b/test/cppia/LocalFunctionExceptions.hx @@ -105,4 +105,22 @@ class LocalFunctionExceptions { return Error("No exception caught"); } + + public static function testHostClassMethodOnHostReturn():Status { + function localFunction() { + (staticFunction() : Common).dummyMethod(); + } + + try { + localFunction(); + } catch (e:String) { + if (e == 'Thrown from static') { + return Ok; + } else { + return Error("Incorrect exception caught from local function call: " + e); + } + } + + return Error("No exception caught"); + } } From c75a21a76edde3f42815173015961868e7a7db2f Mon Sep 17 00:00:00 2001 From: Tobiasz Laskowski Date: Thu, 10 Apr 2025 21:58:00 +0100 Subject: [PATCH 4/4] [cppia] Fix throw/catch of seg faults in tests The host must be compiled with HXCPP_CATCH_SEGV so that seg faults are handled as hxcpp exceptions. --- test/cppia/LocalFunctionExceptions.hx | 6 +++--- test/cppia/compile-host.hxml | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/cppia/LocalFunctionExceptions.hx b/test/cppia/LocalFunctionExceptions.hx index 0b6ce174b..7395daeb6 100644 --- a/test/cppia/LocalFunctionExceptions.hx +++ b/test/cppia/LocalFunctionExceptions.hx @@ -77,7 +77,7 @@ class LocalFunctionExceptions { try { localFunction(); - } catch (e:String) { + } catch (e:Dynamic) { if (e == 'Thrown from static') { return Ok; } else { @@ -95,7 +95,7 @@ class LocalFunctionExceptions { try { localFunction(); - } catch (e:String) { + } catch (e:Dynamic) { if (e == 'Thrown from static') { return Ok; } else { @@ -113,7 +113,7 @@ class LocalFunctionExceptions { try { localFunction(); - } catch (e:String) { + } catch (e:Dynamic) { if (e == 'Thrown from static') { return Ok; } else { diff --git a/test/cppia/compile-host.hxml b/test/cppia/compile-host.hxml index efe8bdf09..218812e3f 100644 --- a/test/cppia/compile-host.hxml +++ b/test/cppia/compile-host.hxml @@ -3,4 +3,5 @@ -D dll_export=host_classes.info -L utest --dce no ---cpp bin \ No newline at end of file +--cpp bin +-D HXCPP_CATCH_SEGV