Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cd7f19d

Browse files
committed
Fix potential pointer overflow in xlogreader.c.
While checking if a record could fit in the circular WAL decoding buffer, the coding from commit 3f1ce97 used arithmetic that could overflow. 64 bit systems were unaffected for various technical reasons, which probably explains the lack of problem reports. Likewise for 32 bit systems running known 32 bit kernels. The systems at risk of problems appear to be 32 bit processes running on 64 bit kernels, with unlucky placement in memory. Per complaint from GCC -fsanitize=undefined -m32, while testing variations of 039_end_of_wal.pl. Back-patch to 15. Reviewed-by: Nathan Bossart <nathandbossart@gmail.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKGKH0oRPOX7DhiQ_b51sM8HqcPp2J3WA-Oen%3DdXog%2BAGGQ%40mail.gmail.com
1 parent 2cc2d02 commit cd7f19d

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

src/backend/access/transam/xlogreader.c

+37-9
Original file line numberDiff line numberDiff line change
@@ -457,18 +457,37 @@ XLogReadRecordAlloc(XLogReaderState *state, size_t xl_tot_len, bool allow_oversi
457457
if (state->decode_buffer_tail >= state->decode_buffer_head)
458458
{
459459
/* Empty, or tail is to the right of head. */
460-
if (state->decode_buffer_tail + required_space <=
461-
state->decode_buffer + state->decode_buffer_size)
460+
if (required_space <=
461+
state->decode_buffer_size -
462+
(state->decode_buffer_tail - state->decode_buffer))
462463
{
463-
/* There is space between tail and end. */
464+
/*-
465+
* There is space between tail and end.
466+
*
467+
* +-----+--------------------+-----+
468+
* | |////////////////////|here!|
469+
* +-----+--------------------+-----+
470+
* ^ ^
471+
* | |
472+
* h t
473+
*/
464474
decoded = (DecodedXLogRecord *) state->decode_buffer_tail;
465475
decoded->oversized = false;
466476
return decoded;
467477
}
468-
else if (state->decode_buffer + required_space <
469-
state->decode_buffer_head)
478+
else if (required_space <
479+
state->decode_buffer_head - state->decode_buffer)
470480
{
471-
/* There is space between start and head. */
481+
/*-
482+
* There is space between start and head.
483+
*
484+
* +-----+--------------------+-----+
485+
* |here!|////////////////////| |
486+
* +-----+--------------------+-----+
487+
* ^ ^
488+
* | |
489+
* h t
490+
*/
472491
decoded = (DecodedXLogRecord *) state->decode_buffer;
473492
decoded->oversized = false;
474493
return decoded;
@@ -477,10 +496,19 @@ XLogReadRecordAlloc(XLogReaderState *state, size_t xl_tot_len, bool allow_oversi
477496
else
478497
{
479498
/* Tail is to the left of head. */
480-
if (state->decode_buffer_tail + required_space <
481-
state->decode_buffer_head)
499+
if (required_space <
500+
state->decode_buffer_head - state->decode_buffer_tail)
482501
{
483-
/* There is space between tail and head. */
502+
/*-
503+
* There is space between tail and head.
504+
*
505+
* +-----+--------------------+-----+
506+
* |/////|here! |/////|
507+
* +-----+--------------------+-----+
508+
* ^ ^
509+
* | |
510+
* t h
511+
*/
484512
decoded = (DecodedXLogRecord *) state->decode_buffer_tail;
485513
decoded->oversized = false;
486514
return decoded;

0 commit comments

Comments
 (0)