From e091861e2bded0263bcdfd447070d4adcaab1f74 Mon Sep 17 00:00:00 2001 From: David Christensen Date: Thu, 16 Apr 2026 13:51:13 -0400 Subject: [PATCH] Critical: check for Size overflow when using palloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multiple locations compute allocation sizes via unchecked integer multiplication: Line 1027: palloc(sizeof(agtype_value) * (*pstate)->size) — size doubles repeatedly (lines 1122, 1169); near 0x40000000, multiplication overflows to a small value, leading to heap buffer overflow on subsequent writes. Line 1038: palloc(sizeof(agtype_pair) * (*pstate)->size) — same pattern. Lines 2267, 2366: sizeof(agtentry) * num_elems and sizeof(agtentry) * num_pairs * 2 — chained multiplication without overflow check. Line 1397: it->num_elems * sizeof(agtentry) * 2 Fix this by making explicit checks. Signed-off-by: David Christensen --- src/backend/utils/adt/agtype_util.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/backend/utils/adt/agtype_util.c b/src/backend/utils/adt/agtype_util.c index b39723413..04db30c3e 100644 --- a/src/backend/utils/adt/agtype_util.c +++ b/src/backend/utils/adt/agtype_util.c @@ -1023,6 +1023,8 @@ static agtype_value *push_agtype_value_scalar(agtype_parse_state **pstate, { (*pstate)->size = 4; } + if ((*pstate)->size > SIZE_MAX / sizeof(agtype_value)) + ereport(ERROR, "allocation request exceeds size limits"); (*pstate)->cont_val.val.array.elems = palloc(sizeof(agtype_value) * (*pstate)->size); (*pstate)->last_updated_value = NULL; @@ -1034,6 +1036,8 @@ static agtype_value *push_agtype_value_scalar(agtype_parse_state **pstate, (*pstate)->cont_val.type = AGTV_OBJECT; (*pstate)->cont_val.val.object.num_pairs = 0; (*pstate)->size = 4; + if ((*pstate)->size > SIZE_MAX / sizeof(agtype_pair)) + ereport(ERROR, "allocation request exceeds size limits"); (*pstate)->cont_val.val.object.pairs = palloc(sizeof(agtype_pair) * (*pstate)->size); (*pstate)->last_updated_value = NULL; @@ -1120,6 +1124,8 @@ static void append_key(agtype_parse_state *pstate, agtype_value *string) if (object->val.object.num_pairs >= pstate->size) { pstate->size *= 2; + if ((*pstate)->size > SIZE_MAX / sizeof(agtype_pair)) + ereport(ERROR, "allocation request exceeds size limits"); object->val.object.pairs = repalloc( object->val.object.pairs, sizeof(agtype_pair) * pstate->size); } @@ -1167,6 +1173,8 @@ static void append_element(agtype_parse_state *pstate, if (array->val.array.num_elems >= pstate->size) { pstate->size *= 2; + if ((*pstate)->size > SIZE_MAX / sizeof(agtype_value)) + ereport(ERROR, "allocation request exceeds size limits"); array->val.array.elems = repalloc(array->val.array.elems, sizeof(agtype_value) * pstate->size); } @@ -1631,6 +1639,8 @@ bool agtype_deep_contains(agtype_iterator **val, uint32 j = 0; /* Make room for all possible values */ + if (num_lhs_elems > SIZE_MAX / sizeof(agtype_value)) + ereport(ERROR, "allocation request exceeds size limits"); lhs_conts = palloc(sizeof(agtype_value) * num_lhs_elems); for (i = 0; i < num_lhs_elems; i++)