mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
MEDIUM: h2: don't use trash to decode headers!
The trash is already used by the hpack layer and for Huffman decoding, it's unsafe to use here as a buffer and results in corrupted data. Use a safely allocated trash instead.
This commit is contained in:
parent
13278b44b1
commit
68dd9856ce
29
src/mux_h2.c
29
src/mux_h2.c
@ -1768,6 +1768,7 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
|
|||||||
{
|
{
|
||||||
struct h2c *h2c = h2s->h2c;
|
struct h2c *h2c = h2s->h2c;
|
||||||
const uint8_t *hdrs = (uint8_t *)h2c->dbuf->p;
|
const uint8_t *hdrs = (uint8_t *)h2c->dbuf->p;
|
||||||
|
struct chunk *copy = NULL;
|
||||||
int flen = h2c->dfl;
|
int flen = h2c->dfl;
|
||||||
int outlen = 0;
|
int outlen = 0;
|
||||||
int wrap;
|
int wrap;
|
||||||
@ -1781,11 +1782,14 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
|
|||||||
/* if the input buffer wraps, take a temporary copy of it (rare) */
|
/* if the input buffer wraps, take a temporary copy of it (rare) */
|
||||||
wrap = h2c->dbuf->data + h2c->dbuf->size - h2c->dbuf->p;
|
wrap = h2c->dbuf->data + h2c->dbuf->size - h2c->dbuf->p;
|
||||||
if (wrap < h2c->dfl) {
|
if (wrap < h2c->dfl) {
|
||||||
char *copy = get_trash_chunk()->str;
|
copy = alloc_trash_chunk();
|
||||||
|
if (!copy) {
|
||||||
memcpy(copy, h2c->dbuf->p, wrap);
|
h2c_error(h2c, H2_ERR_INTERNAL_ERROR);
|
||||||
memcpy(copy + wrap, h2c->dbuf->data, h2c->dfl - wrap);
|
goto fail;
|
||||||
hdrs = (uint8_t *)copy;
|
}
|
||||||
|
memcpy(copy->str, h2c->dbuf->p, wrap);
|
||||||
|
memcpy(copy->str + wrap, h2c->dbuf->data, h2c->dfl - wrap);
|
||||||
|
hdrs = (uint8_t *)copy->str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The padlen is the first byte before data, and the padding appears
|
/* The padlen is the first byte before data, and the padding appears
|
||||||
@ -1814,7 +1818,7 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
|
|||||||
*/
|
*/
|
||||||
if (!(h2c->dff & H2_F_HEADERS_END_HEADERS)) {
|
if (!(h2c->dff & H2_F_HEADERS_END_HEADERS)) {
|
||||||
h2c_error(h2c, H2_ERR_INTERNAL_ERROR);
|
h2c_error(h2c, H2_ERR_INTERNAL_ERROR);
|
||||||
return 0;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -1825,7 +1829,7 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
|
|||||||
if (try <= 0) {
|
if (try <= 0) {
|
||||||
try = buf->p - (buf->data + buf->o);
|
try = buf->p - (buf->data + buf->o);
|
||||||
if (try <= 0)
|
if (try <= 0)
|
||||||
return 0;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (try > count)
|
if (try > count)
|
||||||
try = count;
|
try = count;
|
||||||
@ -1842,17 +1846,17 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
|
|||||||
/* need to let the output buffer flush and
|
/* need to let the output buffer flush and
|
||||||
* mark the buffer for later wake up.
|
* mark the buffer for later wake up.
|
||||||
*/
|
*/
|
||||||
return 0;
|
goto fail;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* no other way around */
|
/* no other way around */
|
||||||
h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
|
h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
|
||||||
return 0;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (outlen < 0) {
|
else if (outlen < 0) {
|
||||||
h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
|
h2c_error(h2c, H2_ERR_COMPRESSION_ERROR);
|
||||||
return 0;
|
goto fail;
|
||||||
}
|
}
|
||||||
} while (outlen < 0);
|
} while (outlen < 0);
|
||||||
|
|
||||||
@ -1870,7 +1874,12 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count)
|
|||||||
h2s->flags |= H2_SF_ES_RCVD;
|
h2s->flags |= H2_SF_ES_RCVD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free_trash_chunk(copy);
|
||||||
return outlen;
|
return outlen;
|
||||||
|
fail:
|
||||||
|
outlen = 0;
|
||||||
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user