]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix various instances of undefined behavior
authorJohn Naylor <john.naylor@postgresql.org>
Wed, 4 Feb 2026 10:55:49 +0000 (17:55 +0700)
committerJohn Naylor <john.naylor@postgresql.org>
Wed, 4 Feb 2026 10:59:18 +0000 (17:59 +0700)
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
src/backend/access/heap/heaptoast.c
src/backend/utils/adt/multirangetypes.c
src/backend/utils/sort/sharedtuplestore.c

index 6f28db7d1edb19a1b487ab559723b105b28aea70..711413df491b039724ed8485cdfa6cc81853f7d5 100644 (file)
@@ -692,10 +692,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.
                 */
index 1575a81b01b6b11d58fa1586dcabd4b009760e41..4e88295df772fb6def0f9c3b7e04e528d60a7fa6 100644 (file)
@@ -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);
 
index da5c7d0906999247ca9c70a3606a1cf3d27d15f0..b482e3e6117a4551bae8a684a7c85702cc1b7728 100644 (file)
@@ -478,8 +478,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++)
index 464d4c5b7fd90278fdba807a8d0d0619f9a786a2..dd4b96ab2eb1b2e0cb9b430521d2c5c834ae231d 100644 (file)
@@ -321,7 +321,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)
                {