]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Add bounds and option length checking.
authorguy <guy>
Wed, 24 Mar 2004 01:27:29 +0000 (01:27 +0000)
committerguy <guy>
Wed, 24 Mar 2004 01:27:29 +0000 (01:27 +0000)
Use "%u", not "%d", for unsigned values.

print-ip.c

index 8d9e874f34d73677f360903d05188cce107619e7..f1f08d2753c4d33f24ee9e4a2346061d551fa669 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.128.2.4 2003-11-19 00:35:44 guy Exp $ (LBL)";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.128.2.5 2004-03-24 01:27:29 guy Exp $ (LBL)";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -47,14 +47,19 @@ static const char rcsid[] _U_ =
 static void
 ip_printroute(const char *type, register const u_char *cp, u_int length)
 {
-       register u_int ptr = cp[2] - 1;
+       register u_int ptr;
        register u_int len;
 
+       if (length < 3) {
+               printf(" [bad length %u]", length);
+               return;
+       }
        printf(" %s{", type);
        if ((length + 1) & 3)
-               printf(" [bad length %d]", length);
+               printf(" [bad length %u]", length);
+       ptr = cp[2] - 1;
        if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
-               printf(" [bad ptr %d]", cp[2]);
+               printf(" [bad ptr %u]", cp[2]);
 
        type = "";
        for (len = 3; len < length; len += 4) {
@@ -85,45 +90,54 @@ ip_finddst(const struct ip *ip)
        length = (IP_HL(ip) << 2) - sizeof(struct ip);
 
        for (; length > 0; cp += len, length -= len) {
-               int tt = *cp;
+               int tt;
 
+               TCHECK(*cp);
+               tt = *cp;
                if (tt == IPOPT_NOP || tt == IPOPT_EOL)
                        len = 1;
                else {
-                       if (&cp[1] >= snapend) {
-                               return 0;
-                       }
+                       TCHECK(cp[1]);
                        len = cp[1];
                }
-               if (len <= 0) {
-                       return 0;
-               }
-               if (&cp[1] >= snapend || cp + len > snapend) {
+               if (len < 2) {
                        return 0;
                }
+               TCHECK2(*cp, len);
                switch (tt) {
 
                case IPOPT_SSRR:
                case IPOPT_LSRR:
+                       if (len < 7)
+                               return 0;
                        memcpy(&retval, cp + len - 4, 4);
                        return retval;
                }
        }
        return ip->ip_dst.s_addr;
+
+trunc:
+       return 0;
 }
 
 static void
 ip_printts(register const u_char *cp, u_int length)
 {
-       register u_int ptr = cp[2] - 1;
-       register u_int len = 0;
+       register u_int ptr;
+       register u_int len;
        int hoplen;
        const char *type;
 
+       if (length < 4) {
+               printf("[bad length %d]", length);
+               return;
+       }
        printf(" TS{");
        hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
        if ((length - 4) & (hoplen-1))
                printf("[bad length %d]", length);
+       ptr = cp[2] - 1;
+       len = 0;
        if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
                printf("[bad ptr %d]", cp[2]);
        switch (cp[3]&0xF) {
@@ -177,25 +191,21 @@ ip_optprint(register const u_char *cp, u_int length)
        register u_int len;
 
        for (; length > 0; cp += len, length -= len) {
-               int tt = *cp;
+               int tt;
 
+               TCHECK(*cp);
+               tt = *cp;
                if (tt == IPOPT_NOP || tt == IPOPT_EOL)
                        len = 1;
                else {
-                       if (&cp[1] >= snapend) {
-                               printf("[|ip]");
-                               return;
-                       }
+                       TCHECK(cp[1]);
                        len = cp[1];
                }
-               if (len <= 0) {
+               if (len < 2) {
                        printf("[|ip op len %d]", len);
                        return;
                }
-               if (&cp[1] >= snapend || cp + len > snapend) {
-                       printf("[|ip]");
-                       return;
-               }
+               TCHECK2(*cp, len);
                switch (tt) {
 
                case IPOPT_EOL:
@@ -238,8 +248,11 @@ ip_optprint(register const u_char *cp, u_int length)
                        printf(" RA");
                        if (len != 4)
                                printf("{%d}", len);
-                       else if (cp[2] || cp[3])
-                               printf("%d.%d", cp[2], cp[3]);
+                       else {
+                               TCHECK(cp[3]);
+                               if (cp[2] || cp[3])
+                                       printf("%d.%d", cp[2], cp[3]);
+                       }
                        break;
 
                default:
@@ -247,6 +260,10 @@ ip_optprint(register const u_char *cp, u_int length)
                        break;
                }
        }
+       return;
+
+trunc:
+       printf("[|ip]");
 }
 
 /*