Hello hackers.

When trying to run `make check` for a build made by clang-21 with
sanitizers enabled:
CFLAGS="-Og  -fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fno-sanitize=function" LDFLAGS="-static-libsan" ...

 I hit into:
../../src/include/lib/sort_template.h:314:15: runtime error: applying non-zero 
offset 8 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior 
../../src/include/lib/sort_template.h:314:15

I could workaround that with:
--- a/src/include/lib/sort_template.h
+++ b/src/include/lib/sort_template.h
@@ -307,6 +307,9 @@ ST_SORT(ST_ELEMENT_TYPE * data, size_t n
     int         r,
                 presorted;

+if (!data && n == 0)
+    return;
+
 loop:

But then there was:
heaptoast.c:770:26: runtime error: addition of unsigned offset to 
0x7395fbd3d204 overflowed to 0x7395fbd3d142
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior heaptoast.c:770:26

sharedtuplestore.c:326:30: runtime error: applying non-zero offset 24 to null 
pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior 
sharedtuplestore.c:326:30

and
trgm_gist.c:702:40: runtime error: applying non-zero offset 16 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior trgm_gist.c:702:40

With the attached patch applied, `make check-world` passes for me.

Reproduced with clang 20.1, but not reproduced with clang 20.0, so maybe
this note is relevant here:
https://releases.llvm.org/20.1.0/tools/clang/docs/ReleaseNotes.html#sanitizers
Changed -fsanitize=pointer-overflow to no longer report NULL + 0 as undefined behavior in C, in line with N3322, and matching the previous behavior for C++. NULL + non_zero continues to be reported as undefined behavior.

Best regards,
Alexander
diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c
index 5c7deb103a6..3a10c8380b7 100644
--- a/contrib/pg_trgm/trgm_gist.c
+++ b/contrib/pg_trgm/trgm_gist.c
@@ -699,7 +699,7 @@ gtrgm_penalty(PG_FUNCTION_ARGS)
 	if (ISARRKEY(newval))
 	{
 		char	   *cache = (char *) fcinfo->flinfo->fn_extra;
-		TRGM	   *cachedVal = (TRGM *) (cache + MAXALIGN(siglen));
+		TRGM	   *cachedVal = cache ? ((TRGM *) (cache + MAXALIGN(siglen))) : NULL;
 		Size		newvalsize = VARSIZE(newval);
 		BITVECP		sign;
 
diff --git a/src/backend/access/heap/heaptoast.c b/src/backend/access/heap/heaptoast.c
index e28fe47a449..13884c26213 100644
--- a/src/backend/access/heap/heaptoast.c
+++ b/src/backend/access/heap/heaptoast.c
@@ -768,7 +768,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,
+			   (int)(curchunk * TOAST_MAX_CHUNK_SIZE - sliceoffset) + chcpystrt,
 			   chunkdata + chcpystrt,
 			   (chcpyend - chcpystrt) + 1);
 
diff --git a/src/backend/utils/sort/sharedtuplestore.c b/src/backend/utils/sort/sharedtuplestore.c
index 8f35a255263..40f9a4606a5 100644
--- a/src/backend/utils/sort/sharedtuplestore.c
+++ b/src/backend/utils/sort/sharedtuplestore.c
@@ -323,7 +323,7 @@ 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_end == NULL && size > 0) || (accessor->write_pointer + size > accessor->write_end))
 	{
 		if (accessor->write_chunk == NULL)
 		{
diff --git a/src/include/lib/sort_template.h b/src/include/lib/sort_template.h
index e02aa73cd4d..71353cdbd72 100644
--- a/src/include/lib/sort_template.h
+++ b/src/include/lib/sort_template.h
@@ -307,6 +307,9 @@ ST_SORT(ST_ELEMENT_TYPE * data, size_t n
 	int			r,
 				presorted;
 
+if (!data && n == 0)
+	return;
+
 loop:
 	DO_CHECK_FOR_INTERRUPTS();
 	if (n < 7)

Reply via email to