Hey,

This adds the more typical strtoll(3) checks we have elsewhere
in the tree to cmp(1).  Make sure we (a) got a number at all,
(b) that it doesn't have any dangling non-digits, (c) that it's
non-negative, and (d) that it didn't overflow.

The only thing in base using the skip extensions to cmp(1) is
distrib/syspatch/diff.sh, and this patch doesn't break it.

This also adds fatal() and fatalx(), convenience wrappers that
check for sflag before logging an error and exiting with status 2.
Use them everywhere except pledge(2) errors and usage errors.
Maybe of note is that we weren't honoring sflag in special.c.

I can separate the fatal()/fatalx() changes from the strtoll-checking
changes, but I wanted to propose them together here because it
makes the strtoll-checking briefer.

ok?

--
Scott Cheloha

Index: usr.bin/cmp/cmp.c
===================================================================
RCS file: /cvs/src/usr.bin/cmp/cmp.c,v
retrieving revision 1.16
diff -u -p -r1.16 cmp.c
--- usr.bin/cmp/cmp.c   28 Oct 2016 07:22:59 -0000      1.16
+++ usr.bin/cmp/cmp.c   2 Mar 2018 03:24:02 -0000
@@ -34,7 +34,9 @@
 #include <sys/stat.h>
 
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -44,6 +46,7 @@
 
 int    lflag, sflag;
 
+static off_t get_skip(const char *, const char *);
 static void __dead usage(void);
 
 int
@@ -84,52 +87,31 @@ main(int argc, char *argv[])
                special = 1;
                fd1 = 0;
                file1 = "stdin";
-       } else if ((fd1 = open(file1, O_RDONLY, 0)) < 0) {
-               if (sflag)
-                       return ERR_EXIT;
-               else
-                       err(ERR_EXIT, "%s", file1);
-       }
+       } else if ((fd1 = open(file1, O_RDONLY, 0)) == -1)
+               fatal("%s", file1);
        if (strcmp(file2 = argv[1], "-") == 0) {
-               if (special) {
-                       if (sflag)
-                               return ERR_EXIT;
-                       else
-                               errx(ERR_EXIT,
-                                       "standard input may only be specified 
once");
-               }
+               if (special)
+                       fatalx("standard input may only be specified once");
                special = 1;
                fd2 = 0;
                file2 = "stdin";
-       } else if ((fd2 = open(file2, O_RDONLY, 0)) < 0) {
-               if (sflag)
-                       return ERR_EXIT;
-               else
-                       err(ERR_EXIT, "%s", file2);
-       }
+       } else if ((fd2 = open(file2, O_RDONLY, 0)) == -1)
+               fatal("%s", file2);
 
        if (pledge("stdio", NULL) == -1)
                err(ERR_EXIT, "pledge");
 
-       skip1 = argc > 2 ? strtoll(argv[2], NULL, 0) : 0;
-       skip2 = argc == 4 ? strtoll(argv[3], NULL, 0) : 0;
+       skip1 = (argc > 2) ? get_skip(argv[2], "skip1") : 0;
+       skip2 = (argc == 4) ? get_skip(argv[3], "skip2") : 0;
 
        if (!special) {
-               if (fstat(fd1, &sb1)) {
-                       if (sflag)
-                               return ERR_EXIT;
-                       else
-                               err(ERR_EXIT, "%s", file1);
-               }
+               if (fstat(fd1, &sb1) == -1)
+                       fatal("%s", file1);
                if (!S_ISREG(sb1.st_mode))
                        special = 1;
                else {
-                       if (fstat(fd2, &sb2)) {
-                               if (sflag)
-                                       return ERR_EXIT;
-                               else
-                                       err(ERR_EXIT, "%s", file2);
-                       }
+                       if (fstat(fd2, &sb2) == -1)
+                               fatal("%s", file2);
                        if (!S_ISREG(sb2.st_mode))
                                special = 1;
                }
@@ -141,6 +123,23 @@ main(int argc, char *argv[])
                c_regular(fd1, file1, skip1, sb1.st_size,
                    fd2, file2, skip2, sb2.st_size);
        return 0;
+}
+
+static off_t
+get_skip(const char *arg, const char *name)
+{
+        off_t skip;
+        char *ep;   
+ 
+        errno = 0;
+        skip = strtoll(arg, &ep, 0);
+        if (ep == arg || *ep != '\0')
+                fatalx("%s is invalid: %s", name, arg);
+        if (skip < 0)
+                fatalx("%s is too small: %s", name, arg);
+        if (skip == LLONG_MAX && errno == ERANGE)
+                fatalx("%s is too large: %s", name, arg);
+        return skip;
 }
 
 static void __dead
Index: usr.bin/cmp/extern.h
===================================================================
RCS file: /cvs/src/usr.bin/cmp/extern.h,v
retrieving revision 1.5
diff -u -p -r1.5 extern.h
--- usr.bin/cmp/extern.h        23 Feb 2007 16:00:04 -0000      1.5
+++ usr.bin/cmp/extern.h        2 Mar 2018 03:24:02 -0000
@@ -39,5 +39,7 @@ void  c_regular(int, char *, off_t, off_t
 void   c_special(int, char *, off_t, int, char *, off_t);
 void   diffmsg(char *, char *, off_t, off_t);
 void   eofmsg(char *);
+void   fatal(const char *, ...);
+void   fatalx(const char *, ...);
 
 extern int lflag, sflag;
Index: usr.bin/cmp/misc.c
===================================================================
RCS file: /cvs/src/usr.bin/cmp/misc.c,v
retrieving revision 1.6
diff -u -p -r1.6 misc.c
--- usr.bin/cmp/misc.c  19 Jan 2011 13:01:25 -0000      1.6
+++ usr.bin/cmp/misc.c  2 Mar 2018 03:24:02 -0000
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 
 #include <err.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -53,4 +54,30 @@ diffmsg(char *file1, char *file2, off_t 
                (void)printf("%s %s differ: char %lld, line %lld\n",
                    file1, file2, (long long)byte, (long long)line);
        exit(DIFF_EXIT);
+}
+
+void
+fatal(const char *fmt, ...)
+{
+       va_list ap;
+
+       if (!sflag) {
+               va_start(ap, fmt);
+               vwarn(fmt, ap);
+               va_end(ap);
+       }
+       exit(ERR_EXIT);
+}
+
+void
+fatalx(const char *fmt, ...)
+{
+       va_list ap;
+
+       if (!sflag) {
+               va_start(ap, fmt);
+               vwarnx(fmt, ap);
+               va_end(ap);
+       }
+       exit(ERR_EXIT);
 }
Index: usr.bin/cmp/special.c
===================================================================
RCS file: /cvs/src/usr.bin/cmp/special.c,v
retrieving revision 1.7
diff -u -p -r1.7 special.c
--- usr.bin/cmp/special.c       19 Jan 2011 13:01:25 -0000      1.7
+++ usr.bin/cmp/special.c       2 Mar 2018 03:24:02 -0000
@@ -48,9 +48,9 @@ c_special(int fd1, char *file1, off_t sk
        int dfound;
 
        if ((fp1 = fdopen(fd1, "r")) == NULL)
-               err(ERR_EXIT, "%s", file1);
+               fatal("%s", file1);
        if ((fp2 = fdopen(fd2, "r")) == NULL)
-               err(ERR_EXIT, "%s", file2);
+               fatal("%s", file2);
 
        dfound = 0;
        while (skip1--)
@@ -79,9 +79,9 @@ c_special(int fd1, char *file1, off_t sk
        }
 
 eof:   if (ferror(fp1))
-               err(ERR_EXIT, "%s", file1);
+               fatal("%s", file1);
        if (ferror(fp2))
-               err(ERR_EXIT, "%s", file2);
+               fatal("%s", file2);
        if (feof(fp1)) {
                if (!feof(fp2))
                        eofmsg(file1);

Reply via email to