From dd97dd1e196aa8dd0a12afb957b046d984ed491e Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Tue, 12 May 2026 17:43:12 +0000 Subject: [PATCH v1 1/2] Fix refint cascade UPDATE crash with NULL keys check_foreign_key() builds cascade UPDATE queries using the new key value retrieved by SPI_getvalue(). When that value is NULL, SPI_getvalue() returns a NULL pointer, which the code then passed to snprintf("%s"). That is undefined behavior; on most builds it happens to print "(null)", which SQL then parses as the NULL keyword, but on builds with _FORTIFY_SOURCE the snprintf formatter crashes when computing the string length, matching the backtrace in the report. Emit the SQL NULL keyword directly when SPI_getvalue() returns NULL. No regression test is added because triggering the crash requires a hardened libc; without that, the existing code already happens to produce the correct result via the "(null)" substitution above. Reported-by: Nikita Kalinin Discussion: https://postgr.es/m/19476-bd04ea6241345303@postgresql.org --- contrib/spi/refint.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/contrib/spi/refint.c b/contrib/spi/refint.c index fbbd558ca1e..0063410f27e 100644 --- a/contrib/spi/refint.c +++ b/contrib/spi/refint.c @@ -496,12 +496,22 @@ check_foreign_key(PG_FUNCTION_ARGS) #endif /* - * is_char_type =1 i set ' ' for define a new value + * is_char_type =1 i set ' ' for define a new value. + * + * SPI_getvalue() returns NULL for SQL NULL values, so + * emit the NULL keyword rather than passing a NULL + * pointer to snprintf("%s"), which is undefined + * behavior. */ - snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), - " %s = %s%s%s %s ", - args2[k], (is_char_type > 0) ? "'" : "", - nv, (is_char_type > 0) ? "'" : "", (k < nkeys) ? ", " : ""); + if (nv == NULL) + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), + " %s = NULL %s ", + args2[k], (k < nkeys) ? ", " : ""); + else + snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), + " %s = %s%s%s %s ", + args2[k], (is_char_type > 0) ? "'" : "", + nv, (is_char_type > 0) ? "'" : "", (k < nkeys) ? ", " : ""); } strcat(sql, " where "); } -- 2.43.0