From: Willy Tarreau Date: Thu, 1 Sep 2011 20:22:28 +0000 (+0200) Subject: [BUG] http: trailing white spaces must also be trimmed after headers X-Git-Tag: v1.5-dev8~138 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=588bd4f8136ea4fdef9d7f0bc8c256ceab8f9d66;p=thirdparty%2Fhaproxy.git [BUG] http: trailing white spaces must also be trimmed after headers Trailing spaces after headers were not trimmed, only the leading ones were. An issue was detected today with a content-length value which was padded with spaces and which was rejected. Recent updates to the http-bis draft made it a lot more clear that such spaces must be ignored, so this is what this patch does. It should be backported to 1.4. --- diff --git a/include/types/proto_http.h b/include/types/proto_http.h index 3f6724b4a1..d9bf830964 100644 --- a/include/types/proto_http.h +++ b/include/types/proto_http.h @@ -340,15 +340,18 @@ struct http_txn { }; /* This structure is used by http_find_header() to return values of headers. - * The header starts at , the value at + for bytes, and - * sets + to point to the last delimitor (colon or comma) before - * this value. points to the index of the header whose next is this one. + * The header starts at , the value (excluding leading and trailing white + * spaces) at + for bytes, followed by optional trailing + * white spaces, and sets + to point to the last delimitor (colon or + * comma) before this value. points to the index of the header whose next + * is this one. */ struct hdr_ctx { char *line; int idx; - int val; /* relative to line */ - int vlen; /* relative to line+val */ + int val; /* relative to line, may skip some leading white spaces */ + int vlen; /* relative to line+val, stops before trailing white spaces */ + int tws; /* added to vlen if some trailing white spaces are present */ int del; /* relative to line */ int prev; /* index of previous header */ }; diff --git a/src/proto_http.c b/src/proto_http.c index 35c2f9db01..a56be3885e 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -503,7 +503,7 @@ int http_find_header2(const char *name, int len, * another one on the same line. */ sol = ctx->line; - ctx->del = ctx->val + ctx->vlen; + ctx->del = ctx->val + ctx->vlen + ctx->tws; sov = sol + ctx->del; eol = sol + idx->v[cur_idx].len; @@ -551,6 +551,11 @@ int http_find_header2(const char *name, int len, ctx->val = sov - sol; eol = find_hdr_value_end(sov, eol); + ctx->tws = 0; + while (http_is_lws[(unsigned char)*(eol - 1)]) { + eol--; + ctx->tws++; + } ctx->vlen = eol - sov; return 1; } @@ -589,7 +594,7 @@ int http_remove_header2(struct http_msg *msg, struct buffer *buf, return 0; hdr = &idx->v[cur_idx]; - if (sol[ctx->del] == ':' && ctx->val + ctx->vlen == hdr->len) { + if (sol[ctx->del] == ':' && ctx->val + ctx->vlen + ctx->tws == hdr->len) { /* This was the only value of the header, we must now remove it entirely. */ delta = buffer_replace2(buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0); http_msg_move_end(msg, delta); @@ -601,23 +606,23 @@ int http_remove_header2(struct http_msg *msg, struct buffer *buf, ctx->idx = ctx->prev; /* walk back to the end of previous header */ ctx->line -= idx->v[ctx->idx].len + idx->v[cur_idx].cr + 1; ctx->val = idx->v[ctx->idx].len; /* point to end of previous header */ - ctx->vlen = 0; + ctx->tws = ctx->vlen = 0; return ctx->idx; } /* This was not the only value of this header. We have to remove between - * ctx->del+1 and ctx->val+ctx->vlen+1 included. If it is the last entry - * of the list, we remove the last separator. + * ctx->del+1 and ctx->val+ctx->vlen+ctx->tws+1 included. If it is the + * last entry of the list, we remove the last separator. */ - skip_comma = (ctx->val + ctx->vlen == hdr->len) ? 0 : 1; + skip_comma = (ctx->val + ctx->vlen + ctx->tws == hdr->len) ? 0 : 1; delta = buffer_replace2(buf, sol + ctx->del + skip_comma, - sol + ctx->val + ctx->vlen + skip_comma, + sol + ctx->val + ctx->vlen + ctx->tws + skip_comma, NULL, 0); hdr->len += delta; http_msg_move_end(msg, delta); ctx->val = ctx->del; - ctx->vlen = 0; + ctx->tws = ctx->vlen = 0; return ctx->idx; }