Skip to content

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 sets errno and musl 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

Merge request reports