Skip to content

Commit b150ae4

Browse files
committed
BUG/MAJOR: mux-h1: Properly handle wrapping on obuf when dumping the first-line
The formatting of the first-line, for a request or a response, does not properly handle the wrapping of the output buffer. This may lead to a data corruption for the current response or eventually for the previous one. Utility functions used to format the first-line of the request or the response rely on the chunk API. So it is not expected to pass a buffer that wraps. Unfortunatly, because of a change performed during the 2.9 dev cycle, the output buffer was direclty used instead of a non-wrapping buffer created from it with b_make() function. It is not an issue for the request because its start-line is always the first block formatted in the output buffer. But for the response, the output may be not empty and may wrap. In that case, the response start-line is dumped at a random position in the buffer, corrupting data. AFAIK, it is only an issue if the HTTP request pipelining is used. To fix the issue, we now take care to create a non-wapping buffer from the output buffer. This patch should fix issues #2779 and #2996. It must be backported as far as 2.9.
1 parent c5d0342 commit b150ae4

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

src/h1_htx.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,7 @@ int h1_parse_msg_tlrs(struct h1m *h1m, struct htx *dsthtx,
951951

952952
/* Appends the H1 representation of the request line <sl> to the chunk <chk>. It
953953
* returns 1 if data are successfully appended, otherwise it returns 0.
954+
* <chk> buffer must not wrap.
954955
*/
955956
int h1_format_htx_reqline(const struct htx_sl *sl, struct buffer *chk)
956957
{
@@ -985,6 +986,7 @@ int h1_format_htx_reqline(const struct htx_sl *sl, struct buffer *chk)
985986

986987
/* Appends the H1 representation of the status line <sl> to the chunk <chk>. It
987988
* returns 1 if data are successfully appended, otherwise it returns 0.
989+
* <chk> buffer must not wrap.
988990
*/
989991
int h1_format_htx_stline(const struct htx_sl *sl, struct buffer *chk)
990992
{
@@ -1018,6 +1020,7 @@ int h1_format_htx_stline(const struct htx_sl *sl, struct buffer *chk)
10181020
/* Appends the H1 representation of the header <n> with the value <v> to the
10191021
* chunk <chk>. It returns 1 if data are successfully appended, otherwise it
10201022
* returns 0.
1023+
* <chk> buffer must not wrap.
10211024
*/
10221025
int h1_format_htx_hdr(const struct ist n, const struct ist v, struct buffer *chk)
10231026
{
@@ -1042,6 +1045,7 @@ int h1_format_htx_hdr(const struct ist n, const struct ist v, struct buffer *chk
10421045
/* Appends the H1 representation of the data <data> to the chunk <chk>. If
10431046
* <chunked> is non-zero, it emits HTTP/1 chunk-encoded data. It returns 1 if
10441047
* data are successfully appended, otherwise it returns 0.
1048+
* <chk> buffer must not wrap.
10451049
*/
10461050
int h1_format_htx_data(const struct ist data, struct buffer *chk, int chunked)
10471051
{

src/mux_h1.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,7 @@ static size_t h1_make_reqline(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
23412341
{
23422342
struct h1c *h1c = h1s->h1c;
23432343
struct htx_blk *blk;
2344+
struct buffer outbuf;
23442345
struct htx_sl *sl;
23452346
enum htx_blk_type type;
23462347
uint32_t sz;
@@ -2365,11 +2366,14 @@ static size_t h1_make_reqline(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
23652366

23662367
if (b_space_wraps(&h1c->obuf))
23672368
b_slow_realign(&h1c->obuf, trash.area, b_data(&h1c->obuf));
2369+
outbuf = b_make(b_tail(&h1c->obuf), b_contig_space(&h1c->obuf), 0, 0);
23682370

23692371
sl = htx_get_blk_ptr(htx, blk);
2370-
if (!h1_format_htx_reqline(sl, &h1c->obuf))
2372+
if (!h1_format_htx_reqline(sl, &outbuf))
23712373
goto full;
23722374

2375+
b_add(&h1c->obuf, outbuf.data);
2376+
23732377
h1s->meth = sl->info.req.meth;
23742378
h1_parse_req_vsn(h1m, sl);
23752379

@@ -2424,6 +2428,7 @@ static size_t h1_make_stline(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
24242428
{
24252429
struct h1c *h1c = h1s->h1c;
24262430
struct htx_blk *blk;
2431+
struct buffer outbuf;
24272432
struct htx_sl *sl;
24282433
enum htx_blk_type type;
24292434
uint32_t sz;
@@ -2450,11 +2455,14 @@ static size_t h1_make_stline(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
24502455

24512456
if (b_space_wraps(&h1c->obuf))
24522457
b_slow_realign(&h1c->obuf, trash.area, b_data(&h1c->obuf));
2458+
outbuf = b_make(b_tail(&h1c->obuf), b_contig_space(&h1c->obuf), 0, 0);
24532459

24542460
sl = htx_get_blk_ptr(htx, blk);
2455-
if (!h1_format_htx_stline(sl, &h1c->obuf))
2461+
if (!h1_format_htx_stline(sl, &outbuf))
24562462
goto full;
24572463

2464+
b_add(&h1c->obuf, outbuf.data);
2465+
24582466
h1s->status = sl->info.res.status;
24592467
h1_parse_res_vsn(h1m, sl);
24602468

0 commit comments

Comments
 (0)