Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -6955,6 +6955,76 @@ #define INIT_PROTOENT #endif +#if SANITIZER_INTERCEPT_NETENT +INTERCEPTOR(struct __sanitizer_netent *, getnetent) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getnetent); + struct __sanitizer_netent *n = REAL(getnetent)(); + if (n) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); + + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1); + + SIZE_T nn_size = 1; // One handles the trailing \0 + + for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1); + + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, + nn_size * sizeof(char **)); + } + return n; +} + +INTERCEPTOR(struct __sanitizer_netent *, getnetbyname, const char *name) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getnetbyname, name); + if (name) + COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); + struct __sanitizer_netent *n = REAL(getnetbyname)(name); + if (n) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); + + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1); + + SIZE_T nn_size = 1; // One handles the trailing \0 + + for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1); + + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, + nn_size * sizeof(char **)); + } + return n; +} + +INTERCEPTOR(struct __sanitizer_netent *, getnetbyaddr, u32 net, int type) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, getnetbyaddr, net, type); + struct __sanitizer_netent *n = REAL(getnetbyaddr)(net, type); + if (n) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); + + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_name, REAL(strlen)(n->n_name) + 1); + + SIZE_T nn_size = 1; // One handles the trailing \0 + + for (char **nn = n->n_aliases; *nn; ++nn, ++nn_size) + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *nn, REAL(strlen)(*nn) + 1); + + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n->n_aliases, + nn_size * sizeof(char **)); + } + return n; +} +#define INIT_NETENT \ + COMMON_INTERCEPT_FUNCTION(getnetent); \ + COMMON_INTERCEPT_FUNCTION(getnetbyname); \ + COMMON_INTERCEPT_FUNCTION(getnetbyaddr) +#else +#define INIT_NETENT +#endif + static void InitializeCommonInterceptors() { static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1]; interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap(); @@ -7187,6 +7257,7 @@ INIT_STRMODE; INIT_TTYENT; INIT_PROTOENT; + INIT_NETENT; #if SANITIZER_NETBSD COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock); Index: lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_interceptors.h +++ lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -463,5 +463,6 @@ #define SANITIZER_INTERCEPT_STRMODE SI_NETBSD #define SANITIZER_INTERCEPT_TTYENT SI_NETBSD #define SANITIZER_INTERCEPT_PROTOENT SI_NETBSD +#define SANITIZER_INTERCEPT_NETENT SI_NETBSD #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H Index: lib/sanitizer_common/sanitizer_platform_limits_netbsd.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -119,6 +119,13 @@ int p_proto; }; +struct __sanitizer_netent { + char *n_name; + char **n_aliases; + int n_addrtype; + u32 n_net; +}; + extern unsigned struct_msqid_ds_sz; extern unsigned struct_mq_attr_sz; extern unsigned struct_timex_sz; Index: test/sanitizer_common/TestCases/NetBSD/netent.cc =================================================================== --- test/sanitizer_common/TestCases/NetBSD/netent.cc +++ test/sanitizer_common/TestCases/NetBSD/netent.cc @@ -0,0 +1,84 @@ +// RUN: %clangxx -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include + +#define STRING_OR_NULL(x) ((x) ? (x) : "null") + +void test1() { + struct netent *ntp = getnetent(); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +void test2() { + struct netent *ntp = getnetbyname("loopback"); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +void test3() { + struct netent *ntp = getnetbyaddr(127, 2); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +void test4() { + setnetent(1); + + struct netent *ntp = getnetent(); + + printf("%s ", ntp->n_name); + + for (char **cp = ntp->n_aliases; *cp != NULL; cp++) + printf("%s ", STRING_OR_NULL(*cp)); + + printf("%d ", ntp->n_addrtype); + printf("%" PRIu32 "\n", ntp->n_net); + + endnetent(); +} + +int main(void) { + printf("netent\n"); + + test1(); + test2(); + test3(); + test4(); + + // CHECK: netent + // CHECK: loopback 2 127 + // CHECK: loopback 2 127 + // CHECK: loopback 2 127 + // CHECK: loopback 2 127 + + return 0; +}