From: Christopher Faulet Date: Thu, 22 Oct 2026 13:32:03 +0000 (+0200) Subject: BUG/MINOR: hlua/filters: Track the payload phase per channel X-Git-Tag: v3.5-dev10~63 X-Git-Url: https://git.kaiwu.me/$%7BISSUES%7D/static/gitweb.js?a=commitdiff_plain;h=0676fccefb8b7be7f057502fbd97c4798a8932ac;p=haproxy.git BUG/MINOR: hlua/filters: Track the payload phase per channel HLUA_FLT_CTX_FL_PAYLOAD is used to know if a filter is in its payload forwarding stage, when its http_payload or tcp_payload callback is called, because the data of a channel may only be manipulated in this context. But this was a per-context flag, shared by both channels, while the payload phase is specific to a channel. Thus, when a filter processed the request payload, a forbidden operation could be performed on the response data while it was analyzed, and reciprocally. Now the payload phase is tracked per channel, with a dedicated flag for the request and the response. All the data manipulation functions now check the flag of the channel on which they operate. The flags are set or cleared by the payload and analysis callbacks of the corresponding channel. In particular, start_analyze only clears the flag of the channel being analyzed, so starting the analysis of a channel no longer resets the payload phase of the other one. --- diff --git a/src/hlua.c b/src/hlua.c index c62b952b4..f2f12b23c 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -414,7 +414,9 @@ static lua_State *hlua_states[MAX_THREADS + 1]; #define HLUA_FLT_CB_ARG_CHN 0x00000004 #define HLUA_FLT_CB_ARG_HTTP_MSG 0x00000008 -#define HLUA_FLT_CTX_FL_PAYLOAD 0x00000001 +#define HLUA_FLT_CTX_FL_REQ_PAYLOAD 0x00000001 +#define HLUA_FLT_CTX_FL_RES_PAYLOAD 0x00000002 +#define HLUA_FLT_CTX_FL_PAYLOAD_BIT(idx) ((idx) ? HLUA_FLT_CTX_FL_RES_PAYLOAD : HLUA_FLT_CTX_FL_REQ_PAYLOAD) const char *hlua_filter_cls_name = "lua"; @@ -478,7 +480,7 @@ struct hlua_cli_ctx { DECLARE_STATIC_TYPED_POOL(pool_head_hlua_flt_ctx, "hlua_flt_ctx", struct hlua_flt_ctx); -static int hlua_filter_from_payload(struct filter *filter); +static int hlua_filter_from_payload(struct filter *filter, struct channel *chn); /* This is the chained list of struct hlua_flt referenced * for haproxy filters. It is used for a post-initialisation control. @@ -3856,7 +3858,7 @@ static struct filter *hlua_channel_filter(lua_State *L, int ud, struct channel * filter = lua_touserdata (L, -1); flt_ctx = filter->ctx; - if (hlua_filter_from_payload(filter)) { + if (hlua_filter_from_payload(filter, chn)) { *offset = flt_ctx->cur_off[CHN_IDX(chn)]; *len = flt_ctx->cur_len[CHN_IDX(chn)]; } @@ -3945,7 +3947,7 @@ __LJMP static int hlua_channel_get_data_yield(lua_State *L, int status, lua_KCon input = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &output, &input); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -4028,7 +4030,7 @@ __LJMP static int hlua_channel_get_line_yield(lua_State *L, int status, lua_KCon input = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &output, &input); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -4122,7 +4124,7 @@ __LJMP static int hlua_channel_dup(lua_State *L) len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); if (!ci_data(chn) && channel_input_closed(chn)) { @@ -4161,7 +4163,7 @@ __LJMP static int hlua_channel_get(lua_State *L) len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); if (!ci_data(chn) && channel_input_closed(chn)) { @@ -4195,7 +4197,7 @@ __LJMP static int hlua_channel_getline_yield(lua_State *L, int status, lua_KCont len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); if (!ci_data(chn) && channel_input_closed(chn)) { @@ -4303,7 +4305,7 @@ __LJMP static int hlua_channel_append(lua_State *L) len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); ret = _hlua_channel_insert(chn, L, ist2(str, sz), offset); @@ -4344,7 +4346,7 @@ __LJMP static int hlua_channel_prepend(lua_State *L) len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); ret = _hlua_channel_insert(chn, L, ist2(str, sz), offset); @@ -4383,7 +4385,7 @@ __LJMP static int hlua_channel_insert_data(lua_State *L) input = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &output, &input); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -4442,7 +4444,7 @@ __LJMP static int hlua_channel_set_data(lua_State *L) input = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &output, &input); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -4516,7 +4518,7 @@ __LJMP static int hlua_channel_del_data(lua_State *L) input = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &output, &input); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -4586,7 +4588,7 @@ __LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); @@ -4698,7 +4700,7 @@ __LJMP static int hlua_channel_forward_yield(lua_State *L, int status, lua_KCont len = ci_data(chn); filter = hlua_channel_filter(L, 1, chn, &offset, &len); - if (filter && !hlua_filter_from_payload(filter)) + if (filter && !hlua_filter_from_payload(filter, chn)) WILL_LJMP(lua_error(L)); max = fwd - l; @@ -7533,7 +7535,7 @@ __LJMP static int hlua_http_msg_get_body(lua_State *L) WILL_LJMP(lua_error(L)); filter = hlua_http_msg_filter(L, 1, msg, &output, &input); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); if (!ci_data(msg->chn) && channel_input_closed(msg->chn)) { @@ -7592,7 +7594,7 @@ __LJMP static int hlua_http_msg_append(lua_State *L) str = MAY_LJMP(luaL_checklstring(L, 2, &sz)); filter = hlua_http_msg_filter(L, 1, msg, &offset, &len); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset+len); @@ -7622,7 +7624,7 @@ __LJMP static int hlua_http_msg_prepend(lua_State *L) str = MAY_LJMP(luaL_checklstring(L, 2, &sz)); filter = hlua_http_msg_filter(L, 1, msg, &offset, &len); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); ret = _hlua_http_msg_insert(msg, filter, ist2(str, sz), offset); @@ -7655,7 +7657,7 @@ __LJMP static int hlua_http_msg_insert_data(lua_State *L) str = MAY_LJMP(luaL_checklstring(L, 2, &sz)); filter = hlua_http_msg_filter(L, 1, msg, &output, &input); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -7696,7 +7698,7 @@ __LJMP static int hlua_http_msg_del_data(lua_State *L) WILL_LJMP(lua_error(L)); filter = hlua_http_msg_filter(L, 1, msg, &output, &input); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -7757,7 +7759,7 @@ __LJMP static int hlua_http_msg_set_data(lua_State *L) str = MAY_LJMP(luaL_checklstring(L, 2, &sz)); filter = hlua_http_msg_filter(L, 1, msg, &output, &input); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); offset = output; @@ -7821,7 +7823,7 @@ __LJMP static int hlua_http_msg_send(lua_State *L) str = MAY_LJMP(luaL_checklstring(L, 2, &sz)); filter = hlua_http_msg_filter(L, 1, msg, &offset, &len); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); /* Return an error if the channel's output is closed */ @@ -7871,7 +7873,7 @@ __LJMP static int hlua_http_msg_forward(lua_State *L) fwd = MAY_LJMP(luaL_checkinteger(L, 2)); filter = hlua_http_msg_filter(L, 1, msg, &offset, &len); - if (!filter || !hlua_filter_from_payload(filter)) + if (!filter || !hlua_filter_from_payload(filter, msg->chn)) WILL_LJMP(lua_error(L)); /* Nothing to do, just return */ @@ -12267,11 +12269,18 @@ static void hlua_filter_delete(struct stream *s, struct filter *filter) filter->ctx = NULL; } -static int hlua_filter_from_payload(struct filter *filter) +/* Returns true if the filter is currently processing the payload of the + * channel , from its http_payload or tcp_payload callback. This is the + * only context where the data of a channel may be manipulated from lua. The + * payload-processing phase is tracked per channel: when a filter processes + * the payload of the request, it must not be allowed to manipulate the data + * of the response while it is analyzed, and reciprocally. + */ +static int hlua_filter_from_payload(struct filter *filter, struct channel *chn) { struct hlua_flt_ctx *flt_ctx = filter->ctx; - return (flt_ctx && !!(flt_ctx->flags & HLUA_FLT_CTX_FL_PAYLOAD)); + return (flt_ctx && !!(flt_ctx->flags & HLUA_FLT_CTX_FL_PAYLOAD_BIT(CHN_IDX(chn)))); } static int hlua_filter_callback(struct stream *s, struct filter *filter, const char *fun, @@ -12443,7 +12452,7 @@ static int hlua_filter_start_analyze(struct stream *s, struct filter *filter, s { struct hlua_flt_ctx *flt_ctx = filter->ctx; - flt_ctx->flags = 0; + flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD_BIT(CHN_IDX(chn)); return hlua_filter_callback(s, filter, "start_analyze", (!(chn->flags & CF_ISRESP) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES), (HLUA_FLT_CB_FINAL | HLUA_FLT_CB_RETVAL | HLUA_FLT_CB_ARG_CHN)); @@ -12453,7 +12462,7 @@ static int hlua_filter_end_analyze(struct stream *s, struct filter *filter, str { struct hlua_flt_ctx *flt_ctx = filter->ctx; - flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD; + flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD_BIT(CHN_IDX(chn)); return hlua_filter_callback(s, filter, "end_analyze", (!(chn->flags & CF_ISRESP) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES), (HLUA_FLT_CB_FINAL | HLUA_FLT_CB_RETVAL | HLUA_FLT_CB_ARG_CHN)); @@ -12463,7 +12472,7 @@ static int hlua_filter_http_headers(struct stream *s, struct filter *filter, st { struct hlua_flt_ctx *flt_ctx = filter->ctx; - flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD; + flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD_BIT(CHN_IDX(msg->chn)); return hlua_filter_callback(s, filter, "http_headers", (!(msg->chn->flags & CF_ISRESP) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES), (HLUA_FLT_CB_FINAL | HLUA_FLT_CB_RETVAL | HLUA_FLT_CB_ARG_HTTP_MSG)); @@ -12481,7 +12490,7 @@ static int hlua_filter_http_payload(struct stream *s, struct filter *filter, st flt_hlua = flt_ctx->hlua[idx]; flt_ctx->cur_off[idx] = offset; flt_ctx->cur_len[idx] = len; - flt_ctx->flags |= HLUA_FLT_CTX_FL_PAYLOAD; + flt_ctx->flags |= HLUA_FLT_CTX_FL_PAYLOAD_BIT(idx); ret = hlua_filter_callback(s, filter, "http_payload", dir, (HLUA_FLT_CB_FINAL | HLUA_FLT_CB_ARG_HTTP_MSG)); if (ret != -1) { ret = flt_ctx->cur_len[idx]; @@ -12499,7 +12508,7 @@ static int hlua_filter_http_end(struct stream *s, struct filter *filter, struct { struct hlua_flt_ctx *flt_ctx = filter->ctx; - flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD; + flt_ctx->flags &= ~HLUA_FLT_CTX_FL_PAYLOAD_BIT(CHN_IDX(msg->chn)); return hlua_filter_callback(s, filter, "http_end", (!(msg->chn->flags & CF_ISRESP) ? SMP_OPT_DIR_REQ : SMP_OPT_DIR_RES), (HLUA_FLT_CB_FINAL | HLUA_FLT_CB_RETVAL | HLUA_FLT_CB_ARG_HTTP_MSG)); @@ -12517,7 +12526,7 @@ static int hlua_filter_tcp_payload(struct stream *s, struct filter *filter, str flt_hlua = flt_ctx->hlua[idx]; flt_ctx->cur_off[idx] = offset; flt_ctx->cur_len[idx] = len; - flt_ctx->flags |= HLUA_FLT_CTX_FL_PAYLOAD; + flt_ctx->flags |= HLUA_FLT_CTX_FL_PAYLOAD_BIT(idx); ret = hlua_filter_callback(s, filter, "tcp_payload", dir, (HLUA_FLT_CB_FINAL | HLUA_FLT_CB_ARG_CHN)); if (ret != -1) { ret = flt_ctx->cur_len[idx];