]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
luawrapper: don't segfault on failure in traceback handler 16230/head
authorPeter van Dijk <peter.van.dijk@powerdns.com>
Thu, 9 Oct 2025 11:41:29 +0000 (13:41 +0200)
committerPeter van Dijk <peter.van.dijk@powerdns.com>
Thu, 9 Oct 2025 14:45:46 +0000 (16:45 +0200)
Signed-off-by: Peter van Dijk <peter.van.dijk@powerdns.com>
ext/luawrapper/include/LuaContext.hpp

index 66f879eb8369405bf3cb7401186e6eb5cdc67be4..b7de2c1c4379f1bef3600a3fc0d388208a36c43b 100644 (file)
@@ -1450,21 +1450,26 @@ private:
 
         // if pcall failed, analyzing the problem and throwing
         if (pcallReturnValue != 0) {
+            switch (pcallReturnValue) {
+                case LUA_ERRMEM:
+                    throw std::bad_alloc{};
+                case LUA_ERRERR:
+                    throw ExecutionErrorException("while handling a Lua error, the traceback handler failed (LUA_ERRERR)");
+                // all other values should have left us an error and a traceback
+            }
+   
 
-            // stack top: {error, traceback}
-            lua_rawgeti(state, -1, 1); // stack top: {error, traceback}, error
-            lua_rawgeti(state, -2, 2); // stack top: {error, traceback}, error, traceback
-            lua_remove(state, -3); // stack top: error, traceback
-
-            PushedObject traceBackRef{state, 1};
-            const auto traceBack = readTopAndPop<std::string>(state, std::move(traceBackRef)); // stack top: error
-            PushedObject errorCode{state, 1};
+            if (lua_gettop(state) >= 1 && lua_type(state, -1) == LUA_TTABLE) {
+                // stack top: {error, traceback}
+                lua_rawgeti(state, -1, 1); // stack top: {error, traceback}, error
+                lua_rawgeti(state, -2, 2); // stack top: {error, traceback}, error, traceback
+                lua_remove(state, -3); // stack top: error, traceback
 
-            // an error occurred during execution, either an error message or a std::exception_ptr was pushed on the stack
-            if (pcallReturnValue == LUA_ERRMEM) {
-                throw std::bad_alloc{};
+                PushedObject traceBackRef{state, 1};
+                const auto traceBack = readTopAndPop<std::string>(state, std::move(traceBackRef)); // stack top: error
+                PushedObject errorCode{state, 1};
 
-            } else if (pcallReturnValue == LUA_ERRRUN) {
+                // an error occurred during execution, either an error message or a std::exception_ptr was pushed on the stack
                 if (lua_isstring(state, 1)) {
                     // the error is a string
                     const auto str = readTopAndPop<std::string>(state, std::move(errorCode));
@@ -1485,6 +1490,9 @@ private:
                     throw ExecutionErrorException{"Unknown Lua error"};
                 }
             }
+            else {
+                throw ExecutionErrorException("while handling a Lua error, the traceback handler did not return a table (" + std::to_string(pcallReturnValue) + ")");
+            }
         }
 
         return PushedObject{state, outArguments};