From: Thierry FOURNIER Date: Thu, 14 Jul 2016 09:42:37 +0000 (+0200) Subject: BUG/MEDIUM: lua: the function txn_done() from sample fetches can crash X-Git-Tag: v1.7-dev4~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ab00df6cf64c0840aa9dd20cee4eb8e9f4297eba;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: lua: the function txn_done() from sample fetches can crash The function txn_done() ends a transaction. It does not make sense to call this function from a lua sample-fetch wrapper, because the role of a sample-fetch is not to terminate a transaction. This patch modify the role of the fucntion txn_done() if it is called from a sample-fetch wrapper, now it just ends the execution of the Lua code like the done() function. Must be backported in 1.6 --- diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index 2bca4d07f5..dccf415620 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -1460,6 +1460,11 @@ TXN class session. It can be used when a critical error is detected or to terminate processing after some data have been returned to the client (eg: a redirect). + *Warning*: It not make sense to call this function from sample-fetches. In + this case the behaviour of this one is the same than core.done(): it quit + the Lua execution. The transaction is really aborted only from an action + registered function. + :param class_txn txn: The class txn object containing the data. .. js:function:: TXN.set_loglevel(txn, loglevel) diff --git a/include/types/hlua.h b/include/types/hlua.h index 43e9f1a6cd..b22e03e7d8 100644 --- a/include/types/hlua.h +++ b/include/types/hlua.h @@ -35,6 +35,8 @@ struct stream; #define HLUA_F_AS_STRING 0x01 #define HLUA_F_MAY_USE_HTTP 0x02 +#define HLUA_TXN_NOTERM 0x00000001 + #define HLUA_CONCAT_BLOCSZ 2048 enum hlua_exec { @@ -109,6 +111,7 @@ struct hlua_txn { struct stream *s; struct proxy *p; int dir; /* SMP_OPT_DIR_{REQ,RES} */ + int flags; }; /* This struct contains the applet context. */ diff --git a/src/hlua.c b/src/hlua.c index 953c219bdf..f9a317d65f 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -4601,7 +4601,7 @@ __LJMP static int hlua_get_priv(lua_State *L) * return 0 if the stack does not contains free slots, * otherwise it returns 1. */ -static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir) +static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir, int flags) { struct hlua_txn *htxn; @@ -4621,6 +4621,7 @@ static int hlua_txn_new(lua_State *L, struct stream *s, struct proxy *p, int dir htxn->s = s; htxn->p = p; htxn->dir = dir; + htxn->flags = flags; /* Create the "f" field that contains a list of fetches. */ lua_pushstring(L, "f"); @@ -4814,6 +4815,15 @@ __LJMP static int hlua_txn_done(lua_State *L) MAY_LJMP(check_args(L, 1, "close")); htxn = MAY_LJMP(hlua_checktxn(L, 1)); + /* If the flags NOTERM is set, we cannot terminate the http + * session, so we just end the execution of the current + * lua code. + */ + if (htxn->flags & HLUA_TXN_NOTERM) { + WILL_LJMP(hlua_done(L)); + return 0; + } + ic = &htxn->s->req; oc = &htxn->s->res; @@ -5265,7 +5275,8 @@ static int hlua_sample_fetch_wrapper(const struct arg *arg_p, struct sample *smp lua_rawgeti(stream->hlua.T, LUA_REGISTRYINDEX, fcn->function_ref); /* push arguments in the stack. */ - if (!hlua_txn_new(stream->hlua.T, stream, smp->px, smp->opt & SMP_OPT_DIR)) { + if (!hlua_txn_new(stream->hlua.T, stream, smp->px, smp->opt & SMP_OPT_DIR, + HLUA_TXN_NOTERM)) { SEND_ERR(smp->px, "Lua sample-fetch '%s': full stack.\n", fcn->name); RESET_SAFE_LJMP(stream->hlua.T); return 0; @@ -5511,7 +5522,7 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px, lua_rawgeti(s->hlua.T, LUA_REGISTRYINDEX, rule->arg.hlua_rule->fcn.function_ref); /* Create and and push object stream in the stack. */ - if (!hlua_txn_new(s->hlua.T, s, px, dir)) { + if (!hlua_txn_new(s->hlua.T, s, px, dir, 0)) { SEND_ERR(px, "Lua function '%s': full stack.\n", rule->arg.hlua_rule->fcn.name); RESET_SAFE_LJMP(s->hlua.T);