]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
problems found by Olaf Kirch <okir@caldera.de>
authorwessels <>
Fri, 29 Mar 2002 12:49:23 +0000 (12:49 +0000)
committerwessels <>
Fri, 29 Mar 2002 12:49:23 +0000 (12:49 +0000)
rfc1035NameUnpack() incorrectly compared the label size (len) to the
whole name buffer size (ns).  It needs to use the name buffer offset (no).

We should exit the do-while loop upon reaching the end of the name
buffer just to be safe.

rfc1035NameUnpack() didn't detect infinite recursion.

lib/rfc1035.c

index 33e716d6824a24be41a1d95d5261e19cef7b2072..7ef3f0f4990a1a5921049bc6ed8de1f36c0e8a5c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: rfc1035.c,v 1.24 2002/03/19 03:03:12 wessels Exp $
+ * $Id: rfc1035.c,v 1.25 2002/03/29 05:49:23 wessels Exp $
  *
  * Low level DNS protocol routines
  * AUTHOR: Duane Wessels
@@ -299,7 +299,7 @@ rfc1035HeaderUnpack(const char *buf, size_t sz, off_t * off, rfc1035_header * h)
  * Returns 0 (success) or 1 (error)
  */
 static int
-rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns)
+rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns, int rflag)
 {
     off_t no = 0;
     unsigned char c;
@@ -312,6 +312,8 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
            /* blasted compression */
            unsigned short s;
            off_t ptr;
+           if (rflag)          /* pointer loop */
+               return 1;
            memcpy(&s, buf + (*off), sizeof(s));
            s = ntohs(s);
            (*off) += sizeof(s);
@@ -322,7 +324,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
            /* Make sure the pointer is inside this message */
            if (ptr >= sz)
                return 1;
-           return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no);
+           return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no, rflag + 1);
        } else if (c > RFC1035_MAXLABELSZ) {
            /*
             * "(The 10 and 01 combinations are reserved for future use.)"
@@ -333,8 +335,8 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
            len = (size_t) c;
            if (len == 0)
                break;
-           if (len > (ns - 1))
-               len = ns - 1;
+           if (len > (ns - no - 1))    /* label won't fit */
+               return 1;
            if ((*off) + len > sz)      /* message is too short */
                return 1;
            memcpy(name + no, buf + (*off), len);
@@ -342,7 +344,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
            no += len;
            *(name + (no++)) = '.';
        }
-    } while (c > 0);
+    } while (c > 0 && no < ns);
     *(name + no - 1) = '\0';
     /* make sure we didn't allow someone to overflow the name buffer */
     assert(no <= ns);
@@ -365,7 +367,7 @@ rfc1035RRUnpack(const char *buf, size_t sz, off_t * off, rfc1035_rr * RR)
     unsigned short s;
     unsigned int i;
     off_t rdata_off;
-    if (rfc1035NameUnpack(buf, sz, off, RR->name, RFC1035_MAXHOSTNAMESZ)) {
+    if (rfc1035NameUnpack(buf, sz, off, RR->name, RFC1035_MAXHOSTNAMESZ, 0)) {
        RFC1035_UNPACK_DEBUG;
        memset(RR, '\0', sizeof(*RR));
        return 1;
@@ -404,7 +406,7 @@ rfc1035RRUnpack(const char *buf, size_t sz, off_t * off, rfc1035_rr * RR)
     case RFC1035_TYPE_PTR:
        RR->rdata = malloc(RFC1035_MAXHOSTNAMESZ);
        rdata_off = *off;
-       if (rfc1035NameUnpack(buf, sz, &rdata_off, RR->rdata, RFC1035_MAXHOSTNAMESZ))
+       if (rfc1035NameUnpack(buf, sz, &rdata_off, RR->rdata, RFC1035_MAXHOSTNAMESZ, 0))
            return 1;
        if (rdata_off != ((*off) + RR->rdlength)) {
            /*