From: wessels <> Date: Fri, 29 Mar 2002 12:49:23 +0000 (+0000) Subject: problems found by Olaf Kirch X-Git-Tag: SQUID_3_0_PRE1~1160 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=13c900c416c03afd3c3402e9f172c0e6db5e49f0;p=thirdparty%2Fsquid.git problems found by Olaf Kirch 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. --- diff --git a/lib/rfc1035.c b/lib/rfc1035.c index 33e716d682..7ef3f0f499 100644 --- a/lib/rfc1035.c +++ b/lib/rfc1035.c @@ -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)) { /*