diff options
author | Denys Vlasenko | 2010-03-24 16:11:32 +0100 |
---|---|---|
committer | Denys Vlasenko | 2010-03-24 16:11:32 +0100 |
commit | 702f7d6c0bb3242e66efb4d1c55b51e535935eab (patch) | |
tree | a84e3b3fde9a7fbf1a4bd311588dd9f0405fbf80 | |
parent | a14a9d73b1274eb7065167914b1b47d3f5e62f6b (diff) | |
download | busybox-702f7d6c0bb3242e66efb4d1c55b51e535935eab.zip busybox-702f7d6c0bb3242e66efb4d1c55b51e535935eab.tar.gz |
udhcp: we call DNS name encoder with NULL, this can SEGV. added a check
function old new delta
dname_enc 418 415 -3
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/domain_codec.c | 80 |
1 files changed, 43 insertions, 37 deletions
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c index 93dfd9a..c81372a 100644 --- a/networking/udhcp/domain_codec.c +++ b/networking/udhcp/domain_codec.c @@ -7,8 +7,6 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#if ENABLE_FEATURE_UDHCP_RFC3397 - #include "common.h" #define NS_MAXDNAME 1025 /* max domain name length */ @@ -63,7 +61,7 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) if (dst) dst[len - 1] = '.'; } else { - /* null: end of current domain name */ + /* NUL: end of current domain name */ if (retpos == 0) { /* toplevel? keep going */ crtpos++; @@ -107,38 +105,39 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) */ static uint8_t *convert_dname(const char *src) { - uint8_t c, *res, *lp, *rp; + uint8_t c, *res, *lenptr, *dst; int len; res = xmalloc(strlen(src) + 2); - rp = lp = res; - rp++; + dst = lenptr = res; + dst++; for (;;) { c = (uint8_t)*src++; - if (c == '.' || c == '\0') { /* end of label */ - len = rp - lp - 1; + if (c == '.' || c == '\0') { /* end of label */ + len = dst - lenptr - 1; /* label too long, too short, or two '.'s in a row? abort */ if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { free(res); return NULL; } - *lp = len; - lp = rp++; - if (c == '\0' || *src == '\0') /* end of dname */ + *lenptr = len; + if (c == '\0' || *src == '\0') /* "" or ".": end of src */ break; - } else { - if (c >= 0x41 && c <= 0x5A) /* uppercase? convert to lower */ - c += 0x20; - *rp++ = c; + lenptr = dst++; + continue; } + if (c >= 'A' && c <= 'Z') /* uppercase? convert to lower */ + c += ('a' - 'A'); + *dst++ = c; } - *lp = 0; - if (rp - res > NS_MAXCDNAME) { /* dname too long? abort */ + if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ free(res); return NULL; } + + *dst = 0; return res; } @@ -147,30 +146,35 @@ static uint8_t *convert_dname(const char *src) static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) { const uint8_t *c, *d; - int off, inc; + int off; /* find all labels in cstr */ off = 0; while (off < clen) { c = cstr + off; - if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { /* pointer, skip */ + if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { /* pointer, skip */ off += 2; - } else if (*c) { /* label, try matching dname */ - inc = *c + 1; + continue; + } + if (*c) { /* label, try matching dname */ d = dname; - while (*c == *d && memcmp(c + 1, d + 1, *c) == 0) { - if (*c == 0) /* match, return offset */ + while (1) { + unsigned len1 = *c + 1; + if (memcmp(c, d, len1) != 0) + break; + if (len1 == 1) /* at terminating NUL - match, return offset */ return off; - d += *c + 1; - c += *c + 1; + d += len1; + c += len1; if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) /* pointer, jump */ c = cstr + (((c[0] & 0x3f) << 8) | c[1]); } - off += inc; - } else { /* null, skip */ - off++; + off += cstr[off] + 1; + continue; } + /* NUL, skip */ + off++; } return -1; @@ -178,7 +182,7 @@ static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) /* computes string to be appended to cstr so that src would be added to * the compression (best case, it's a 2-byte pointer to some offset within - * cstr; worst case, it's all of src, converted to rfc3011 format). + * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). * The computed string is returned directly; its length is returned via retlen; * NULL and 0, respectively, are returned if an error occurs. */ @@ -193,17 +197,19 @@ uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int return NULL; } - for (d = dname; *d != 0; d += *d + 1) { - off = find_offset(cstr, clen, d); - if (off >= 0) { /* found a match, add pointer and terminate string */ - *d++ = NS_CMPRSFLGS + (off >> 8); - *d = off; - break; + d = dname; + while (*d) { + if (cstr) { + off = find_offset(cstr, clen, d); + if (off >= 0) { /* found a match, add pointer and return */ + *d++ = NS_CMPRSFLGS | (off >> 8); + *d = off; + break; + } } + d += *d + 1; } *retlen = d - dname + 1; return dname; } - -#endif /* ENABLE_FEATURE_UDHCP_RFC3397 */ |