public inbox for [email protected]
help / color / mirror / Atom feedFrom: Richard Guo <[email protected]>
To: Alexander Lakhin <[email protected]>
Cc: [email protected]
Subject: Re: BUG #19405: Assertion in eval_windowaggregates() fails due to integer overflow
Date: Sat, 14 Feb 2026 22:44:48 +0900
Message-ID: <CAMbWs4-i9Hk8+fyxoT88ixbrBYuT+2=d9nLqFLi8jfS3k_z68w@mail.gmail.com> (raw)
In-Reply-To: <CAMbWs4_jYG-vjN579aLuE7pf9PaZaPL9KCjPRN0kn3T+obE7hw@mail.gmail.com>
References: <[email protected]>
<CAMbWs4_GnG0NYnsBZJpHG-BLo28euD6VUx0WhFd4Ur6RaLr5WQ@mail.gmail.com>
<[email protected]>
<CAMbWs4_jYG-vjN579aLuE7pf9PaZaPL9KCjPRN0kn3T+obE7hw@mail.gmail.com>
On Sat, Feb 14, 2026 at 8:00 PM Richard Guo <[email protected]> wrote:
> Right, I noticed this one too. Basically, nodeWindowAgg.c doesn't
> check for overflow when adding startOffsetValue or endOffsetValue.
> Since these values are provided by the user and can be arbitrarily
> large, simple addition does not seem safe. I think we may need to
> switch to overflow-aware integer operations in all relevant code.
Here is an updated patch to fix all relevant code in nodeWindowAgg.c.
- Richard
Attachments:
[application/octet-stream] v2-0001-Fix-signed-integer-overflow-in-nodeWindowAgg.c.patch (4.3K, 2-v2-0001-Fix-signed-integer-overflow-in-nodeWindowAgg.c.patch)
download | inline diff:
From 9589510f4e284ef4ee9f0a95fac572aced43cbe7 Mon Sep 17 00:00:00 2001
From: Richard Guo <[email protected]>
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)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected]
Subject: Re: BUG #19405: Assertion in eval_windowaggregates() fails due to integer overflow
In-Reply-To: <CAMbWs4-i9Hk8+fyxoT88ixbrBYuT+2=d9nLqFLi8jfS3k_z68w@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox