]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: hlua: consume error object if ignored after a failing lua_pcall()
authorAurelien DARRAGON <adarragon@haproxy.com>
Fri, 23 Jan 2026 09:58:26 +0000 (10:58 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Fri, 23 Jan 2026 10:23:37 +0000 (11:23 +0100)
We frequently use lua_pcall() to provide safe alternative functions
(encapsulated helpers) that prevent the process from crashing in case
of Lua error when Lua is executed from an unsafe environment.

However, some of those safe helpers don't handle errors properly. In case
of error, the Lua API will always put an error object on top of the stack
as stated in the documentation. This error object can be used to retrieve
more info about the error. But in some cases when we ignore it, we should
still consume it to prevent the stack from being altered with an extra
object when returning from the helper function.

It should be backported to all stable versions. If the patch doesn't apply
automatically, all that's needed is to check for lua_pcall() in hlua.c
and for other cases than 'LUA_OK', make sure that the error object is popped
from the stack before the function returns.

src/hlua.c

index 4ef5a8cf5cb0b8c2cefa34b6e0a689b49ccc1173..b826e6ab867d9725e24c049a2f4c4492bf059d1e 100644 (file)
@@ -273,6 +273,7 @@ static const char *hlua_tostring_safe(lua_State *L, int index)
                        break;
                default:
                        /* error was caught */
+                       lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
                        return NULL;
        }
        return str;
@@ -323,6 +324,7 @@ static const char *hlua_pushvfstring_safe(lua_State *L, const char *fmt, va_list
                        break;
                default:
                        /* error was caught */
+                       lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
                        dst = NULL;
        }
        va_end(cpy_argp);
@@ -904,6 +906,7 @@ const char *hlua_traceback(lua_State *L, const char* sep)
                        case LUA_OK:
                                break;
                        default:
+                               lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
                                goto end; // abort
                }
 
@@ -1002,6 +1005,7 @@ static int hlua_pusherror(lua_State *L, const char *fmt, ...)
                case LUA_OK:
                        break;
                default:
+                       lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
                        ret = 0;
        }
 
@@ -10192,6 +10196,7 @@ static int hlua_new_event_sub_safe(lua_State *L, struct event_hdl_sub *sub)
                        return 1;
                default:
                        /* error was caught */
+                       lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
                        return 0;
        }
 }