Prereq: "3.9.10" diff -ur --new-file /var/tmp/postfix-3.9.10/src/global/mail_version.h ./src/global/mail_version.h --- /var/tmp/postfix-3.9.10/src/global/mail_version.h 2026-05-01 16:49:08.000000000 -0400 +++ ./src/global/mail_version.h 2026-05-15 15:53:10.000000000 -0400 @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20260501" -#define MAIL_VERSION_NUMBER "3.9.10" +#define MAIL_RELEASE_DATE "20260515" +#define MAIL_VERSION_NUMBER "3.9.11" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -ur --new-file /var/tmp/postfix-3.9.10/HISTORY ./HISTORY --- /var/tmp/postfix-3.9.10/HISTORY 2026-05-01 19:48:25.000000000 -0400 +++ ./HISTORY 2026-05-15 15:55:27.000000000 -0400 @@ -28326,3 +28326,31 @@ Cleanup: log a fatal error instead of dereferencing a null pointer after a first/next cursor initialization failure. Fedor Vorobev. File: util/dict_db.c. + +20260507 + + Fix for 'uninitialized value' error. Viktor Dukhovni. File: + auxiliary/collate/collate.pl. + +20260508 + + Claude AI finding: signed integer overshift (util/vstring.h). + Brought to our attention by Robert Sayre. + +20260513 + + Bitrot: builds with musl libc were using the obsolete + NO_SNPRINTF code path in vbuf_print.c. File: util/sys_defs.h. + +20260514 + + Bitrot: the obsolete NO_SNPRINTF code path in vbuf_print.c + wasn't updated for Claude Code findings. File: util/vbuf_print.c. + +20250515 + + Portability: The __MAXINT__(T) macro, to determine the + maximal signed value for objects of type T, was using + implementation-defined behavior (shift one bit into the + sign position). This works today but may break later. + Reported by Kamil Frankowicz. File: util/sys_defs.h. diff -ur --new-file /var/tmp/postfix-3.9.10/auxiliary/collate/collate.pl ./auxiliary/collate/collate.pl --- /var/tmp/postfix-3.9.10/auxiliary/collate/collate.pl 2022-02-11 16:56:54.000000000 -0500 +++ ./auxiliary/collate/collate.pl 2026-05-15 15:52:46.000000000 -0400 @@ -122,8 +122,7 @@ if (defined($transaction{$qid})) { $transaction{$qid} .= $_; } - $transaction{$newid} = - $_ . $transaction{$newid}; + $transaction{$newid} = $_ . ($transaction{$newid} // ""); $seqno{$newid} = ++$i if (! exists $seqno{$newid}); } next; diff -ur --new-file /var/tmp/postfix-3.9.10/src/util/sys_defs.h ./src/util/sys_defs.h --- /var/tmp/postfix-3.9.10/src/util/sys_defs.h 2026-05-01 16:37:37.000000000 -0400 +++ ./src/util/sys_defs.h 2026-05-15 15:52:46.000000000 -0400 @@ -797,8 +797,6 @@ #if HAVE_GLIBC_API_VERSION_SUPPORT(2, 1) #define SOCKADDR_SIZE socklen_t #define SOCKOPT_SIZE socklen_t -#else -#define NO_SNPRINTF #endif #ifndef NO_IPV6 #define HAS_IPV6 @@ -1697,13 +1695,15 @@ /* * Bit banging!! There is no official constant that defines the INT_MAX - * equivalent for off_t, ssize_t, etc. Wietse came up with the following - * macro that works as long as off_t, ssize_t, etc. use one's or two's - * complement logic (that is, the maximum value is binary 01...1). Don't use - * right-shift for signed types: the result is implementation-defined. + * equivalent for off_t, ssize_t, etc. Decades ago, Wietse came up with a + * macro that worked on one's or two's complement logic (that is, the + * maximum value is binary 01...1). As Kamil Frankowicz pointed out, that + * code relied on shifting into the sign bit, which is not defined in the + * language standard. The current version still works on one's and two's + * complement logic, but avoids the undefined behavior. */ #include -#define __MAXINT__(T) ((T) ~(((T) 1) << ((sizeof(T) * CHAR_BIT) - 1))) +#define __MAXINT__(T) ((((T) 1 << (sizeof(T) * CHAR_BIT - 2)) - 1) * 2 + 1) #ifndef OFF_T_MAX #define OFF_T_MAX __MAXINT__(off_t) #endif diff -ur --new-file /var/tmp/postfix-3.9.10/src/util/vbuf_print.c ./src/util/vbuf_print.c --- /var/tmp/postfix-3.9.10/src/util/vbuf_print.c 2026-05-01 16:33:00.000000000 -0400 +++ ./src/util/vbuf_print.c 2026-05-15 15:52:46.000000000 -0400 @@ -122,8 +122,11 @@ VBUF_SKIP(bp); \ } while (0) #else -#define VBUF_SNPRINTF(bp, sz, fmt, arg) do { \ - if (VBUF_SPACE((bp), (sz)) != 0) \ +#define VBUF_SNPRINTF(bp, width_or_prec, type_space, fmt, arg) do { \ + if ((width_or_prec) > INT_MAX - (type_space)) \ + msg_panic("vbuf_print: field width (%d + %lu) > INT_MAX", \ + (width_or_prec), (unsigned long) (type_space)); \ + if (VBUF_SPACE((bp), (width_or_prec) + (type_space)) != 0) \ return (bp); \ sprintf((char *) (bp)->ptr, (fmt), (arg)); \ VBUF_SKIP(bp); \ diff -ur --new-file /var/tmp/postfix-3.9.10/src/util/vstring.h ./src/util/vstring.h --- /var/tmp/postfix-3.9.10/src/util/vstring.h 2020-09-25 16:41:00.000000000 -0400 +++ ./src/util/vstring.h 2026-05-15 15:52:46.000000000 -0400 @@ -62,7 +62,7 @@ /* Flags 24..31 are reserved for VSTRING. */ #define VSTRING_FLAG_EXACT (1<<24) /* exact allocation for tests */ -#define VSTRING_FLAG_MASK (255 << 24) +#define VSTRING_FLAG_MASK (255U << 24) /* * Macros. Unsafe macros have UPPERCASE names.