A. Schulze:
> postqueue: panic: vbuf_print: output for '%s' exceeds space 0

Unfortunately, there is no way that I can reproduce this in
postfix-3.2.0, given the preconditions in this code.  Does this
machine have ECC meory? Does it have a history of programs crashing?

        Wietse

Message-ID: <20170826122446.horde.wtusryfdzjjo1nij3m0g...@andreasschulze.de>
postfix 3.2.0
postqueue: panic: vbuf_print: output for '%s' exceeds space 0

This msg_panic() call is made from VBUF_SNPRINTF():
#define VBUF_SNPRINTF(bp, sz, fmt, arg) do { \
        ssize_t _ret; \
        VBUF_SPACE((bp), (sz)); \
        _ret = snprintf((char *) (bp)->ptr, (bp)->cnt, (fmt), (arg)); \
        if (_ret < 0) \
            msg_panic("%s: output error for '%s'", myname, (fmt)); \
        if (_ret >= (bp)->cnt) \
            msg_panic("%s: output for '%s' exceeds space %ld", \
                      myname, fmt, (long) (bp)->cnt); \

According to the panic message, (bp)->cnt is zero, meaning the
output buffer has no free space, which can't happen because
VBUF_SNPRINTF() is called with sz > 0, as will be argued below.
Therefore, VBUF_SPACE() is called with a value sz > 0, and the
output buffer must have free space.

The panic message says "%s" therefore this VBUF_SNPRINTF() call is
made while formatting a string with an fmt value of "%s".

This VBUF_SNPRINTF() call is made from vbuf_print():
                s = va_arg(ap, char *);
                if (prec >= 0 || (width > 0 && width > strlen(s))) {
                    VBUF_SNPRINTF(bp, (width > prec ? width : prec) + INT_SPACE,
                                  vstring_str(fmt), s);
                } else {
                    VBUF_STRCAT(bp, s); /* noop for empty string */
                }

This is the only VBUF_SNPRINTF() call with an fmt value of "%<whatever>s".

Note that this VBUF_SNPRINTF() call happens only when prec >= 0
(VBUF_SNPRINTF called with sz >= INT_SPACE) or when width > 0
(VBUF_SNPRINTF called with sz > INT_SPACE).

The fmt argument for VBUF_SNPRINTF() contains "%s". Therefore:

    There was no '-' for left-adjusted field. This info is copied literally.

    There was no '+' for signed field. This info is copied literally.

    There was no '0' for numeric left-padding. This info is copied literally.

    There was no '*' for dynamic field width. This info is converted to
    decimal string and added to the format string.

    There was no hard-coded field width. This info is copied literally.

Therefore width == 0 (see vbuf_print source code).

There was no '.' for precision. This info is copied literally.

    Therefore there was no '*' for dynamic precision.

    Therefore there was no hard-coded precision.

Therefore prec == -1 (see vbuf_print source code).

In order to invoke VBUF_SNPRINTF() for %s, at least one of the
following predicates must be true:

    prec >= 0, falsified by the above analysis.

    width > 0 && width > strlen(s), falsified by the above analysis.

If VBUF_SNPRINTF() is invoked anyway, then some memory was corrupted
either dynamically during program execution, or some bit got flipped
in the file system page cache with some part of the executable file
or Postfix library, so that a constant or instruction was clobbered.

There is no point speculating which memory might be affected, without
making this panic independently reproducible.

Reply via email to