From a890d072fc11b0c0b6e20b82ff98dcf945d28232 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 2 Apr 2013 12:01:06 +0200 Subject: [PATCH] BUG/MAJOR: http: use a static storage for sample fetch context Baptiste Assmann reported that the cook*() ACLs do not work anymore. The reason is the way we store the hdr_ctx between subsequent calls to smp_fetch_cookie() since commit 3740635b (1.5-dev10). The smp->ctx.a[] storage holds up to 8 pointers. It is not meant for generic storage. We used to store hdr_ctx in the ctx, but while it used to just fit for smp_fetch_hdr(), it does not for smp_fetch_cookie() since we stored it at offset 2. The correct solution is to use this storage to store a pointer to the current hdr_ctx struct which is statically allocated. --- src/proto_http.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index 087cd4703..e7d84ce95 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -220,6 +220,9 @@ const char *stat_status_codes[STAT_STATUS_SIZE] = { */ struct chunk http_err_chunks[HTTP_ERR_SIZE]; +/* this struct is used between calls to smp_fetch_hdr() or smp_fetch_cookie() */ +static struct hdr_ctx static_hdr_ctx; + #define FD_SETS_ARE_BITFIELDS #ifdef FD_SETS_ARE_BITFIELDS /* @@ -8660,12 +8663,19 @@ smp_fetch_hdr(struct proxy *px, struct session *l4, void *l7, unsigned int opt, { struct http_txn *txn = l7; struct hdr_idx *idx = &txn->hdr_idx; - struct hdr_ctx *ctx = (struct hdr_ctx *)smp->ctx.a; + struct hdr_ctx *ctx = smp->ctx.a[0]; const struct http_msg *msg = ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ) ? &txn->req : &txn->rsp; int occ = 0; const char *name_str = NULL; int name_len = 0; + if (!ctx) { + /* first call */ + ctx = &static_hdr_ctx; + ctx->idx = 0; + smp->ctx.a[2] = ctx; + } + if (args) { if (args[0].type != ARGT_STR) return 0; @@ -9116,7 +9126,7 @@ extract_cookie_value(char *hdr, const char *hdr_end, /* Iterate over all cookies present in a message. The context is stored in * smp->ctx.a[0] for the in-header position, smp->ctx.a[1] for the - * end-of-header-value, and smp->ctx.a[2] for the hdr_idx. Depending on + * end-of-header-value, and smp->ctx.a[2] for the hdr_ctx. Depending on * the direction, multiple cookies may be parsed on the same line or not. * The cookie name is in args and the name length in args->data.str.len. * Accepts exactly 1 argument of type string. If the input options indicate @@ -9128,7 +9138,7 @@ smp_fetch_cookie(struct proxy *px, struct session *l4, void *l7, unsigned int op { struct http_txn *txn = l7; struct hdr_idx *idx = &txn->hdr_idx; - struct hdr_ctx *ctx = (struct hdr_ctx *)&smp->ctx.a[2]; + struct hdr_ctx *ctx = smp->ctx.a[2]; const struct http_msg *msg; const char *hdr_name; int hdr_name_len; @@ -9139,6 +9149,13 @@ smp_fetch_cookie(struct proxy *px, struct session *l4, void *l7, unsigned int op if (!args || args->type != ARGT_STR) return 0; + if (!ctx) { + /* first call */ + ctx = &static_hdr_ctx; + ctx->idx = 0; + smp->ctx.a[2] = ctx; + } + CHECK_HTTP_MESSAGE_FIRST(); if ((opt & SMP_OPT_DIR) == SMP_OPT_DIR_REQ) {