lua_drop_global_lock();
}
+/* below is an helper function to retrieve string on on Lua stack at <index>
+ * in a safe way (function may not LJMP). It can be useful to retrieve errors
+ * at the top of the stack from an unprotected environment.
+ *
+ * The returned string will is only valid as long as the value at <index> is
+ * not removed from the stack.
+ *
+ * It is assumed that the calling function is allowed to manipulate <L>
+ */
+__LJMP static int _hlua_tostring_safe(lua_State *L)
+{
+ const char **str = lua_touserdata(L, 1);
+ const char *cur_str = MAY_LJMP(lua_tostring(L, 2));
+
+ if (cur_str)
+ *str = cur_str;
+ return 0;
+}
+static const char *hlua_tostring_safe(lua_State *L, int index)
+{
+ const char *str = NULL;
+
+ if (!lua_checkstack(L, 4))
+ return NULL;
+
+ /* before any stack modification, save the targeted value on the top of
+ * the stack: this will allow us to use relative index to target it.
+ */
+ lua_pushvalue(L, index);
+
+ /* push our custom _hlua_tostring_safe() function on the stack, then push
+ * our own string pointer and targeted value (at <index>) as argument
+ */
+ lua_pushcfunction(L, _hlua_tostring_safe);
+ lua_pushlightuserdata(L, &str); // 1st func argument = string pointer
+ lua_pushvalue(L, -3); // 2nd func argument = targeted value
+
+ lua_remove(L, -4); // remove <index> copy as we're done using it
+
+ /* call our custom function with proper arguments using pcall() to catch
+ * exceptions (if any)
+ */
+ switch (lua_pcall(L, 2, 0, 0)) {
+ case LUA_OK:
+ break;
+ default:
+ /* error was caught */
+ return NULL;
+ }
+ return str;
+}
+
#define SET_SAFE_LJMP_L(__L, __HLUA) \
({ \
int ret; \
ret = HLUA_E_ERR;
break;
}
- msg = lua_tostring(lua->T, -1);
+ msg = hlua_tostring_safe(lua->T, -1);
trace = hlua_traceback(lua->T, ", ");
if (msg)
lua_pushfstring(lua->T, "[state-id %d] runtime error: %s from %s", lua->state_id, msg, trace);
ret = HLUA_E_ERR;
break;
}
- msg = lua_tostring(lua->T, -1);
+ msg = hlua_tostring_safe(lua->T, -1);
if (msg)
lua_pushfstring(lua->T, "[state-id %d] message handler error: %s", lua->state_id, msg);
else
SEND_ERR(NULL, "Lua task: execution timeout.\n");
goto err_task_abort;
case HLUA_E_ERRMSG:
- SEND_ERR(NULL, "Lua task: %s.\n", lua_tostring(hlua->T, -1));
+ SEND_ERR(NULL, "Lua task: %s.\n", hlua_tostring_safe(hlua->T, -1));
goto err_task_abort;
case HLUA_E_ERR:
default:
break;
case HLUA_E_ERRMSG:
- SEND_ERR(NULL, "Lua event_hdl: %s.\n", lua_tostring(hlua->T, -1));
+ SEND_ERR(NULL, "Lua event_hdl: %s.\n", hlua_tostring_safe(hlua->T, -1));
break;
case HLUA_E_ERR:
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(hlua_sub->hlua)) {
if (lua_type(hlua_sub->hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(hlua_sub->hlua->T, -1);
+ error = hlua_tostring_safe(hlua_sub->hlua->T, -1);
else
error = "critical error";
ha_alert("Lua event_hdl: %s.\n", error);
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(stream->hlua)) {
if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(stream->hlua->T, -1);
+ error = hlua_tostring_safe(stream->hlua->T, -1);
else
error = "critical error";
SEND_ERR(stream->be, "Lua converter '%s': %s.\n", fcn->name, error);
case HLUA_E_ERRMSG:
/* Display log. */
SEND_ERR(stream->be, "Lua converter '%s': %s.\n",
- fcn->name, lua_tostring(stream->hlua->T, -1));
+ fcn->name, hlua_tostring_safe(stream->hlua->T, -1));
lua_pop(stream->hlua->T, 1);
return 0;
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(stream->hlua)) {
if (lua_type(stream->hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(stream->hlua->T, -1);
+ error = hlua_tostring_safe(stream->hlua->T, -1);
else
error = "critical error";
SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n", fcn->name, error);
case HLUA_E_ERRMSG:
/* Display log. */
SEND_ERR(smp->px, "Lua sample-fetch '%s': %s.\n",
- fcn->name, lua_tostring(stream->hlua->T, -1));
+ fcn->name, hlua_tostring_safe(stream->hlua->T, -1));
lua_pop(stream->hlua->T, 1);
return 0;
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(s->hlua)) {
if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(s->hlua->T, -1);
+ error = hlua_tostring_safe(s->hlua->T, -1);
else
error = "critical error";
SEND_ERR(px, "Lua function '%s': %s.\n",
case HLUA_E_ERRMSG:
/* Display log. */
SEND_ERR(px, "Lua function '%s': %s.\n",
- rule->arg.hlua_rule->fcn->name, lua_tostring(s->hlua->T, -1));
+ rule->arg.hlua_rule->fcn->name, hlua_tostring_safe(s->hlua->T, -1));
lua_pop(s->hlua->T, 1);
goto end;
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(hlua)) {
if (lua_type(hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(hlua->T, -1);
+ error = hlua_tostring_safe(hlua->T, -1);
else
error = "critical error";
SEND_ERR(strm->be, "Lua applet tcp '%s': %s.\n",
case HLUA_E_ERRMSG:
/* Display log. */
SEND_ERR(px, "Lua applet tcp '%s': %s.\n",
- rule->arg.hlua_rule->fcn->name, lua_tostring(hlua->T, -1));
+ rule->arg.hlua_rule->fcn->name, hlua_tostring_safe(hlua->T, -1));
lua_pop(hlua->T, 1);
goto error;
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(hlua)) {
if (lua_type(hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(hlua->T, -1);
+ error = hlua_tostring_safe(hlua->T, -1);
else
error = "critical error";
SEND_ERR(strm->be, "Lua applet http '%s': %s.\n",
case HLUA_E_ERRMSG:
/* Display log. */
SEND_ERR(px, "Lua applet http '%s': %s.\n",
- rule->arg.hlua_rule->fcn->name, lua_tostring(hlua->T, -1));
+ rule->arg.hlua_rule->fcn->name, hlua_tostring_safe(hlua->T, -1));
lua_pop(hlua->T, 1);
goto error;
/* The following Lua calls can fail. */
if (!SET_SAFE_LJMP(hlua)) {
if (lua_type(hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(hlua->T, -1);
+ error = hlua_tostring_safe(hlua->T, -1);
else
error = "critical error";
SEND_ERR(NULL, "Lua cli '%s': %s.\n", fcn->name, error);
case HLUA_E_ERRMSG:
/* Display log. */
SEND_ERR(NULL, "Lua cli '%s': %s.\n",
- fcn->name, lua_tostring(hlua->T, -1));
+ fcn->name, hlua_tostring_safe(hlua->T, -1));
lua_pop(hlua->T, 1);
return 1;
conf->ref[state_id] = flt_ref;
break;
case LUA_ERRRUN:
- ha_alert("Lua filter '%s' : runtime error : %s", conf->reg->name, lua_tostring(L, -1));
+ ha_alert("Lua filter '%s' : runtime error : %s", conf->reg->name, hlua_tostring_safe(L, -1));
goto error;
case LUA_ERRMEM:
ha_alert("Lua filter '%s' : out of memory error", conf->reg->name);
goto error;
case LUA_ERRERR:
- ha_alert("Lua filter '%s' : message handler error : %s", conf->reg->name, lua_tostring(L, -1));
+ ha_alert("Lua filter '%s' : message handler error : %s", conf->reg->name, hlua_tostring_safe(L, -1));
goto error;
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 503
case LUA_ERRGCMM:
- ha_alert("Lua filter '%s' : garbage collector error : %s", conf->reg->name, lua_tostring(L, -1));
+ ha_alert("Lua filter '%s' : garbage collector error : %s", conf->reg->name, hlua_tostring_safe(L, -1));
goto error;
#endif
default:
- ha_alert("Lua filter '%s' : unknown error : %s", conf->reg->name, lua_tostring(L, -1));
+ ha_alert("Lua filter '%s' : unknown error : %s", conf->reg->name, hlua_tostring_safe(L, -1));
goto error;
}
const char *error;
if (lua_type(s->hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(s->hlua->T, -1);
+ error = hlua_tostring_safe(s->hlua->T, -1);
else
error = "critical error";
SEND_ERR(s->be, "Lua filter '%s': %s.\n", conf->reg->name, error);
filter->ctx = flt_ctx;
break;
case HLUA_E_ERRMSG:
- SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, lua_tostring(s->hlua->T, -1));
+ SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, hlua_tostring_safe(s->hlua->T, -1));
ret = -1;
goto end;
case HLUA_E_ETMOUT:
const char *error;
if (lua_type(flt_hlua->T, -1) == LUA_TSTRING)
- error = lua_tostring(flt_hlua->T, -1);
+ error = hlua_tostring_safe(flt_hlua->T, -1);
else
error = "critical error";
SEND_ERR(s->be, "Lua filter '%s': %s.\n", conf->reg->name, error);
ret = 0;
goto end;
case HLUA_E_ERRMSG:
- SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, lua_tostring(flt_hlua->T, -1));
+ SEND_ERR(s->be, "Lua filter '%s' : %s.\n", conf->reg->name, hlua_tostring_safe(flt_hlua->T, -1));
ret = -1;
goto end;
case HLUA_E_ETMOUT:
/* Just load and compile the file. */
error = luaL_loadfile(L, args[0]);
if (error) {
- memprintf(err, "error in Lua file '%s': %s", args[0], lua_tostring(L, -1));
+ memprintf(err, "error in Lua file '%s': %s", args[0], hlua_tostring_safe(L, -1));
lua_pop(L, 1);
return -1;
}
case LUA_OK:
break;
case LUA_ERRRUN:
- memprintf(err, "Lua runtime error: %s", lua_tostring(L, -1));
+ memprintf(err, "Lua runtime error: %s", hlua_tostring_safe(L, -1));
lua_pop(L, 1);
return -1;
case LUA_ERRMEM:
memprintf(err, "Lua out of memory error");
return -1;
case LUA_ERRERR:
- memprintf(err, "Lua message handler error: %s", lua_tostring(L, -1));
+ memprintf(err, "Lua message handler error: %s", hlua_tostring_safe(L, -1));
lua_pop(L, 1);
return -1;
#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 503
case LUA_ERRGCMM:
- memprintf(err, "Lua garbage collector error: %s", lua_tostring(L, -1));
+ memprintf(err, "Lua garbage collector error: %s", hlua_tostring_safe(L, -1));
lua_pop(L, 1);
return -1;
#endif
default:
- memprintf(err, "Lua unknown error: %s", lua_tostring(L, -1));
+ memprintf(err, "Lua unknown error: %s", hlua_tostring_safe(L, -1));
lua_pop(L, 1);
return -1;
}
if (setjmp(safe_ljmp_env) != 0) {
lua_atpanic(L, hlua_panic_safe);
if (lua_type(L, -1) == LUA_TSTRING)
- error = lua_tostring(L, -1);
+ error = hlua_tostring_safe(L, -1);
else
error = "critical error";
fprintf(stderr, "lua-prepend-path: %s.\n", error);
if (setjmp(safe_ljmp_env) != 0) {
lua_atpanic(L, hlua_panic_safe);
if (lua_type(L, -1) == LUA_TSTRING)
- error = lua_tostring(L, -1);
+ error = hlua_tostring_safe(L, -1);
else
error = "critical error";
fprintf(stderr, "Lua post-init: %s.\n", error);
case LUA_ERRRUN:
if (!kind)
kind = "runtime error";
- msg = lua_tostring(L, -1);
+ msg = hlua_tostring_safe(L, -1);
trace = hlua_traceback(L, ", ");
if (msg)
ha_alert("Lua init: %s: '%s' from %s\n", kind, msg, trace);
if (setjmp(safe_ljmp_env) != 0) {
lua_atpanic(L, hlua_panic_safe);
if (lua_type(L, -1) == LUA_TSTRING)
- error_msg = lua_tostring(L, -1);
+ error_msg = hlua_tostring_safe(L, -1);
else
error_msg = "critical error";
fprintf(stderr, "Lua init: %s.\n", error_msg);