]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.9.10 postfix-3.9 v3.9.10
authorWietse Z Venema <wietse@porcupine.org>
Fri, 1 May 2026 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Sat, 2 May 2026 08:48:19 +0000 (18:48 +1000)
17 files changed:
postfix/HISTORY
postfix/makedefs
postfix/src/global/dict_pgsql.c
postfix/src/global/dsn_util.c
postfix/src/global/mail_version.h
postfix/src/global/pipe_command.c
postfix/src/tls/tls_prng_file.c
postfix/src/util/argv.c
postfix/src/util/dict_cdb.c
postfix/src/util/dict_cidr.c
postfix/src/util/dict_db.c
postfix/src/util/dict_pcre.c
postfix/src/util/dict_sockmap.c
postfix/src/util/midna_domain.c
postfix/src/util/netstring.c
postfix/src/util/sys_defs.h
postfix/src/util/vbuf_print.c

index 3cf6d402727f4db30eeb6cb41690597745843eed..358357ff12b5974007a3001031a298063201dfda 100644 (file)
@@ -28282,3 +28282,47 @@ Apologies for any names omitted.
        recursive logging loop with "posttls-finger -v -v -v".
        Reported by Geert Hendrickx, diagnosed by Viktor Dukhovni,
        and fixed by Wietse. Files: util/vstream.[hc], util/msg_vstream.c.
+
+20260310
+
+       Bugfix (defect introduced: Postfix 3.0): buffer over-read
+       when Postfix is configured with an enhanced status code not
+       followed by other text. For example, "5.7.2" without text
+       after the three-number code in a remote server response,
+       in an access(5) table, header or body checks, or with
+       "$rbl_code $rbl_text" in rbl_reply_maps or default_rbl_reply.
+       Problem reported by Kamil Frankowicz.  File: global/dsn_split.c.
+
+20260426
+
+       Portability: support for recent FreeBSD, NetBSD, and OpenBSD
+       versions. Brad Smith. Files: makedefs, util/sys_defs.h.
+
+20260501
+
+       Bugfix (defect introduced: Postfix 2.2, date 20041207):
+       When truncating a database file, the CDB client looked at
+       the file size from before requesting an exclusive lock on
+       a database file, instead of the file size after the exclusive
+       lock was granted. Found by Claude Opus 4.6. File:
+       util/dict_cdb.c.
+
+       Bugfix (defect introduced: Postfix alpha, date 19980309):
+       file descriptor leak after fork() failure. Found by Claude
+       Opus 4.6. File: global/pipe_command.c.
+
+       Mistakes in debug logging. Found by Claude Opus 4.6. Files:
+       util/dict_cidr.c, tls/tls_prng_file.c.
+
+       Unchecked null pointer results after an out-of-memory
+       condition in a library dependency. Found by Claude Opus
+       4.6. Files: util/dict_pcre.c, util/midna_domain.c,
+       global/dict_pgsql.c.
+
+       Missing or incomplete guards for ssize_t or int overflow,
+       found by Claude Opus 4.6. Files: util/argv.c, util/netstring.c,
+       util/vbuf_print.c.
+
+       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.
index 14810b6dc6c0f3eba08d4e81c81f324f735435f9..893208c360cdf27b1fbdff96a5299b62f46a9ed4 100644 (file)
@@ -347,6 +347,24 @@ case "$SYSTEM.$RELEASE" in
                : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
                : ${PLUGIN_LD="${CC} -shared"}
                ;;
+   FreeBSD.15*)        SYSTYPE=FREEBSD15
+               : ${CC=cc}
+               : ${SHLIB_SUFFIX=.so}
+               : ${SHLIB_CFLAGS=-fPIC}
+               : ${SHLIB_LD="${CC} -shared"' -Wl,-soname,${LIB}'}
+               : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'}
+               : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
+               : ${PLUGIN_LD="${CC} -shared"}
+               ;;
+   FreeBSD.16*)        SYSTYPE=FREEBSD16
+               : ${CC=cc}
+               : ${SHLIB_SUFFIX=.so}
+               : ${SHLIB_CFLAGS=-fPIC}
+               : ${SHLIB_LD="${CC} -shared"' -Wl,-soname,${LIB}'}
+               : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'}
+               : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
+               : ${PLUGIN_LD="${CC} -shared"}
+               ;;
  DragonFly.*)  SYSTYPE=DRAGONFLY
                ;;
   OpenBSD.2*)  SYSTYPE=OPENBSD2
@@ -382,9 +400,18 @@ case "$SYSTEM.$RELEASE" in
                : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
                : ${PLUGIN_LD="${CC} -shared"}
                ;;
+  OpenBSD.8*)  SYSTYPE=OPENBSD8
+               : ${CC=cc}
+               : ${SHLIB_SUFFIX=.so.1.0}
+               : ${SHLIB_CFLAGS=-fPIC}
+               : ${SHLIB_LD="${CC} -shared"' -Wl,-soname,${LIB}'}
+               : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'}
+               : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
+               : ${PLUGIN_LD="${CC} -shared"}
+               ;;
   ekkoBSD.1*)  SYSTYPE=EKKOBSD1
                ;;
-   NetBSD.1*)  SYSTYPE=NETBSD1
+   NetBSD.1.*) SYSTYPE=NETBSD1
                ;;
    NetBSD.2*)  SYSTYPE=NETBSD2
                ;;
@@ -434,6 +461,22 @@ case "$SYSTEM.$RELEASE" in
                : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
                : ${PLUGIN_LD="${CC-gcc} -shared"}
                ;;
+   NetBSD.11*) SYSTYPE=NETBSD11
+               : ${SHLIB_SUFFIX=.so}
+               : ${SHLIB_CFLAGS=-fPIC}
+               : ${SHLIB_LD="${CC-gcc} -shared"' -Wl,-soname,${LIB}'}
+               : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'}
+               : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
+               : ${PLUGIN_LD="${CC-gcc} -shared"}
+               ;;
+   NetBSD.12*) SYSTYPE=NETBSD12
+               : ${SHLIB_SUFFIX=.so}
+               : ${SHLIB_CFLAGS=-fPIC}
+               : ${SHLIB_LD="${CC-gcc} -shared"' -Wl,-soname,${LIB}'}
+               : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'}
+               : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
+               : ${PLUGIN_LD="${CC-gcc} -shared"}
+               ;;
    BSD/OS.2*)  SYSTYPE=BSDI2
                ;;
    BSD/OS.3*)  SYSTYPE=BSDI3
index 89cb59f070da202bbadcd3f71d88b68247d17c02..902c057e8c3f913434a5ac23b1770e24c2f9a516 100644 (file)
@@ -572,8 +572,10 @@ static void plpgsql_connect_single(DICT_PGSQL *dict_pgsql, HOST *host)
                                dict_pgsql->password);
     }
     if (host->db == NULL || PQstatus(host->db) != CONNECTION_OK) {
+       /* 202604 Claude: don't call PQerrorMessage(NULL). */
        msg_warn("connect to pgsql server %s: %s",
-                host->hostname, PQerrorMessage(host->db));
+                host->hostname, host->db ? PQerrorMessage(host->db) :
+                "PQconnectdb or PQsetdbLogin failed");
        plpgsql_down_host(host, dict_pgsql->retry_interval);
        return;
     }
index 52b997a3320593bc2ab577442d38e7290e11a18f..57511280a5a0afe3360f055466e6e6f1a39604d3 100644 (file)
@@ -154,7 +154,7 @@ DSN_SPLIT *dsn_split(DSN_SPLIT *dp, const char *def_dsn, const char *text)
     if ((len = dsn_valid(cp)) > 0) {
        strncpy(dp->dsn.data, cp, len);
        dp->dsn.data[len] = 0;
-       cp += len + 1;
+       cp += len;
     } else if ((len = dsn_valid(def_dsn)) > 0) {
        strncpy(dp->dsn.data, def_dsn, len);
        dp->dsn.data[len] = 0;
index 0142198dcb5121886b16c846333d09cc04c7d4c1..a627f3b67e75c42038c4d7c9fd46e63d1208913a 100644 (file)
@@ -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      "20260218"
-#define MAIL_VERSION_NUMBER    "3.9.9"
+#define MAIL_RELEASE_DATE      "20260501"
+#define MAIL_VERSION_NUMBER    "3.9.10"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index 66aec8a67321d493e90dde1f7d9a695f69fe6261..a7a1d62a5f805b86ba21357399d93563aa23deee 100644 (file)
@@ -460,6 +460,11 @@ int     pipe_command(VSTREAM *src, DSN_BUF *why,...)
        msg_warn("fork: %m");
        dsb_unix(why, "4.3.0", sys_exits_detail(EX_OSERR)->text,
                 "Delivery failed: %m");
+       /* 202604 Claude: close pipes for the child and parent paths. */
+       close(cmd_in_pipe[0]);
+       close(cmd_in_pipe[1]);
+       close(cmd_out_pipe[0]);
+       close(cmd_out_pipe[1]);
        return (PIPE_STAT_DEFER);
 
        /*
index 23865be39db8df64bffa419542038e45210165bf..14feebe2629c1d67d7ffc12614ace7817dbf353c 100644 (file)
@@ -132,7 +132,8 @@ ssize_t tls_prng_file_read(TLS_PRNG_SRC *fh, size_t len)
        RAND_seed(buffer, count);
     }
     if (msg_verbose)
-       msg_info("read %ld bytes from entropy file %s: %m",
+       /* 202604 Claude: remove '%m' from non-error logging. */
+       msg_info("read %ld bytes from entropy file %s",
                 (long) (len - to_read), fh->name);
     return (len - to_read);
 }
index 332426e88790ba9e51935207c2a7fc931cbd1e35..15456766d9e4a83072ab5c02ba49ef5f19119521 100644 (file)
@@ -192,6 +192,9 @@ ARGV   *argv_alloc(ssize_t len)
     argvp = (ARGV *) mymalloc(sizeof(*argvp));
     argvp->len = 0;
     sane_len = (len < 2 ? 2 : len);
+    /* 202604 Claude: avoid overflowing sane_len + 1 */
+    if (sane_len > SSIZE_MAX - 1)
+       msg_panic("argv_alloc: array length overflow");
     argvp->argv = (char **) mymalloc((sane_len + 1) * sizeof(char *));
     argvp->len = sane_len;
     argvp->argc = 0;
@@ -250,6 +253,9 @@ static void argv_extend(ARGV *argvp)
 {
     ssize_t new_len;
 
+    /* 202604 Claude: avoid overflowing (new_len + 1) * sizeof(char *).  */
+    if (argvp->len > SSIZE_MAX / (2 * sizeof(char *)) - 1)
+       msg_panic("argv_extend: array length overflow");
     new_len = argvp->len * 2;
     argvp->argv = (char **)
        myrealloc((void *) argvp->argv, (new_len + 1) * sizeof(char *));
@@ -376,9 +382,10 @@ void    argv_delete(ARGV *argvp, ssize_t first, ssize_t how_many)
     ssize_t pos;
 
     /*
-     * Sanity check.
+     * Sanity check. 202604 Claude: avoid expression 'first + how_many'.
      */
-    if (first < 0 || how_many < 0 || first + how_many > argvp->argc)
+    if (first < 0 || how_many < 0 || first > argvp->argc 
+       || how_many > argvp->argc - first)
        msg_panic("argv_delete bad range: (start=%ld count=%ld)",
                  (long) first, (long) how_many);
 
index a9133cc3555f9361cbfa224d082fb19ffb2c91eb..d44571545fa6b7927db3e6d46c84ae30dc2b249f 100644 (file)
@@ -394,7 +394,8 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags)
     }
 
 #ifndef NO_FTRUNCATE
-    if (st0.st_size)
+    /* 202604 Claude: use the post-myflock() fstat result. */
+    if (st1.st_size)
        ftruncate(fd, 0);
 #endif
 
index 726d11cd6fb4117532d0d8a798f13a60310e307a..f8246b3e831c42c26f225479bf07b71561e7ed2f 100644 (file)
@@ -237,11 +237,14 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(DICT *dict, char *p, int lineno,
     rule->lineno = lineno;
 
     if (msg_verbose) {
-       if (inet_ntop(cidr_info.addr_family, cidr_info.net_bytes,
-                     hostaddr.buf, sizeof(hostaddr.buf)) == 0)
-           msg_fatal("inet_ntop: %m");
-       msg_info("dict_cidr_open: add %s/%d %s",
-                hostaddr.buf, cidr_info.mask_shift, rule->value);
+       /* 202604 Claude: ENDIF has no address pattern. */
+       if (cidr_info.op != CIDR_MATCH_OP_ENDIF) {
+           if (inet_ntop(cidr_info.addr_family, cidr_info.net_bytes,
+                         hostaddr.buf, sizeof(hostaddr.buf)) == 0)
+               msg_fatal("inet_ntop: %m");
+           msg_info("dict_cidr_open: add %s/%d %s",
+                    hostaddr.buf, cidr_info.mask_shift, rule->value);
+       }
     }
     return (rule);
 }
index 053db3c1edcc1cedda51131a6c2bf7617da3e342..4084561f2227adb5c755a0d8dd90ac13ee0fe296 100644 (file)
@@ -446,8 +446,10 @@ static int dict_db_sequence(DICT *dict, int function,
      */
     switch (function) {
     case DICT_SEQ_FUN_FIRST:
-       if (dict_db->cursor == 0)
-           DICT_DB_CURSOR(db, &(dict_db->cursor));
+       if (dict_db->cursor == 0
+           && (status = DICT_DB_CURSOR(db, &(dict_db->cursor))) != 0)
+           msg_fatal("error [%d] initializing cursor for %s: %m",
+                     status, dict_db->dict.name);
        db_function = DB_FIRST;
        break;
     case DICT_SEQ_FUN_NEXT:
index 20eee02c112c85c08f42ab9d015fbc956e3010ff..94b90c6dd10375d43b80b5d91542c98ba0ab5c34 100644 (file)
@@ -728,6 +728,9 @@ static int dict_pcre_compile(const char *mapname, int lineno,
     }
     engine->match_data = pcre2_match_data_create_from_pattern(
                                               engine->pattern, (void *) 0);
+    /* 202604 Claude: handle error result. */
+    if (engine->match_data == 0)
+       msg_fatal("out of memory in pcre2_match_data_create_from_pattern()");
 #endif
     return (1);
 }
index becad1ae875d63570dd4dcde32f5b80e386b9dce..8c6c29829e91e2846a991806f8a1821783017d40 100644 (file)
@@ -254,7 +254,8 @@ static const char *dict_sockmap_lookup(DICT *dict, const char *key)
     reply_payload = split_at(STR(dp->rdwr_buf), ' ');
     if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_OK) == 0) {
        dict->error = 0;
-       return (reply_payload);
+       /* 202604 Claude: don't return NULL with dict->error==0. */
+       return (reply_payload ? reply_payload : "");
     } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_NOTFOUND) == 0) {
        dict->error = 0;
        return (0);
index bc016b637922692f6a1c7ce9d62e9463f2827472..21d681617863086ee96b2429d28bc288f5c379b4 100644 (file)
@@ -189,11 +189,13 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context
      */
     idna = uidna_openUTS46(midna_domain_transitional ? UIDNA_DEFAULT
                           : UIDNA_NONTRANSITIONAL_TO_ASCII, &error);
-    anl = uidna_nameToASCII_UTF8(idna,
-                                name, strlen(name),
-                                buf, sizeof(buf) - 1,
-                                &info,
-                                &error);
+    /* 202604 Claude: avoid null deref after uidna_openUTS46() failure. */
+    if (idna && U_SUCCESS(error))
+       anl = uidna_nameToASCII_UTF8(idna,
+                                    name, strlen(name),
+                                    buf, sizeof(buf) - 1,
+                                    &info,
+                                    &error);
     uidna_close(idna);
 
     /*
@@ -203,7 +205,7 @@ static void *midna_domain_to_ascii_create(const char *name, void *unused_context
      * "fake" A-labels, as required by UTS 46 section 4.1, but we rely on
      * valid_hostname() on the output side just to be sure.
      */
-    if (U_SUCCESS(error) && info.errors == 0 && anl > 0) {
+    if (idna && U_SUCCESS(error) && info.errors == 0 && anl > 0) {
        buf[anl] = 0;                           /* XXX */
        if (!valid_hostname(buf, DONT_GRIPE)) {
            msg_warn("%s: Problem translating domain \"%.100s\" to ASCII form: %s",
@@ -243,11 +245,13 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context)
      */
     idna = uidna_openUTS46(midna_domain_transitional ? UIDNA_DEFAULT
                           : UIDNA_NONTRANSITIONAL_TO_UNICODE, &error);
-    anl = uidna_nameToUnicodeUTF8(idna,
-                                 name, strlen(name),
-                                 buf, sizeof(buf) - 1,
-                                 &info,
-                                 &error);
+    /* 202604 Claude: avoid null deref after uidna_openUTS46() failure. */
+    if (idna && U_SUCCESS(error))
+       anl = uidna_nameToUnicodeUTF8(idna,
+                                     name, strlen(name),
+                                     buf, sizeof(buf) - 1,
+                                     &info,
+                                     &error);
     uidna_close(idna);
 
     /*
@@ -256,7 +260,7 @@ static void *midna_domain_to_utf8_create(const char *name, void *unused_context)
      * other invalid forms that are not covered in UTS 46, section 4.1). We
      * rely on midna_domain_to_ascii() to validate the output.
      */
-    if (U_SUCCESS(error) && info.errors == 0 && anl > 0) {
+    if (idna && U_SUCCESS(error) && info.errors == 0 && anl > 0) {
        buf[anl] = 0;                           /* XXX */
        if (midna_domain_to_ascii(buf) == 0)
            return (0);
index 0edd80e1b848a1fd1bdbc913b3046e8818cb4386..471d33d7897d5034be1007d6ba7957a9211e00e1 100644 (file)
@@ -301,14 +301,17 @@ void    netstring_put_multi(VSTREAM *stream,...)
     VA_COPY(ap2, ap);
 
     /*
-     * Figure out the total result size.
+     * Figure out the total result size. 202604 Claude: move the wrap-around
+     * guard inside the loop.
      */
-    for (total = 0; (data = va_arg(ap, char *)) != 0; total += data_len)
+    for (total = 0; (data = va_arg(ap, char *)) != 0; /* see below */ ) {
        if ((data_len = va_arg(ap, ssize_t)) < 0)
            msg_panic("%s: bad data length %ld", myname, (long) data_len);
+       if (data_len > SSIZE_T_MAX - total)
+           msg_panic("%s: total length overflow", myname);
+       total += data_len;
+    }
     va_end(ap);
-    if (total < 0)
-       msg_panic("%s: bad total length %ld", myname, (long) total);
     if (msg_verbose > 1)
        msg_info("%s: write total length %ld", myname, (long) total);
 
index 62749ab574261cc01361528c6d9f41034b679412..ab1b00a5984ea3282de5d2f583b5dc1566b9d8fa 100644 (file)
     || defined(FREEBSD5) || defined(FREEBSD6) || defined(FREEBSD7) \
     || defined(FREEBSD8) || defined(FREEBSD9) || defined(FREEBSD10) \
     || defined(FREEBSD11) || defined(FREEBSD12) || defined(FREEBSD13) \
-    || defined(FREEBSD14) \
+    || defined(FREEBSD14) || defined(FREEBSD15) || defined(FREEBSD16) \
     || defined(BSDI2) || defined(BSDI3) || defined(BSDI4) \
     || defined(OPENBSD2) || defined(OPENBSD3) || defined(OPENBSD4) \
     || defined(OPENBSD5) || defined(OPENBSD6) || defined(OPENBSD7) \
+    || defined(OPENBSD8) \
     || defined(NETBSD1) || defined(NETBSD2) || defined(NETBSD3) \
     || defined(NETBSD4) || defined(NETBSD5) || defined(NETBSD6) \
     || defined(NETBSD7) | defined(NETBSD8) || defined(NETBSD9) \
-    || defined(NETBSD10) \
+    || defined(NETBSD10) || defined(NETBSD11) || defined(NETBSD12) \
     || defined(EKKOBSD1) || defined(DRAGONFLY)
 #define SUPPORTED
 #include <sys/param.h>
index d7a323f241dd7cd6039bf6272c32da267703a37f..70bc35a99d645ae7dfa6fc0e8be4158b64815520 100644 (file)
 
  /*
   * Helper macros... Note that there is no need to check the result from
-  * VSTRING_SPACE() because that always succeeds or never returns.
+  * VSTRING_SPACE() because that always succeeds or never returns. 202406
+  * Claude: avoid integer overflow in field width computations.
   */
 #ifndef NO_SNPRINTF
-#define VBUF_SNPRINTF(bp, sz, fmt, arg) do { \
+#define VBUF_SNPRINTF(bp, width_or_prec, type_space, fmt, arg) do { \
        ssize_t _ret; \
-       if (VBUF_SPACE((bp), (sz)) != 0) \
+       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); \
        _ret = snprintf((char *) (bp)->ptr, (bp)->cnt, (fmt), (arg)); \
        if (_ret < 0) \
     } while (0)
 
 #define VSTRING_ADDNUM(vp, n) do { \
-       VBUF_SNPRINTF(&(vp)->vbuf, INT_SPACE, "%d", n); \
+       VBUF_SNPRINTF(&(vp)->vbuf, 0, INT_SPACE, "%d", n); \
     } while (0)
 
 #define VBUF_STRCAT(bp, s) do { \
@@ -259,7 +263,7 @@ VBUF   *vbuf_print(VBUF *bp, const char *format, va_list ap)
                    msg_panic("%s: %%l%c is not supported", myname, *cp);
                s = va_arg(ap, char *);
                if (prec >= 0 || (width > 0 && width > strlen(s))) {
-                   VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE,
+                   VBUF_SNPRINTF(bp, (width > prec ? width : prec), INT_SPACE,
                                  vstring_str(fmt), s);
                } else {
                    VBUF_STRCAT(bp, s);
@@ -275,17 +279,17 @@ VBUF   *vbuf_print(VBUF *bp, const char *format, va_list ap)
            case 'x':
            case 'X':
                if (long_flag)
-                   VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE,
+                   VBUF_SNPRINTF(bp, (width > prec ? width : prec), INT_SPACE,
                                  vstring_str(fmt), va_arg(ap, long));
                else
-                   VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE,
+                   VBUF_SNPRINTF(bp, (width > prec ? width : prec), INT_SPACE,
                                  vstring_str(fmt), va_arg(ap, int));
                break;
            case 'e':                           /* float-valued argument */
            case 'f':
            case 'g':
                /* C99 *printf ignore the 'l' modifier. */
-               VBUF_SNPRINTF(bp, (width > prec ? width : prec) + DBL_SPACE,
+               VBUF_SNPRINTF(bp, (width > prec ? width : prec), DBL_SPACE,
                              vstring_str(fmt), va_arg(ap, double));
                break;
            case 'm':
@@ -296,7 +300,7 @@ VBUF   *vbuf_print(VBUF *bp, const char *format, va_list ap)
            case 'p':
                if (long_flag)
                    msg_panic("%s: %%l%c is not supported", myname, *cp);
-               VBUF_SNPRINTF(bp, (width > prec ? width : prec) + PTR_SPACE,
+               VBUF_SNPRINTF(bp, (width > prec ? width : prec), PTR_SPACE,
                              vstring_str(fmt), va_arg(ap, char *));
                break;
            default:                            /* anything else is bad */