vi is kind of weird about COLUMNS/LINES handling.

For one, it doesn't do any error checking:

$ COLUMNS=a vi
Floating point exception (core dumped) 

The manpage also claims that COLUMNS supersedes everything else. This
is true... unless you ^Z and then unsuspend, at which point it uses
TIOCGWINSZ.

And then it has to handle :set columns, which it does by setting
environment variables and immediately unsetting them...

Maybe I just don't get it, but it all seems very complicated. For
the time being here's a diff to at least add error checking so COLUMNS
can't crash the program. Kept as strtol() since patches still flow
between our vi and sundry forks.

ok?

Index: cl/cl_term.c
===================================================================
RCS file: /cvs/src/usr.bin/vi/cl/cl_term.c,v
retrieving revision 1.21
diff -u -p -r1.21 cl_term.c
--- cl/cl_term.c        6 Jan 2016 22:28:52 -0000       1.21
+++ cl/cl_term.c        14 Mar 2016 07:38:41 -0000
@@ -319,7 +319,8 @@ cl_ssize(SCR *sp, int sigwinch, size_t *
        struct winsize win;
        size_t col, row;
        int rval;
-       char *p;
+       long lval;
+       char *p, *ep;
 
        /* Assume it's changed. */
        if (changedp != NULL)
@@ -413,10 +414,28 @@ noterm:   if (row == 0)
         * deleting the LINES and COLUMNS environment variables from their
         * dot-files.
         */
-       if ((p = getenv("LINES")) != NULL)
-               row = strtol(p, NULL, 10);
-       if ((p = getenv("COLUMNS")) != NULL)
-               col = strtol(p, NULL, 10);
+       if ((p = getenv("LINES")) != NULL) {
+               errno = 0;
+               lval = strtol(p, &ep, 10);
+               if (p[0] == '\0' || *ep != '\0')
+                       ;
+               else if ((errno == ERANGE && (lval == LONG_MAX || lval ==
+                   LONG_MIN)) || (lval > INT_MAX || lval < 1))
+                       ;
+               else
+                       row = lval;
+       }
+       if ((p = getenv("COLUMNS")) != NULL) {
+               errno = 0;
+               lval = strtol(p, &ep, 10);
+               if (p[0] == '\0' || *ep != '\0')
+                       ;
+               else if ((errno == ERANGE && (lval == LONG_MAX || lval ==
+                   LONG_MIN)) || (lval > INT_MAX || lval < 1))
+                       ;
+               else
+                       col = lval;
+       }
 
        if (rowp != NULL)
                *rowp = row;

Reply via email to