mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-24 20:31:00 +01:00
[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.
This commit is contained in:
parent
631f01c2f1
commit
588bd4f813
@ -340,15 +340,18 @@ struct http_txn {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* This structure is used by http_find_header() to return values of headers.
|
/* This structure is used by http_find_header() to return values of headers.
|
||||||
* The header starts at <line>, the value at <line>+<val> for <vlen> bytes, and
|
* The header starts at <line>, the value (excluding leading and trailing white
|
||||||
* sets <line>+<del> to point to the last delimitor (colon or comma) before
|
* spaces) at <line>+<val> for <vlen> bytes, followed by optional <tws> trailing
|
||||||
* this value. <prev> points to the index of the header whose next is this one.
|
* white spaces, and sets <line>+<del> to point to the last delimitor (colon or
|
||||||
|
* comma) before this value. <prev> points to the index of the header whose next
|
||||||
|
* is this one.
|
||||||
*/
|
*/
|
||||||
struct hdr_ctx {
|
struct hdr_ctx {
|
||||||
char *line;
|
char *line;
|
||||||
int idx;
|
int idx;
|
||||||
int val; /* relative to line */
|
int val; /* relative to line, may skip some leading white spaces */
|
||||||
int vlen; /* relative to line+val */
|
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 del; /* relative to line */
|
||||||
int prev; /* index of previous header */
|
int prev; /* index of previous header */
|
||||||
};
|
};
|
||||||
|
|||||||
@ -503,7 +503,7 @@ int http_find_header2(const char *name, int len,
|
|||||||
* another one on the same line.
|
* another one on the same line.
|
||||||
*/
|
*/
|
||||||
sol = ctx->line;
|
sol = ctx->line;
|
||||||
ctx->del = ctx->val + ctx->vlen;
|
ctx->del = ctx->val + ctx->vlen + ctx->tws;
|
||||||
sov = sol + ctx->del;
|
sov = sol + ctx->del;
|
||||||
eol = sol + idx->v[cur_idx].len;
|
eol = sol + idx->v[cur_idx].len;
|
||||||
|
|
||||||
@ -551,6 +551,11 @@ int http_find_header2(const char *name, int len,
|
|||||||
ctx->val = sov - sol;
|
ctx->val = sov - sol;
|
||||||
|
|
||||||
eol = find_hdr_value_end(sov, eol);
|
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;
|
ctx->vlen = eol - sov;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -589,7 +594,7 @@ int http_remove_header2(struct http_msg *msg, struct buffer *buf,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hdr = &idx->v[cur_idx];
|
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. */
|
/* 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);
|
delta = buffer_replace2(buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
|
||||||
http_msg_move_end(msg, delta);
|
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->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->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->val = idx->v[ctx->idx].len; /* point to end of previous header */
|
||||||
ctx->vlen = 0;
|
ctx->tws = ctx->vlen = 0;
|
||||||
return ctx->idx;
|
return ctx->idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This was not the only value of this header. We have to remove between
|
/* 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
|
* ctx->del+1 and ctx->val+ctx->vlen+ctx->tws+1 included. If it is the
|
||||||
* of the list, we remove the last separator.
|
* 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,
|
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);
|
NULL, 0);
|
||||||
hdr->len += delta;
|
hdr->len += delta;
|
||||||
http_msg_move_end(msg, delta);
|
http_msg_move_end(msg, delta);
|
||||||
ctx->val = ctx->del;
|
ctx->val = ctx->del;
|
||||||
ctx->vlen = 0;
|
ctx->tws = ctx->vlen = 0;
|
||||||
return ctx->idx;
|
return ctx->idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user