mirror of
https://github.com/haproxy/haproxy.git
synced 2026-07-15 03:56:56 -04:00
BUG/MINOR: shctx: fix shctx_row_data_get() when offset exceeds a block
The loop advanced the block pointer only after the copy, but skipped blocks preceding <offset> with a continue, which bypassed that advance. As a result any read starting past the first block copied nothing. This notably affects conditional requests: should_send_notmodified_response() reads the stored ETag at entry->etag_offset, so a cached response whose ETag header sits beyond the first block fails revalidation and is served in full (200) instead of 304. Rewrite the loop as a for() so the block pointer always advances, regardless of whether the current block is copied or skipped. This should be backported as far as 2.6.
This commit is contained in:
parent
f34517a1aa
commit
6750c36adf
1 changed files with 8 additions and 18 deletions
26
src/shctx.c
26
src/shctx.c
|
|
@ -226,30 +226,22 @@ int shctx_row_data_append(struct shared_context *shctx, struct shared_block *fir
|
|||
int shctx_row_data_get(struct shared_context *shctx, struct shared_block *first,
|
||||
unsigned char *dst, int offset, int len)
|
||||
{
|
||||
int count = 0, size = 0, start = -1;
|
||||
int count, size, start = -1;
|
||||
struct shared_block *block;
|
||||
|
||||
/* can't copy more */
|
||||
if (len > first->len)
|
||||
len = first->len;
|
||||
|
||||
block = first;
|
||||
count = 0;
|
||||
/* Pass through the blocks to copy them */
|
||||
do {
|
||||
if (count >= first->block_count || len <= 0)
|
||||
break;
|
||||
|
||||
count++;
|
||||
/* continue until we are in right block
|
||||
corresponding to the offset */
|
||||
if (count < offset / shctx->block_size + 1)
|
||||
/* Walk the blocks, skipping those that precede the one holding <offset>. */
|
||||
for (block = first, count = 0; count < first->block_count && len > 0;
|
||||
block = LIST_ELEM(block->list.n, struct shared_block *, list), count++) {
|
||||
if (count < offset / shctx->block_size)
|
||||
continue;
|
||||
|
||||
/* on the first block, data won't possibly began at offset 0 */
|
||||
/* the first copied block may not start at its beginning */
|
||||
if (start == -1)
|
||||
start = offset - (count - 1) * shctx->block_size;
|
||||
|
||||
start = offset - count * shctx->block_size;
|
||||
BUG_ON(start < 0);
|
||||
|
||||
/* size can be lower than a block when copying the last block */
|
||||
|
|
@ -260,9 +252,7 @@ int shctx_row_data_get(struct shared_context *shctx, struct shared_block *first,
|
|||
dst += size;
|
||||
len -= size;
|
||||
start = 0;
|
||||
|
||||
block = LIST_ELEM(block->list.n, struct shared_block*, list);
|
||||
} while (block != first);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue