]> granicus.if.org Git - procps-ng/commitdiff
0120-w: Prevent out-of-bounds reads in print_display_or_interface().
authorQualys Security Advisory <qsa@qualys.com>
Thu, 1 Jan 1970 00:00:00 +0000 (00:00 +0000)
committerCraig Small <csmall@enc.com.au>
Sat, 23 Jun 2018 11:59:14 +0000 (21:59 +1000)
They occur if disp or tmp reaches host + len: add checks. Also, constify
everything.

w.c

diff --git a/w.c b/w.c
index 724036470c3a68e49480122fb18c6aa878ba3bd3..1516667e9400f49acd4fb92f92c58ee00099de8a 100644 (file)
--- a/w.c
+++ b/w.c
@@ -106,21 +106,22 @@ static void print_host(const char *restrict host, int len, const int fromlen)
 /* This routine prints the display part of the host or IPv6 link address interface */
 static void print_display_or_interface(const char *restrict host, int len, int restlen)
 {
-       char *disp,*tmp;
+       const char *const end = host + (len > 0 ? len : 0);
+       const char *disp, *tmp;
 
        if (restlen <= 0) return; /* not enough space for printing anything */
 
        /* search for a collon (might be a display) */
-       disp = (char *)host;
-       while ( (disp < (host + len)) && (*disp != ':') && isprint(*disp) ) disp++;
+       disp = host;
+       while ( (disp < end) && (*disp != ':') && isprint(*disp) ) disp++;
 
        /* colon found */
-       if (*disp == ':') {
+       if (disp < end && *disp == ':') {
                /* detect multiple colons -> IPv6 in the host (not a display) */
                tmp = disp+1;
-               while ( (tmp < (host + len)) && (*tmp != ':') && isprint(*tmp) ) tmp++;
+               while ( (tmp < end) && (*tmp != ':') && isprint(*tmp) ) tmp++;
 
-               if (*tmp != ':') { /* multiple colons not found - it's a display */
+               if (tmp >= end || *tmp != ':') { /* multiple colons not found - it's a display */
 
                        /* number of chars till the end of the input field */
                        len -= (disp - host);
@@ -142,9 +143,9 @@ static void print_display_or_interface(const char *restrict host, int len, int r
                } else { /* multiple colons found - it's an IPv6 address */
 
                        /* search for % (interface separator in case of IPv6 link address) */
-                       while ( (tmp < (host + len)) && (*tmp != '%') && isprint(*tmp) ) tmp++;
+                       while ( (tmp < end) && (*tmp != '%') && isprint(*tmp) ) tmp++;
 
-                       if (*tmp == '%') { /* interface separator found */
+                       if (tmp < end && *tmp == '%') { /* interface separator found */
 
                                /* number of chars till the end of the input field */
                                len -= (tmp - host);
@@ -163,7 +164,6 @@ static void print_display_or_interface(const char *restrict host, int len, int r
                                        fputc('-', stdout);
                                }
                        }
-
                }
        }