fix(netdb): Out of bounds in gethostbyaddr and less transmutes
-
gethostbyaddr
panics when resolving an address without a hostname, such as a private address.glibc
setserrno
andmusl
copies the address to use as a host name instead. - Some of the transmutes (
[u8; 4] -> u32
and back) can be replaced with standard library functions. - Lastly, user provided strings may not be valid UTF8 or may be null.
CStr::from_ptr
shouldn't be used with non-null pointers.str::from_utf8_unchecked
should only be used with UTF8 strings (e.g. strings we produce rather than unknown user strings).
Code to test:
#include <assert.h>
#include <netdb.h>
#include <stdint.h>
#include <string.h>
#define ADDR_SIZE sizeof(uint8_t) * 4
int main(void) {
const uint8_t private[] = {169, 254, 0, 1};
// Relibc panics here
struct hostent *private_host = gethostbyaddr(private, ADDR_SIZE, AF_INET);
assert(!private_host);
const uint8_t cloudflare[] = {1, 1, 1, 1};
struct hostent *cloudflare_host =
gethostbyaddr(cloudflare, ADDR_SIZE, AF_INET);
assert(cloudflare_host);
const char expected[] = "one.one.one.one";
assert(strcmp(expected, cloudflare_host->h_name) == 0);
const uint8_t localhost[] = {127, 0, 0, 1};
struct hostent *localhost_host = gethostbyaddr(localhost, ADDR_SIZE, AF_INET);
assert(localhost_host);
return 0;
}
Edited by Josh Megnauth