udhcp: fix a SEGV on malformed RFC1035-encoded domain name
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 10 Mar 2016 10:47:58 +0000 (11:47 +0100)
committerMike Frysinger <vapier@gentoo.org>
Mon, 21 Mar 2016 18:23:12 +0000 (14:23 -0400)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
(cherry picked from commit d474ffc68290e0a83651c4432eeabfa62cd51e87)

networking/udhcp/domain_codec.c

index c1325d8be947ce6a9ba13dc88be75854dde3403b..8429367b8189816be84e865ca4a3adfd7d9df80c 100644 (file)
@@ -63,11 +63,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
                                if (crtpos + *c + 1 > clen) /* label too long? abort */
                                        return NULL;
                                if (dst)
-                                       memcpy(dst + len, c + 1, *c);
+                                       /* \3com ---> "com." */
+                                       ((char*)mempcpy(dst + len, c + 1, *c))[0] = '.';
                                len += *c + 1;
                                crtpos += *c + 1;
-                               if (dst)
-                                       dst[len - 1] = '.';
                        } else {
                                /* NUL: end of current domain name */
                                if (retpos == 0) {
@@ -78,7 +77,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre)
                                        crtpos = retpos;
                                        retpos = depth = 0;
                                }
-                               if (dst)
+                               if (dst && len != 0)
+                                       /* \4host\3com\0\4host and we are at \0:
+                                        * \3com was converted to "com.", change dot to space.
+                                        */
                                        dst[len - 1] = ' ';
                        }
 
@@ -228,6 +230,9 @@ int main(int argc, char **argv)
        int len;
        uint8_t *encoded;
 
+        uint8_t str[6] = { 0x00, 0x00, 0x02, 0x65, 0x65, 0x00 };
+        printf("NUL:'%s'\n",   dname_dec(str, 6, ""));
+
 #define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre))
        printf("'%s'\n",       DNAME_DEC("\4host\3com\0", "test1:"));
        printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", ""));