summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSzabolcs Nagy <nsz@port70.net>2014-06-05 22:32:42 +0200
committerRich Felker <dalias@aerifal.cx>2014-06-06 17:57:37 -0400
commit309cfa4f2c3a5596a024d0bff7bba326382884b4 (patch)
tree63ea5fc0cb154de336417ba76cd3e7a9c4f85c47 /src
parent8daa49cdfd5c74fb8edf931394be11c62b915e52 (diff)
downloadmusl-309cfa4f2c3a5596a024d0bff7bba326382884b4.tar.gz
fix multiple validation issues in dns response label parsing
Due to an error introduced in commit fcc522c92335783293ac19df318415cd97fbf66b, checking of the remaining output buffer space was not performed correctly, allowing malformed input to write past the end of the buffer. In addition, the loop detection logic failed to account for the possibility of infinite loops with no output, which would hang the function. The output size is now limited more strictly so only names with valid length are accepted. (cherry picked from commit b3d9e0b94ea73c68ef4169ec82c898ce59a4e30a)
Diffstat (limited to 'src')
-rw-r--r--src/network/dn_expand.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/src/network/dn_expand.c b/src/network/dn_expand.c
index 96adf37e..849df19a 100644
--- a/src/network/dn_expand.c
+++ b/src/network/dn_expand.c
@@ -4,10 +4,11 @@
int __dn_expand(const unsigned char *base, const unsigned char *end, const unsigned char *src, char *dest, int space)
{
const unsigned char *p = src;
- int len = -1, j;
- if (space > 256) space = 256;
+ char *dend = dest + (space > 254 ? 254 : space);
+ int len = -1, i, j;
if (p==end || !*p) return -1;
- for (;;) {
+ /* detect reference loop using an iteration counter */
+ for (i=0; i < end-base; i+=2) {
if (*p & 0xc0) {
if (p+1==end) return -1;
j = ((p[0] & 0x3f) << 8) | p[1];
@@ -16,7 +17,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig
p = base+j;
} else if (*p) {
j = *p+1;
- if (j>=end-p || j>space) return -1;
+ if (j>=end-p || j>dend-dest) return -1;
while (--j) *dest++ = *++p;
*dest++ = *++p ? '.' : 0;
} else {
@@ -24,6 +25,7 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsig
return len;
}
}
+ return -1;
}
weak_alias(__dn_expand, dn_expand);