mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-21 20:00:17 +00:00
BUG/MEDIUM: compression/htx: Fix the adding of the last data block
The function htx_add_data_before() is buggy and cannot work. It first add a data block and then move it before another one, passed in argument. The problem happens when a defragmentation is done to add the new block. In this case, the reference is no longer valid, because the blocks are rearranged. So, instead of moving the new block before the reference, it is moved at the head of the HTX message. So this function has been removed. It was only used by the compression filter to add a last data block before a TLR, EOT or EOM block. Now, the new function htx_add_last_data() is used. It adds a last data block, after all others and before any TLR, EOT or EOM block. Then, the next bock is get. It is the first non-data block after data in the HTX message. The compression loop continues with it. This patch must be backported to 1.9.
This commit is contained in:
parent
bda8397fba
commit
86bc8df955
@ -189,7 +189,7 @@ struct htx_blk *htx_add_all_trailers(struct htx *htx, const struct http_hdr *hdr
|
||||
struct htx_blk *htx_add_endof(struct htx *htx, enum htx_blk_type type);
|
||||
struct htx_blk *htx_add_data_atonce(struct htx *htx, const struct ist data);
|
||||
size_t htx_add_data(struct htx *htx, const struct ist data);
|
||||
struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, const struct ist data);
|
||||
struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data);
|
||||
|
||||
int htx_reqline_to_h1(const struct htx_sl *sl, struct buffer *chk);
|
||||
int htx_stline_to_h1(const struct htx_sl *sl, struct buffer *chk);
|
||||
|
@ -256,7 +256,10 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg,
|
||||
if (htx_compression_buffer_end(st, &trash, 1) < 0)
|
||||
goto error;
|
||||
if (b_data(&trash)) {
|
||||
blk = htx_add_data_before(htx, blk, ist2(b_head(&trash), b_data(&trash)));
|
||||
struct htx_blk *last = htx_add_last_data(htx, ist2(b_head(&trash), b_data(&trash)));
|
||||
if (!last)
|
||||
goto error;
|
||||
blk = htx_get_next_blk(htx, last);
|
||||
if (!blk)
|
||||
goto error;
|
||||
to_forward += b_data(&trash);
|
||||
|
37
src/htx.c
37
src/htx.c
@ -868,22 +868,29 @@ size_t htx_add_data(struct htx *htx, const struct ist data)
|
||||
return len;
|
||||
}
|
||||
|
||||
struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref,
|
||||
const struct ist data)
|
||||
{
|
||||
struct htx_blk *blk;
|
||||
int32_t prev;
|
||||
|
||||
/* FIXME: check data.len (< 256MB) */
|
||||
blk = htx_add_blk(htx, HTX_BLK_DATA, data.len);
|
||||
/* Adds an HTX block of type DATA in <htx> just after all other DATA
|
||||
* blocks. Because it relies on htx_add_data_atonce(), It may be happened to a
|
||||
* DATA block if possible. But, if the function succeeds, it will be the last
|
||||
* DATA block in all cases. If an error occurred, NULL is returned. Otherwise,
|
||||
* on success, the updated block (or the new one) is returned.
|
||||
*/
|
||||
struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data)
|
||||
{
|
||||
struct htx_blk *blk, *pblk;
|
||||
|
||||
blk = htx_add_data_atonce(htx, data);
|
||||
if (!blk)
|
||||
return NULL;
|
||||
|
||||
blk->info += data.len;
|
||||
memcpy(htx_get_blk_ptr(htx, blk), data.ptr, data.len);
|
||||
for (pblk = htx_get_prev_blk(htx, blk); pblk; pblk = htx_get_prev_blk(htx, pblk)) {
|
||||
int32_t cur, prev;
|
||||
|
||||
for (prev = htx_get_prev(htx, htx->tail); prev != -1; prev = htx_get_prev(htx, prev)) {
|
||||
struct htx_blk *pblk = htx_get_blk(htx, prev);
|
||||
if (htx_get_blk_type(pblk) <= HTX_BLK_DATA)
|
||||
break;
|
||||
|
||||
cur = htx_get_blk_pos(htx, blk);
|
||||
prev = htx_get_blk_pos(htx, pblk);
|
||||
|
||||
/* Swap .addr and .info fields */
|
||||
blk->addr ^= pblk->addr; pblk->addr ^= blk->addr; blk->addr ^= pblk->addr;
|
||||
@ -891,11 +898,11 @@ struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref,
|
||||
|
||||
if (blk->addr == pblk->addr)
|
||||
blk->addr += htx_get_blksz(pblk);
|
||||
htx->front = prev;
|
||||
|
||||
if (pblk == ref)
|
||||
break;
|
||||
blk = pblk;
|
||||
if (htx->front == cur)
|
||||
htx->front = prev;
|
||||
else if (htx->front == prev)
|
||||
htx->front = cur;
|
||||
}
|
||||
|
||||
if (htx_get_blk_pos(htx, blk) != htx->front)
|
||||
|
Loading…
Reference in New Issue
Block a user