summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2020-07-07 19:48:32 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2020-07-07 19:48:32 +0000
commitb278a44990ed89c4d28df42012fe81707d93be90 (patch)
treef3f7b62d3a6084765c6df678966b505a434f7101
parent8b4954dc0d81b64e58bf217e2aad0364d09ed92d (diff)
Revert r1.121 and rewrite merge_option_data() to achieve same effect
w/o using string functions on data that *MIGHT NOT* be NUL terminated. Fiddle parse_domain_name_list() to avoid string functions for the same reason. Problem encountered by Jesper Wallin when running with vm.malloc_conf=CFGJUR, although he later proved 'J' (more junking) was the actual trouble maker.
-rw-r--r--sbin/dhclient/options.c57
1 files changed, 28 insertions, 29 deletions
diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c
index 3c37bdb1024..84b76e1730c 100644
--- a/sbin/dhclient/options.c
+++ b/sbin/dhclient/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.122 2020/05/21 01:07:52 krw Exp $ */
+/* $OpenBSD: options.c,v 1.123 2020/07/07 19:48:31 krw Exp $ */
/* DHCP options parsing and reassembly. */
@@ -671,13 +671,19 @@ pretty_print_domain_list(unsigned char *src, size_t srclen,
memset(buf, 0, buflen);
- if (srclen >= DHCP_DOMAIN_SEARCH_LEN || strlen(src) == 0 ||
- strlen(src) > DHCP_DOMAIN_SEARCH_LEN)
+ /*
+ * N.B.: option data is *NOT* guaranteed to be NUL
+ * terminated. Avoid strlen(), strdup(), etc.!
+ */
+ if (srclen >= DHCP_DOMAIN_SEARCH_LEN || src[0] == '\0')
return;
- dupnames = inputstring = strdup(src);
+ inputstring = malloc(srclen + 1);
if (inputstring == NULL)
fatal("domain name list");
+ memcpy(inputstring, src, srclen);
+ inputstring[srclen] = '\0';
+ dupnames = inputstring;
count = 0;
while ((hn = strsep(&inputstring, " \t")) != NULL) {
@@ -966,7 +972,7 @@ void
merge_option_data(char *fmt, struct option_data *first,
struct option_data *second, struct option_data *dest)
{
- int rslt;
+ int space = 0;
free(dest->data);
dest->data = NULL;
@@ -974,29 +980,22 @@ merge_option_data(char *fmt, struct option_data *first,
if (dest->len == 0)
return;
- switch (fmt[0]) {
- case 'D':
- rslt = asprintf((char **)&dest->data, "%s%s%s",
- (first->len > 0) ? (char *)first->data : "",
- (first->len > 0 && second->len > 0) ? " " : "",
- (second->len > 0) ? (char *)second->data : "");
- if (rslt == -1)
- fatal("merged 'D'");
- dest->len = strlen(dest->data);
- break;
- case 't':
- rslt = asprintf((char **)&dest->data, "%s%s",
- (first->len > 0) ? (char *)first->data : "",
- (second->len > 0) ? (char *)second->data : "");
- if (rslt == -1)
- fatal("merged 't'");
- break;
- default:
- dest->data = calloc(1, dest->len);
- if (dest->data == NULL)
- fatal("merged option data");
- memcpy(dest->data, first->data, first->len);
- memcpy(dest->data + first->len, second->data, second->len);
- break;
+ /*
+ * N.B.: option data is *NOT* guaranteed to be NUL
+ * terminated. Avoid strlen(), strdup(), etc.!
+ */
+ if (fmt[0] == 'D') {
+ if (first->len > 0 && second->len > 0)
+ space = 1;
}
+
+ dest->len += space;
+ dest->data = malloc(dest->len);
+ if (dest->data == NULL)
+ fatal("merged option data");
+
+ memcpy(dest->data, first->data, first->len);
+ if (space == 1)
+ dest->data[first->len] = ' ';
+ memcpy(dest->data + first->len + space, second->data, second->len);
}