postgres.git / summary / log / commit / refs
commit 73ac2b37401d7aa910ebd81795bb0f4faf0eaab3
Author: John Naylor <john.naylor@postgresql.org>
Date: Wed Feb 04 10:55:49 2026 +0000
First released in: 14.21, 15.16, 16.12, 17.8, 18.2
Fix various instances of undefined behavior
Mostly this involves checking for NULL pointer before doing operations
that add a non-zero offset.
The exception is an overflow warning in heap_fetch_toast_slice(). This
was caused by unneeded parentheses forcing an expression to be
evaluated to a negative integer, which then got cast to size_t.
Per clang 21 undefined behavior sanitizer.
Backpatch to all supported versions.
Co-authored-by: Alexander Lakhin <exclusion@gmail.com>
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Discussion: https://postgr.es/m/777bd201-6e3a-4da0-a922-4ea9de46a3ee@gmail.com
Backpatch-through: 14
contrib/pg_trgm/trgm_gist.c | 5 ++++-
src/backend/access/heap/heaptoast.c | 2 +-
src/backend/utils/adt/multirangetypes.c | 5 +++--
src/backend/utils/sort/sharedtuplestore.c | 3 ++-
4 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index 9ef2e38560a..d89376c7dc7 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -699,10 +699,13 @@ gtrgm_penalty(PG_FUNCTION_ARGS)
if (ISARRKEY(newval))
{
char *cache = (char *) fcinfo->flinfo->fn_extra;
- TRGM *cachedVal = (TRGM *) (cache + MAXALIGN(siglen));
+ TRGM *cachedVal = NULL;
Size newvalsize = VARSIZE(newval);
BITVECP sign;
+ if (cache != NULL)
+ cachedVal = (TRGM *) (cache + MAXALIGN(siglen));
+
/*
* Cache the sign data across multiple calls with the same newval.
*/
diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index 52ecd45654c..ec22fbe0816 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -770,7 +770,7 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
chcpyend = (sliceoffset + slicelength - 1) % TOAST_MAX_CHUNK_SIZE;
memcpy(VARDATA(result) +
- (curchunk * TOAST_MAX_CHUNK_SIZE - sliceoffset) + chcpystrt,
+ curchunk * TOAST_MAX_CHUNK_SIZE - sliceoffset + chcpystrt,
chunkdata + chcpystrt,
(chcpyend - chcpystrt) + 1);
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c
index 9443c2b884a..4c035911e92 100644
--- a/src/backend/utils/adt/multirangetypes.c
+++ b/src/backend/utils/adt/multirangetypes.c
@@ -484,8 +484,9 @@ multirange_canonicalize(TypeCacheEntry *rangetyp, int32 input_range_count,
int32 output_range_count = 0;
/* Sort the ranges so we can find the ones that overlap/meet. */
- qsort_arg(ranges, input_range_count, sizeof(RangeType *), range_compare,
- rangetyp);
+ if (ranges != NULL)
+ qsort_arg(ranges, input_range_count, sizeof(RangeType *),
+ range_compare, rangetyp);
/* Now merge where possible: */
for (i = 0; i < input_range_count; i++)
diff --git a/src/backend/utils/sort/sharedtuplestore.c b/src/backend/utils/sort/sharedtuplestore.c
index 236be65f221..c01704d2f82 100644
--- a/src/backend/utils/sort/sharedtuplestore.c
+++ b/src/backend/utils/sort/sharedtuplestore.c
@@ -325,7 +325,8 @@ sts_puttuple(SharedTuplestoreAccessor *accessor, void *meta_data,
/* Do we have space? */
size = accessor->sts->meta_data_size + tuple->t_len;
- if (accessor->write_pointer + size > accessor->write_end)
+ if (accessor->write_pointer == NULL ||
+ accessor->write_pointer + size > accessor->write_end)
{
if (accessor->write_chunk == NULL)
{
[parent: 6548e4a10d18]