diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-03-10 11:47:58 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-03-10 11:47:58 +0100 |
commit | d474ffc68290e0a83651c4432eeabfa62cd51e87 (patch) | |
tree | e2ac94fcab17bdf31bd70de2e92bce79eabfa21f | |
parent | d2b820b540ada43dfef8751328c158e342387304 (diff) | |
download | busybox-w32-d474ffc68290e0a83651c4432eeabfa62cd51e87.tar.gz busybox-w32-d474ffc68290e0a83651c4432eeabfa62cd51e87.tar.bz2 busybox-w32-d474ffc68290e0a83651c4432eeabfa62cd51e87.zip |
udhcp: fix a SEGV on malformed RFC1035-encoded domain name
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/udhcp/domain_codec.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/networking/udhcp/domain_codec.c b/networking/udhcp/domain_codec.c index 05cdf51e9..cee31f14d 100644 --- a/networking/udhcp/domain_codec.c +++ b/networking/udhcp/domain_codec.c | |||
@@ -63,11 +63,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) | |||
63 | if (crtpos + *c + 1 > clen) /* label too long? abort */ | 63 | if (crtpos + *c + 1 > clen) /* label too long? abort */ |
64 | return NULL; | 64 | return NULL; |
65 | if (dst) | 65 | if (dst) |
66 | memcpy(dst + len, c + 1, *c); | 66 | /* \3com ---> "com." */ |
67 | ((char*)mempcpy(dst + len, c + 1, *c))[0] = '.'; | ||
67 | len += *c + 1; | 68 | len += *c + 1; |
68 | crtpos += *c + 1; | 69 | crtpos += *c + 1; |
69 | if (dst) | ||
70 | dst[len - 1] = '.'; | ||
71 | } else { | 70 | } else { |
72 | /* NUL: end of current domain name */ | 71 | /* NUL: end of current domain name */ |
73 | if (retpos == 0) { | 72 | if (retpos == 0) { |
@@ -78,7 +77,10 @@ char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) | |||
78 | crtpos = retpos; | 77 | crtpos = retpos; |
79 | retpos = depth = 0; | 78 | retpos = depth = 0; |
80 | } | 79 | } |
81 | if (dst) | 80 | if (dst && len != 0) |
81 | /* \4host\3com\0\4host and we are at \0: | ||
82 | * \3com was converted to "com.", change dot to space. | ||
83 | */ | ||
82 | dst[len - 1] = ' '; | 84 | dst[len - 1] = ' '; |
83 | } | 85 | } |
84 | 86 | ||
@@ -227,6 +229,9 @@ int main(int argc, char **argv) | |||
227 | int len; | 229 | int len; |
228 | uint8_t *encoded; | 230 | uint8_t *encoded; |
229 | 231 | ||
232 | uint8_t str[6] = { 0x00, 0x00, 0x02, 0x65, 0x65, 0x00 }; | ||
233 | printf("NUL:'%s'\n", dname_dec(str, 6, "")); | ||
234 | |||
230 | #define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre)) | 235 | #define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre)) |
231 | printf("'%s'\n", DNAME_DEC("\4host\3com\0", "test1:")); | 236 | printf("'%s'\n", DNAME_DEC("\4host\3com\0", "test1:")); |
232 | printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", "")); | 237 | printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", "")); |