From 9e17087aebe0130fc34aaab4e1981e60707e4a82 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Tue, 3 Feb 2026 07:46:22 +0100 Subject: [PATCH] BUG/MEDIUM: shctx: Use the next block when data exactly filled a block When the hot list was removed in 3.0, a regression was introduced. Theorically, it is possible to override data in a block when new data are appended. It happens when data are copied. If the data size is a multiple of the block size, all data are copied and the last used block is full. But instead of saving a reference on the next block as the restart point for the next copies, we keep a reference on the last full one. On the next read, we reuse this block and old data are crushed. To hit the bug, no new blocks should be reserved between the two data copy attempts. Concretely, for now, it seems not possible to hit the bug. But with a block size set to 1024, if more than 1024 bytes are reseved, with a first copy of 1024 bytes and a second one with remaining data, data in the first block will be crushed. So to fix the bug, the reference of the last block used to write data (which is in fact the next one to use to perform the next copy) is only updated when a block is full. In that case the next block is used. This patch should be backported as far as 3.0 after a period of observation. --- src/shctx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/shctx.c b/src/shctx.c index 931bc4f5f..fb1611396 100644 --- a/src/shctx.c +++ b/src/shctx.c @@ -206,9 +206,12 @@ int shctx_row_data_append(struct shared_context *shctx, struct shared_block *fir data += remain; len -= remain; first->len += remain; /* update len in the head of the row */ - first->last_append = block; block = LIST_ELEM(block->list.n, struct shared_block*, list); + + /* Update block only if the previous one is full */ + if (start + remain == shctx->block_size) + first->last_append = block; } while (block != first); return len;