Typos (introduced: Postfix 2.10): in comments about
IPv4-in-IPv6 addresses, replace :ffff::1.2.3.4 with the
- correct form :ffff::1.2.3.4. Incorrect or misleading comments
+ correct form ::ffff:1.2.3.4. Incorrect or misleading comments
are worse than no comments. Files: smtpd/smtpd_haproxy.c,
postscreen/postscreen_haproxy.c.
to always store the verify result under the original address,
and to conditionally store it under the rewritten address.
File: global/verify.c.
+
+20170827
+
+ Safety: in vstream_buf_space(), add a sanity check to reject
+ negative request sizes, instead of letting the program fail
+ later. File: util/vstream.c
+
+ Bugfix: in tests that enable the VSTRING_FLAG_EXACT flag,
+ vstring_buf_put_ready() could fail to extend the buffer,
+ causing infinite recursion in VBUF_PUT(). File: util/vstring.c.
+
+20170830
+
+ Bugfix: in vbuf_print(), save the parser-produced format
+ string before calling msg_panic(), so that the panic message
+ will not display its own format string. File: util/vbuf_print.c.
+
+20170831
+
+ Portability (introduced Postfix 1.0): possible cause for
+ panic in postqueue when listing the deferred queue. This
+ assigned the result from unsigned integer subtraction to a
+ signed integer, followed by a safety check to ensure that
+ the result was non-negative. This assignment relied on
+ undefined behavior, meaning that a compiler may eliminate
+ the safety check, causing the program to fail later. File:
+ postqueue/showq_compat.c.
+
+20170910
+
+ Safety: restore sanity checks for dynamically-specified
+ width and precision in format strings (%*, %.*, and %*.*).
+ These checks were lost with the Postfix 3.2.2 rewrite of
+ the vbuf_print formatter. File: vbuf_print.c.
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20170730"
+#define MAIL_RELEASE_DATE "20170910"
#define MAIL_VERSION_NUMBER "3.3"
#ifdef SNAPSHOT
myfree(saved_reason);
saved_reason = mystrdup(STR(why));
show_reason = *saved_reason ? saved_reason : "reason unavailable";
- if ((padding = 76 - strlen(show_reason)) < 0)
+ if ((padding = 76 - (int) strlen(show_reason)) < 0)
padding = 0;
vstream_printf("%*s(%s)\n", padding, "", show_reason);
}
/* Application-specific. */
#include "msg.h"
+#include "mymalloc.h"
#include "vbuf.h"
#include "vstring.h"
#include "vbuf_print.h"
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)); \
+ msg_panic("%s: output error for '%s'", myname, mystrdup(fmt)); \
if (_ret >= (bp)->cnt) \
msg_panic("%s: output for '%s' exceeds space %ld", \
- myname, fmt, (long) (bp)->cnt); \
+ myname, mystrdup(fmt), (long) (bp)->cnt); \
VBUF_SKIP(bp); \
} while (0)
#else
VSTRING_ADDCH(fmt, *cp++);
if (*cp == '*') { /* dynamic field width */
width = va_arg(ap, int);
- VSTRING_ADDNUM(fmt, width);
+ if (width < 0) {
+ msg_warn("%s: bad width %d in %.50s",
+ myname, width, format);
+ width = 0;
+ } else
+ VSTRING_ADDNUM(fmt, width);
cp++;
} else { /* hard-coded field width */
for (width = 0; ch = *cp, ISDIGIT(ch); cp++) {
VSTRING_ADDCH(fmt, *cp++);
if (*cp == '*') { /* dynamic precision */
prec = va_arg(ap, int);
- VSTRING_ADDNUM(fmt, prec);
+ if (prec < 0) {
+ msg_warn("%s: bad precision %d in %.50s",
+ myname, prec, format);
+ prec = -1;
+ } else
+ VSTRING_ADDNUM(fmt, prec);
cp++;
} else { /* hard-coded precision */
for (prec = 0; ch = *cp, ISDIGIT(ch); cp++) {
%.100f 1e308
%g 1e308
%.309g 1e308
+
+%s foo
+%0s foo
+%.0s foo
+%10s foo
+%+10s foo
+%-10s foo
./vbuf_print: "100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
./vbuf_print: "1e+308"
./vbuf_print: "100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336"
+./vbuf_print: "foo"
+./vbuf_print: "foo"
+./vbuf_print: ""
+./vbuf_print: " foo"
+./vbuf_print: " foo"
+./vbuf_print: "foo "
*/
if (bp->put_ready == 0)
msg_panic("%s: read-only stream", myname);
+ if (want < 0)
+ msg_panic("%s: bad length %ld", myname, (long) want);
switch (bp->flags & (VSTREAM_FLAG_READ | VSTREAM_FLAG_WRITE)) {
case VSTREAM_FLAG_READ: /* change direction */
bp->flags &= ~VSTREAM_FLAG_READ;
static int vstring_buf_put_ready(VBUF *bp)
{
- vstring_extend(bp, 0);
+ vstring_extend(bp, 1);
return (0);
}