Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
75efc2e
Harden our regex engine against integer overflow in size calculations.
tglsfdc May 11, 2026
a0517df
Prevent buffer overrun in unicode_normalize().
tglsfdc May 11, 2026
c828898
Fix assorted places that need to use palloc_array().
tglsfdc May 11, 2026
56c01e1
Add raw_connect and raw_connect_works to Cluster.pm
michaelpq May 11, 2026
5ebbb28
Fix unbounded recursive handling of SSL/GSS in ProcessStartupPacket()
michaelpq May 11, 2026
b05ed7d
Unify src/common/'s definitions of MaxAllocSize.
tglsfdc May 11, 2026
0400bc8
Guard against overflow in "left" fields of query_int and ltxtquery.
tglsfdc May 11, 2026
2405817
Apply timingsafe_bcmp() in authentication paths
michaelpq May 11, 2026
b670a54
Avoid passing unintended format codes to snprintf().
tglsfdc May 11, 2026
aa0801c
Guard against unsafe conditions in usage of pg_strftime().
tglsfdc May 11, 2026
1f88b09
Check CREATE privilege on multirange type schema in CREATE TYPE.
nathan-bossart May 11, 2026
4febf42
Avoid overflow in size calculations in formatting.c.
nathan-bossart May 11, 2026
958e694
Prevent path traversal in pg_basebackup and pg_rewind
michaelpq May 11, 2026
70a1581
Fix integer-overflow and alignment hazards in locale-related code.
tglsfdc May 11, 2026
ce2e1b0
Fix integer overflow in array_agg(), when the array grows too large
hlinnaka May 11, 2026
17dbe07
Mark PQfn() unsafe and fix overrun in frontend LO interface.
nathan-bossart May 11, 2026
17757d0
refint: Fix SQL injection and buffer overruns.
nathan-bossart May 11, 2026
c248cd5
Partally apply 37842f3dc6c
reshke May 23, 2026
5582acf
Add timingsafe_bcmp(), for constant-time memory comparison
hlinnaka May 11, 2026
ac34fdb
Make palloc_array() and friends safe against integer overflow.
tglsfdc May 11, 2026
1ce5319
Adapt cloubderry mock generator for pg_noinline function attribute
reshke May 24, 2026
7f5b84f
Fix rebase issue in ac34fdb2af95
reshke May 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -19829,6 +19829,16 @@ fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_STRNLEN $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "timingsafe_bcmp" "ac_cv_have_decl_timingsafe_bcmp" "$ac_includes_default"
if test "x$ac_cv_have_decl_timingsafe_bcmp" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_TIMINGSAFE_BCMP $ac_have_decl
_ACEOF


# We can't use AC_REPLACE_FUNCS to replace these functions, because it
Expand Down Expand Up @@ -20182,6 +20192,19 @@ esac

fi

ac_fn_c_check_func "$LINENO" "timingsafe_bcmp" "ac_cv_func_timingsafe_bcmp"
if test "x$ac_cv_func_timingsafe_bcmp" = xyes; then :
$as_echo "#define HAVE_TIMINGSAFE_BCMP 1" >>confdefs.h

else
case " $LIBOBJS " in
*" timingsafe_bcmp.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS timingsafe_bcmp.$ac_objext"
;;
esac

fi



if test "$enable_thread_safety" = yes; then
Expand Down
3 changes: 2 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2400,7 +2400,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
]) # fi

AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
AC_CHECK_DECLS([strlcat, strlcpy, strnlen])
AC_CHECK_DECLS([strlcat, strlcpy, strnlen, timingsafe_bcmp])

# We can't use AC_REPLACE_FUNCS to replace these functions, because it
# won't handle deployment target restrictions on macOS
Expand Down Expand Up @@ -2449,6 +2449,7 @@ AC_REPLACE_FUNCS(m4_normalize([
strlcpy
strnlen
strtof
timingsafe_bcmp
]))

if test "$enable_thread_safety" = yes; then
Expand Down
60 changes: 48 additions & 12 deletions contrib/intarray/_int_bool.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,35 +436,66 @@ boolop(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(result);
}

/*
* Recursively fill the "left" fields of an ITEM array that represents
* a valid postfix tree.
*
* ptr: starting element of array
* pos: in/out argument, the array index this call is responsible to fill
*
* At exit, *pos has been decremented to point before the sub-tree whose
* top is the entry-time value of *pos.
*/
static void
findoprnd(ITEM *ptr, int32 *pos)
{
int32 mypos;

/* since this function recurses, it could be driven to stack overflow. */
check_stack_depth();

/* get the position this call is supposed to update */
mypos = *pos;
Assert(mypos >= 0);

/* in all cases, we should decrement *pos to advance over this item */
(*pos)--;

#ifdef BS_DEBUG
elog(DEBUG3, (ptr[*pos].type == OPR) ?
"%d %c" : "%d %d", *pos, ptr[*pos].val);
elog(DEBUG3, (ptr[mypos].type == OPR) ?
"%d %c" : "%d %d", mypos, ptr[mypos].val);
#endif
if (ptr[*pos].type == VAL)

if (ptr[mypos].type == VAL)
{
ptr[*pos].left = 0;
(*pos)--;
/* base case: a VAL has no operand, so just set its left to zero */
ptr[mypos].left = 0;
}
else if (ptr[*pos].val == (int32) '!')
else if (ptr[mypos].val == (int32) '!')
{
ptr[*pos].left = -1;
(*pos)--;
/* unary operator, likewise easy: operand is just before it */
ptr[mypos].left = -1;
/* recurse to scan operand */
findoprnd(ptr, pos);
}
else
{
ITEM *curitem = &ptr[*pos];
int32 tmp = *pos;
/* binary operator */
int32 delta;

(*pos)--;
/* recurse to scan right operand */
findoprnd(ptr, pos);
curitem->left = *pos - tmp;
/* we must fill left with offset to left operand's top */
/* abs(delta) < QUERYTYPEMAXITEMS, so it can't overflow ... */
delta = *pos - mypos;
/* ... but it might be too large to fit in the 16-bit left field */
Assert(delta < 0);
if (unlikely(delta < PG_INT16_MIN))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("query_int expression is too complex")));
ptr[mypos].left = (int16) delta;
/* recurse to scan left operand */
findoprnd(ptr, pos);
}
}
Expand Down Expand Up @@ -514,6 +545,7 @@ bqarr_in(PG_FUNCTION_ARGS)
query->size = state.num;
ptr = GETQUERY(query);

/* fill the query array from the data makepol constructed */
for (i = state.num - 1; i >= 0; i--)
{
ptr[i].type = state.str->type;
Expand All @@ -523,8 +555,12 @@ bqarr_in(PG_FUNCTION_ARGS)
state.str = tmp;
}

/* now fill the "left" fields */
pos = query->size - 1;
findoprnd(ptr, &pos);
/* if successful, findoprnd should have scanned the whole array */
Assert(pos == -1);

#ifdef BS_DEBUG
initStringInfo(&pbuf);
for (i = 0; i < query->size; i++)
Expand Down
3 changes: 3 additions & 0 deletions contrib/intarray/expected/_int.out
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ SELECT '1&(2&(4&(5|!6)))'::query_int;
1 & 2 & 4 & ( 5 | !6 )
(1 row)

SELECT (SELECT '0 | ' || string_agg(i::text, ' & ')
FROM generate_series(1, 17000) AS i)::query_int;
ERROR: query_int expression is too complex
CREATE TABLE test__int( a int[] );
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' as the Apache Cloudberry data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
Expand Down
2 changes: 2 additions & 0 deletions contrib/intarray/sql/_int.sql
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ SELECT '1&(2&(4&(5&6)))'::query_int;
SELECT '1&2&4&5&6'::query_int;
SELECT '1&(2&(4&(5|6)))'::query_int;
SELECT '1&(2&(4&(5|!6)))'::query_int;
SELECT (SELECT '0 | ' || string_agg(i::text, ' & ')
FROM generate_series(1, 17000) AS i)::query_int;


CREATE TABLE test__int( a int[] );
Expand Down
3 changes: 3 additions & 0 deletions contrib/ltree/expected/ltree.out
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,9 @@ SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_rw%*'::ltxtquery;
f
(1 row)

SELECT (SELECT 'a | ' || string_agg('b', ' & ')
FROM generate_series(1, 17000) AS i)::ltxtquery;
ERROR: ltxtquery is too large
--arrays
SELECT '{1.2.3}'::ltree[] @> '1.2.3.4';
?column?
Expand Down
51 changes: 41 additions & 10 deletions contrib/ltree/ltxtquery_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,31 +271,60 @@ makepol(QPRS_STATE *state)
return END;
}

/*
* Recursively fill the "left" fields of an ITEM array that represents
* a valid postfix tree.
*
* ptr: starting element of array
* pos: in/out argument, the array index this call is responsible to fill
*
* At exit, *pos has been incremented to point after the sub-tree whose
* top is the entry-time value of *pos.
*/
static void
findoprnd(ITEM *ptr, int32 *pos)
{
int32 mypos;

/* since this function recurses, it could be driven to stack overflow. */
check_stack_depth();

if (ptr[*pos].type == VAL || ptr[*pos].type == VALTRUE)
/* get the position this call is supposed to update */
mypos = *pos;

/* in all cases, we should increment *pos to advance over this item */
(*pos)++;

if (ptr[mypos].type == VAL || ptr[mypos].type == VALTRUE)
{
ptr[*pos].left = 0;
(*pos)++;
/* base case: a VAL has no operand, so just set its left to zero */
ptr[mypos].left = 0;
}
else if (ptr[*pos].val == (int32) '!')
else if (ptr[mypos].val == (int32) '!')
{
ptr[*pos].left = 1;
(*pos)++;
/* unary operator, likewise easy: operand is just after it */
ptr[mypos].left = 1;
/* recurse to scan operand */
findoprnd(ptr, pos);
}
else
{
ITEM *curitem = &ptr[*pos];
int32 tmp = *pos;
/* binary operator */
int32 delta;

(*pos)++;
/* recurse to scan right operand */
findoprnd(ptr, pos);
curitem->left = *pos - tmp;
/* we must fill left with offset to left operand's top */
/* delta can't overflow, see LTXTQUERY_TOO_BIG ... */
delta = *pos - mypos;
/* ... but it might be too large to fit in the 16-bit left field */
Assert(delta > 0);
if (unlikely(delta > PG_INT16_MAX))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("ltxtquery is too large")));
ptr[mypos].left = (int16) delta;
/* recurse to scan left operand */
findoprnd(ptr, pos);
}
}
Expand Down Expand Up @@ -372,6 +401,8 @@ queryin(char *buf)
/* set left operand's position for every operator */
pos = 0;
findoprnd(ptr, &pos);
/* if successful, findoprnd should have scanned the whole array */
Assert(pos == state.num);

return query;
}
Expand Down
3 changes: 3 additions & 0 deletions contrib/ltree/sql/ltree.sql
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ SELECT 'tree.awdfg'::ltree @ 'tree & aWdfg@'::ltxtquery;
SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_qw%*'::ltxtquery;
SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_rw%*'::ltxtquery;

SELECT (SELECT 'a | ' || string_agg('b', ' & ')
FROM generate_series(1, 17000) AS i)::ltxtquery;

--arrays

SELECT '{1.2.3}'::ltree[] @> '1.2.3.4';
Expand Down
Loading
Loading