From 9589510f4e284ef4ee9f0a95fac572aced43cbe7 Mon Sep 17 00:00:00 2001 From: Richard Guo Date: Sat, 14 Feb 2026 18:16:27 +0900 Subject: [PATCH v2] Fix signed integer overflow in nodeWindowAgg.c --- src/backend/executor/nodeWindowAgg.c | 54 +++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index d9b64b0f465..dab057df0bd 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -37,6 +37,7 @@ #include "catalog/objectaccess.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_proc.h" +#include "common/int.h" #include "executor/executor.h" #include "executor/nodeWindowAgg.h" #include "miscadmin.h" @@ -1532,12 +1533,17 @@ row_is_in_frame(WindowObject winobj, int64 pos, TupleTableSlot *slot, if (frameOptions & FRAMEOPTION_ROWS) { int64 offset = DatumGetInt64(winstate->endOffsetValue); + int64 target_pos; /* rows after current row + offset are out of frame */ if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) offset = -offset; - if (pos > winstate->currentpos + offset) + if (pg_add_s64_overflow(winstate->currentpos, offset, &target_pos)) + { + /* overflow: frame extends to end of partition */ + } + else if (pos > target_pos) return -1; } else if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS)) @@ -1672,7 +1678,16 @@ update_frameheadpos(WindowAggState *winstate) if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) offset = -offset; - winstate->frameheadpos = winstate->currentpos + offset; + /* + * If we have an overflow, it means the frame head is beyond the + * range of int64. Since currentpos >= 0, this can only be a + * positive overflow. We treat this as being beyond end of + * partition. + */ + if (pg_add_s64_overflow(winstate->currentpos, offset, + &winstate->frameheadpos)) + winstate->frameheadpos = PG_INT64_MAX; + /* frame head can't go before first row */ if (winstate->frameheadpos < 0) winstate->frameheadpos = 0; @@ -1789,7 +1804,16 @@ update_frameheadpos(WindowAggState *winstate) if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING) minheadgroup = winstate->currentgroup - offset; else - minheadgroup = winstate->currentgroup + offset; + { + /* + * If we have an overflow, it means the target group is beyond + * the range of int64. We treat this as "infinity", which + * ensures the loop below advances to end of partition. + */ + if (pg_add_s64_overflow(winstate->currentgroup, offset, + &minheadgroup)) + minheadgroup = PG_INT64_MAX; + } tuplestore_select_read_pointer(winstate->buffer, winstate->framehead_ptr); @@ -1926,7 +1950,18 @@ update_frametailpos(WindowAggState *winstate) if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) offset = -offset; - winstate->frametailpos = winstate->currentpos + offset + 1; + /* + * If we have an overflow, it means the frame tail is beyond the + * range of int64. Since currentpos >= 0, this can only be a + * positive overflow. We treat this as being beyond end of + * partition. + */ + if (pg_add_s64_overflow(winstate->currentpos, offset, + &winstate->frametailpos) || + pg_add_s64_overflow(winstate->frametailpos, 1, + &winstate->frametailpos)) + winstate->frametailpos = PG_INT64_MAX; + /* smallest allowable value of frametailpos is 0 */ if (winstate->frametailpos < 0) winstate->frametailpos = 0; @@ -2043,7 +2078,16 @@ update_frametailpos(WindowAggState *winstate) if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING) maxtailgroup = winstate->currentgroup - offset; else - maxtailgroup = winstate->currentgroup + offset; + { + /* + * If we have an overflow, it means the target group is beyond + * the range of int64. We treat this as "infinity", which + * ensures the loop below advances to end of partition. + */ + if (pg_add_s64_overflow(winstate->currentgroup, offset, + &maxtailgroup)) + maxtailgroup = PG_INT64_MAX; + } tuplestore_select_read_pointer(winstate->buffer, winstate->frametail_ptr); -- 2.39.5 (Apple Git-154)