From ebf5296026b6f07fb30821ee0603fff24817001b Mon Sep 17 00:00:00 2001 From: Matheus Alcantara Date: Tue, 9 Jun 2026 17:59:20 -0300 Subject: [PATCH v2] Fix out-of-bounds access in autoprewarm worker The read stream callback apw_read_stream_next_block() advances p->pos through the block_info array. When processing the last block, it increments p->pos to prewarm_stop_idx before returning. The callback itself is safe because it checks bounds before accessing the array. However, the caller assigned blk from block_info[i] at the end of the loop body, before the loop condition was re-evaluated. When i equaled prewarm_stop_idx, this accessed memory beyond the allocated DSM segment, causing a segfault. Restructure the loop to check bounds at the top and assign blk at the beginning of the loop body, where it is always safe. This avoids the need for an explicit bounds check at the end. Author: Matheus Alcantara Reported-by: Glauber Batista Discussion: https://www.postgresql.org/message-id/CAO%2B_mTQgQyTYwDh%3DU8iTnsDmOGyWsZJjUV31SmEYwmw6_xY6Bw%40mail.gmail.com --- contrib/pg_prewarm/autoprewarm.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index ba0bc8e6d4a..f3569b12d11 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -572,16 +572,23 @@ autoprewarm_database_main(Datum main_arg) * valid forks or run out of options, we'll close the relation and * move on. */ - while (i < apw_state->prewarm_stop_idx && - blk.tablespace == tablespace && - blk.filenumber == filenumber) + while (i < apw_state->prewarm_stop_idx) { - ForkNumber forknum = blk.forknum; + ForkNumber forknum; BlockNumber nblocks; struct AutoPrewarmReadStreamData p; ReadStream *stream; Buffer buf; + blk = block_info[i]; + + /* Stop when we reach a different relation. */ + if (blk.tablespace != tablespace || + blk.filenumber != filenumber) + break; + + forknum = blk.forknum; + /* * smgrexists is not safe for illegal forknum, hence check whether * the passed forknum is valid before using it in smgrexists. @@ -645,7 +652,6 @@ autoprewarm_database_main(Datum main_arg) /* Advance i past all the blocks just prewarmed. */ i = p.pos; - blk = block_info[i]; } relation_close(rel, AccessShareLock); -- 2.50.1 (Apple Git-155)