diff --git a/CHANGELOG b/CHANGELOG index 01ccaf7e..6493dea4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -80,6 +80,9 @@ HISTORY ++ Bugfixes: + 2013-01-14: Simon Goldschmidt + * dns.c: fixed bug #37705 Possible memory corruption in DNS query + 2013-01-11: Simon Goldschmidt * raw.c: fixed bug #38066 Raw pcbs can alter packet without eating it diff --git a/src/core/dns.c b/src/core/dns.c index 788df715..4e3a7dec 100644 --- a/src/core/dns.c +++ b/src/core/dns.c @@ -576,6 +576,7 @@ dns_send(u8_t numdns, const char* name, u8_t id) p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH + SIZEOF_DNS_QUERY, PBUF_RAM); if (p != NULL) { + u16_t realloc_size; LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); /* fill dns header */ hdr = (struct dns_hdr*)p->payload; @@ -607,7 +608,9 @@ dns_send(u8_t numdns, const char* name, u8_t id) SMEMCPY(query, &qry, SIZEOF_DNS_QUERY); /* resize pbuf to the exact dns query */ - pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)))); + realloc_size = (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))); + LWIP_ASSERT("p->tot_len >= realloc_size", p->tot_len >= realloc_size); + pbuf_realloc(p, realloc_size); /* connect to the server for faster receiving */ udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT); @@ -860,12 +863,14 @@ memerr: * Queues a new hostname to resolve and sends out a DNS query for that hostname * * @param name the hostname that is to be queried + * @param hostnamelen length of the hostname * @param found a callback founction to be called on success, failure or timeout * @param callback_arg argument to pass to the callback function * @return @return a err_t return code. */ static err_t -dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) +dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, + void *callback_arg) { u8_t i; u8_t lseq, lseqi; @@ -910,7 +915,7 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) pEntry->seqno = dns_seqno++; pEntry->found = found; pEntry->arg = callback_arg; - namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1); + namelen = LWIP_MIN(hostnamelen, DNS_MAX_NAME_LENGTH-1); MEMCPY(pEntry->name, name, namelen); pEntry->name[namelen] = 0; @@ -945,13 +950,18 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun void *callback_arg) { u32_t ipaddr; + size_t hostnamelen; /* not initialized or no valid server yet, or invalid addr pointer * or invalid hostname or invalid hostname length */ if ((dns_pcb == NULL) || (addr == NULL) || - (!hostname) || (!hostname[0]) || - (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { + (!hostname) || (!hostname[0])) { return ERR_ARG; } + hostnamelen = strlen(hostname); + if (hostnamelen >= DNS_MAX_NAME_LENGTH) { + return ERR_ARG; + } + #if LWIP_HAVE_LOOPIF if (strcmp(hostname, "localhost")==0) { @@ -972,7 +982,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun } /* queue query with specified callback */ - return dns_enqueue(hostname, found, callback_arg); + return dns_enqueue(hostname, hostnamelen, found, callback_arg); } #endif /* LWIP_DNS */