From 06170c50ae5cd0fb23510b832826f7e63a5a8894 Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Mon, 16 Mar 2015 23:23:53 +0100 Subject: [PATCH 7/9] BUG/MEDIUM: http: the function "(req|res)-replace-value" doesn't respect the HTTP syntax These function used an invalid header parser. - The trailing white-spaces were embedded in the replacement regex, - The double-quote (") containing comma (,) were not respected. This patch replace this parser by the "official" parser http_find_header2(). (cherry picked from commit 191f9efdc58f21af1d9dde3db5ba198d7f1ce22e) --- src/proto_http.c | 126 +++++++++++++++---------------------------------------- 1 file changed, 34 insertions(+), 92 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index f53b5e2..c49c4f4 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3179,113 +3179,55 @@ static inline void inet_set_tos(int fd, struct sockaddr_storage from, int tos) #endif } -/* Returns the number of characters written to destination, - * -1 on internal error and -2 if no replacement took place. - */ -static int http_replace_header(struct my_regex *re, char *dst, uint dst_size, char *val, int len, - const char *rep_str) -{ - if (!regex_exec_match2(re, val, len, MAX_MATCH, pmatch)) - return -2; - - return exp_replace(dst, dst_size, val, rep_str, pmatch); -} - -/* Returns the number of characters written to destination, - * -1 on internal error and -2 if no replacement took place. - */ -static int http_replace_value(struct my_regex *re, char *dst, uint dst_size, char *val, int len, char delim, - const char *rep_str) -{ - char* p = val; - char* dst_end = dst + dst_size; - char* dst_p = dst; - - for (;;) { - char *p_delim; - - /* look for delim. */ - p_delim = p; - while (p_delim < val + len && *p_delim != delim) - p_delim++; - - if (regex_exec_match2(re, p, p_delim-p, MAX_MATCH, pmatch)) { - int replace_n = exp_replace(dst_p, dst_end - dst_p, p, rep_str, pmatch); - - if (replace_n < 0) - return -1; - - dst_p += replace_n; - } else { - uint len = p_delim - p; - - if (dst_p + len >= dst_end) - return -1; - - memcpy(dst_p, p, len); - dst_p += len; - } - - if (dst_p >= dst_end) - return -1; - - /* end of the replacements. */ - if (p_delim >= val + len) - break; - - /* Next part. */ - *dst_p++ = delim; - p = p_delim + 1; - } - - return dst_p - dst; -} - static int http_transform_header(struct session* s, struct http_msg *msg, const char* name, uint name_len, char* buf, struct hdr_idx* idx, struct list *fmt, struct my_regex *re, struct hdr_ctx* ctx, int action) { + int (*http_find_hdr_func)(const char *name, int len, char *sol, + struct hdr_idx *idx, struct hdr_ctx *ctx); + struct chunk *replace = get_trash_chunk(); + struct chunk *output = get_trash_chunk(); + + replace->len = build_logline(s, replace->str, replace->size, fmt); + if (replace->len >= replace->size - 1) + return -1; + ctx->idx = 0; - while (http_find_full_header2(name, name_len, buf, idx, ctx)) { + /* Choose the header browsing function. */ + switch (action) { + case HTTP_REQ_ACT_REPLACE_VAL: + case HTTP_RES_ACT_REPLACE_VAL: + http_find_hdr_func = http_find_header2; + break; + case HTTP_REQ_ACT_REPLACE_HDR: + case HTTP_RES_ACT_REPLACE_HDR: + http_find_hdr_func = http_find_full_header2; + break; + default: /* impossible */ + return -1; + } + + while (http_find_hdr_func(name, name_len, buf, idx, ctx)) { struct hdr_idx_elem *hdr = idx->v + ctx->idx; int delta; - char* val = (char*)ctx->line + ctx->val; - char* val_end = (char*)ctx->line + hdr->len; - char* reg_dst_buf; - uint reg_dst_buf_size; - int n_replaced; - - trash.len = build_logline(s, trash.str, trash.size, fmt); - - if (trash.len >= trash.size - 1) - return -1; + char *val = ctx->line + ctx->val; + char* val_end = val + ctx->vlen; - reg_dst_buf = trash.str + trash.len + 1; - reg_dst_buf_size = trash.size - trash.len - 1; + if (!regex_exec_match2(re, val, val_end-val, MAX_MATCH, pmatch)) + continue; - switch (action) { - case HTTP_REQ_ACT_REPLACE_VAL: - case HTTP_RES_ACT_REPLACE_VAL: - n_replaced = http_replace_value(re, reg_dst_buf, reg_dst_buf_size, val, val_end-val, ',', trash.str); - break; - case HTTP_REQ_ACT_REPLACE_HDR: - case HTTP_RES_ACT_REPLACE_HDR: - n_replaced = http_replace_header(re, reg_dst_buf, reg_dst_buf_size, val, val_end-val, trash.str); - break; - default: /* impossible */ + output->len = exp_replace(output->str, output->size, val, replace->str, pmatch); + if (output->len == -1) return -1; - } - switch (n_replaced) { - case -1: return -1; - case -2: continue; - } - - delta = buffer_replace2(msg->chn->buf, val, val_end, reg_dst_buf, n_replaced); + delta = buffer_replace2(msg->chn->buf, val, val_end, output->str, output->len); hdr->len += delta; http_msg_move_end(msg, delta); + + /* Adjust the length of the current value of the index. */ + ctx->vlen += delta; } return 0; -- 2.0.5