|
From: <fli...@li...> - 2026-05-07 05:49:49
|
unknown user pushed a commit to branch next
in repository simgear.
The following commit(s) were added to refs/heads/next by this push:
new fa14d6cd Fix crash when NasalCode call fails
fa14d6cd is described below
SF URL: http://sourceforge.net/p/flightgear/simgear/ci/fa14d6cde0baf7f6397bf5298e350c20491d37a7/
Commit: fa14d6cde0baf7f6397bf5298e350c20491d37a7
Author: James Turner
Committer: James Turner
AuthorDate: Wed May 6 11:55:50 2026 +0100
Fix crash when NasalCode call fails
---
simgear/nasal/cppbind/NasalCode.cxx | 25 +++++++++++++++++++++++++
simgear/nasal/cppbind/test/cppbind_test.cxx | 22 ++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/simgear/nasal/cppbind/NasalCode.cxx b/simgear/nasal/cppbind/NasalCode.cxx
index 2be18b6a..a0cdc450 100644
--- a/simgear/nasal/cppbind/NasalCode.cxx
+++ b/simgear/nasal/cppbind/NasalCode.cxx
@@ -7,6 +7,8 @@
#include <sstream>
+#include <simgear/structure/exception.hxx>
+
namespace nasal {
//----------------------------------------------------------------------------
@@ -67,6 +69,17 @@ naRef NasalCode::doCall(Context& ctx, std::initializer_list<naRef> args) const
naNil() // locals
);
+ // naCallMethodCtx has already invoked the registered error handler
+ // (which logs the error). Re-surface it as a C++ exception so that
+ // callers can detect the failure and disable the offending code path.
+ if (const char* err = naGetError(ctx)) {
+ int line = naGetLine(ctx, 0);
+ char* file = naStr_data(naGetSourceFile(ctx, 0));
+ throw sg_exception(std::string("Nasal runtime error: ") + err,
+ "",
+ sg_location(file, line));
+ }
+
return result;
}
@@ -94,6 +107,18 @@ naRef NasalCode::callWithLocals(naRef locals) const
locals);
naGCRelease(lsave);
+
+ // naCallMethodCtx has already invoked the registered error handler
+ // (which logs the error). Re-surface it as a C++ exception so that
+ // callers can detect the failure and disable the offending code path.
+ if (const char* err = naGetError(ctx)) {
+ int line = naGetLine(ctx, 0);
+ char* file = naStr_data(naGetSourceFile(ctx, 0));
+ throw sg_exception(std::string("Nasal runtime error: ") + err,
+ "",
+ sg_location(file, line));
+ }
+
return result;
}
diff --git a/simgear/nasal/cppbind/test/cppbind_test.cxx b/simgear/nasal/cppbind/test/cppbind_test.cxx
index f32b681d..2f8ab823 100644
--- a/simgear/nasal/cppbind/test/cppbind_test.cxx
+++ b/simgear/nasal/cppbind/test/cppbind_test.cxx
@@ -10,6 +10,7 @@
#include <simgear/nasal/cppbind/NasalCode.hxx>
#include <simgear/nasal/cppbind/NasalHash.hxx>
#include <simgear/nasal/cppbind/NasalString.hxx>
+#include <simgear/structure/exception.hxx>
#include <simgear/structure/map.hxx>
#include <cstring>
@@ -579,4 +580,25 @@ BOOST_AUTO_TEST_CASE(nasal_code)
naRef result = code.callWithLocals(locals.get_naRef());
BOOST_CHECK_EQUAL(ctx.from_nasal<double>(result), 42.0);
}
+
+ // call() with a runtime error must throw sg_exception, not crash
+ {
+ TestContext ctx;
+ Hash globals(ctx);
+
+ NasalCode code(globals.get_naRef(), "undefined_sym()");
+ BOOST_REQUIRE(code.isValid()); // parses fine; error is at call time
+ BOOST_CHECK_THROW(code.call(), sg_exception);
+ }
+
+ // callWithLocals() with a runtime error must also throw sg_exception
+ {
+ TestContext ctx;
+ Hash locals(ctx);
+ Hash globals(ctx);
+
+ NasalCode code(globals.get_naRef(), "no_such_func()");
+ BOOST_REQUIRE(code.isValid());
+ BOOST_CHECK_THROW(code.callWithLocals(locals.get_naRef()), sg_exception);
+ }
}
|