Use the canonical idiom to check strlcat(3). An unchecked strlcat call
authortb <tb@openbsd.org>
Fri, 15 Dec 2017 14:20:52 +0000 (14:20 +0000)
committertb <tb@openbsd.org>
Fri, 15 Dec 2017 14:20:52 +0000 (14:20 +0000)
led to unexpected output: compare 'jot -w $(printf %1020s)%d%' 1 1'
with 'jot -w $(printf %1019s)%d%' 1 1'.

found by & ok martijn

usr.bin/jot/jot.c

index c01ebb0..12b1fc5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: jot.c,v 1.38 2017/12/15 13:04:11 tb Exp $     */
+/*     $OpenBSD: jot.c,v 1.39 2017/12/15 14:20:52 tb Exp $     */
 /*     $NetBSD: jot.c,v 1.3 1994/12/02 20:29:43 pk Exp $       */
 
 /*-
@@ -379,10 +379,9 @@ getformat(void)
                        errx(1, "-w word too long");
                intdata = true;
        } else if (*(p+1) == '\0') {
-               if (sz <= 0)
-                       errx(1, "-w word too long");
                /* cannot end in single '%' */
-               strlcat(format, "%", sizeof format);
+               if (strlcat(format, "%", sizeof(format)) >= sizeof(format))
+                       errx(1, "-w word too long");
        } else {
                /*
                 * Allow conversion format specifiers of the form
@@ -459,7 +458,10 @@ fmt_broken:
                        else if (*p == '%' && *(p+1) == '%')
                                p++;
                        else if (*p == '%' && *(p+1) == '\0') {
-                               strlcat(format, "%", sizeof format);
+                               /* cannot end in single '%' */
+                               if (strlcat(format, "%", sizeof(format)) >=
+                                   sizeof(format))
+                                       errx(1, "-w word too long");
                                break;
                        }
        }