forked from OSchip/llvm-project
[sanitizer] Interceptors for gethostbyname and friends.
llvm-svn: 182573
This commit is contained in:
parent
5c24cca0f0
commit
ab25369d04
|
@ -127,6 +127,7 @@ set(SANITIZER_COMMON_CFLAGS
|
|||
-fomit-frame-pointer
|
||||
-funwind-tables
|
||||
-fno-stack-protector
|
||||
-Wno-gnu # Variadic macros with 0 arguments for ...
|
||||
-O3
|
||||
)
|
||||
if(NOT WIN32)
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
# include <emmintrin.h>
|
||||
|
@ -651,6 +652,108 @@ TEST(MemorySanitizer, bind_getsockname) {
|
|||
close(sock);
|
||||
}
|
||||
|
||||
#define EXPECT_HOSTENT_NOT_POISONED(he) \
|
||||
do { \
|
||||
EXPECT_NOT_POISONED(*(he)); \
|
||||
ASSERT_NE((void *) 0, (he)->h_name); \
|
||||
ASSERT_NE((void *) 0, (he)->h_aliases); \
|
||||
ASSERT_NE((void *) 0, (he)->h_addr_list); \
|
||||
EXPECT_NOT_POISONED(strlen((he)->h_name)); \
|
||||
char **p = (he)->h_aliases; \
|
||||
while (*p) { \
|
||||
EXPECT_NOT_POISONED(strlen(*p)); \
|
||||
++p; \
|
||||
} \
|
||||
char **q = (he)->h_addr_list; \
|
||||
while (*q) { \
|
||||
EXPECT_NOT_POISONED(*q[0]); \
|
||||
++q; \
|
||||
} \
|
||||
EXPECT_NOT_POISONED(*q); \
|
||||
} while (0)
|
||||
|
||||
TEST(MemorySanitizer, gethostent) {
|
||||
struct hostent *he = gethostent();
|
||||
ASSERT_NE((void *)NULL, he);
|
||||
EXPECT_HOSTENT_NOT_POISONED(he);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostbyname) {
|
||||
struct hostent *he = gethostbyname("localhost");
|
||||
ASSERT_NE((void *)NULL, he);
|
||||
EXPECT_HOSTENT_NOT_POISONED(he);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostbyname2) {
|
||||
struct hostent *he = gethostbyname2("localhost", AF_INET);
|
||||
ASSERT_NE((void *)NULL, he);
|
||||
EXPECT_HOSTENT_NOT_POISONED(he);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostbyaddr) {
|
||||
in_addr_t addr = inet_addr("127.0.0.1");
|
||||
EXPECT_NOT_POISONED(addr);
|
||||
struct hostent *he = gethostbyaddr(&addr, sizeof(addr), AF_INET);
|
||||
ASSERT_NE((void *)NULL, he);
|
||||
EXPECT_HOSTENT_NOT_POISONED(he);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostent_r) {
|
||||
char buf[2000];
|
||||
struct hostent he;
|
||||
struct hostent *result;
|
||||
int err;
|
||||
int res = gethostent_r(&he, buf, sizeof(buf), &result, &err);
|
||||
ASSERT_EQ(0, res);
|
||||
EXPECT_NOT_POISONED(result);
|
||||
ASSERT_NE((void *)NULL, result);
|
||||
EXPECT_HOSTENT_NOT_POISONED(result);
|
||||
EXPECT_NOT_POISONED(err);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostbyname_r) {
|
||||
char buf[2000];
|
||||
struct hostent he;
|
||||
struct hostent *result;
|
||||
int err;
|
||||
int res = gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err);
|
||||
ASSERT_EQ(0, res);
|
||||
EXPECT_NOT_POISONED(result);
|
||||
ASSERT_NE((void *)NULL, result);
|
||||
EXPECT_HOSTENT_NOT_POISONED(result);
|
||||
EXPECT_NOT_POISONED(err);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostbyname2_r) {
|
||||
char buf[2000];
|
||||
struct hostent he;
|
||||
struct hostent *result;
|
||||
int err;
|
||||
int res = gethostbyname2_r("localhost", AF_INET, &he, buf, sizeof(buf),
|
||||
&result, &err);
|
||||
ASSERT_EQ(0, res);
|
||||
EXPECT_NOT_POISONED(result);
|
||||
ASSERT_NE((void *)NULL, result);
|
||||
EXPECT_HOSTENT_NOT_POISONED(result);
|
||||
EXPECT_NOT_POISONED(err);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, gethostbyaddr_r) {
|
||||
char buf[2000];
|
||||
struct hostent he;
|
||||
struct hostent *result;
|
||||
int err;
|
||||
in_addr_t addr = inet_addr("127.0.0.1");
|
||||
EXPECT_NOT_POISONED(addr);
|
||||
int res = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &he, buf, sizeof(buf),
|
||||
&result, &err);
|
||||
ASSERT_EQ(0, res);
|
||||
EXPECT_NOT_POISONED(result);
|
||||
ASSERT_NE((void *)NULL, result);
|
||||
EXPECT_HOSTENT_NOT_POISONED(result);
|
||||
EXPECT_NOT_POISONED(err);
|
||||
}
|
||||
|
||||
TEST(MemorySanitizer, getcwd) {
|
||||
char path[PATH_MAX + 1];
|
||||
char* res = getcwd(path, sizeof(path));
|
||||
|
|
|
@ -796,6 +796,152 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
|
|||
#define INIT_GETSOCKNAME
|
||||
#endif
|
||||
|
||||
static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
|
||||
if (h->h_name)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
|
||||
char **p = h->h_aliases;
|
||||
while (*p) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
|
||||
++p;
|
||||
}
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(
|
||||
ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
|
||||
p = h->h_addr_list;
|
||||
while (*p) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
|
||||
++p;
|
||||
}
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(
|
||||
ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
|
||||
}
|
||||
|
||||
#if SANITIZER_INTERCEPT_GETHOSTBYNAME
|
||||
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
|
||||
struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
|
||||
if (res) write_hostent(ctx, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
|
||||
int type) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
|
||||
struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
|
||||
if (res) write_hostent(ctx, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(struct __sanitizer_hostent *, gethostent) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostent);
|
||||
struct __sanitizer_hostent *res = REAL(gethostent)();
|
||||
if (res) write_hostent(ctx, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
|
||||
struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
|
||||
if (res) write_hostent(ctx, res);
|
||||
return res;
|
||||
}
|
||||
#define INIT_GETHOSTBYNAME \
|
||||
INTERCEPT_FUNCTION(gethostent); \
|
||||
INTERCEPT_FUNCTION(gethostbyaddr); \
|
||||
INTERCEPT_FUNCTION(gethostbyname); \
|
||||
INTERCEPT_FUNCTION(gethostbyname2);
|
||||
#else
|
||||
#define INIT_GETHOSTBYNAME
|
||||
#endif
|
||||
|
||||
#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
|
||||
INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
|
||||
SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
|
||||
h_errnop);
|
||||
int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
|
||||
if (res == 0) {
|
||||
if (result) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
||||
if (*result) write_hostent(ctx, *result);
|
||||
}
|
||||
if (h_errnop)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
|
||||
struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
|
||||
__sanitizer_hostent **result, int *h_errnop) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
|
||||
buflen, result, h_errnop);
|
||||
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
|
||||
int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
|
||||
h_errnop);
|
||||
if (res == 0) {
|
||||
if (result) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
||||
if (*result) write_hostent(ctx, *result);
|
||||
}
|
||||
if (h_errnop)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
|
||||
char *buf, SIZE_T buflen, __sanitizer_hostent **result,
|
||||
int *h_errnop) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
|
||||
h_errnop);
|
||||
int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
|
||||
if (res == 0) {
|
||||
if (result) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
||||
if (*result) write_hostent(ctx, *result);
|
||||
}
|
||||
if (h_errnop)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
|
||||
struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
|
||||
__sanitizer_hostent **result, int *h_errnop) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
|
||||
result, h_errnop);
|
||||
int res =
|
||||
REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
|
||||
if (res == 0) {
|
||||
if (result) {
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
||||
if (*result) write_hostent(ctx, *result);
|
||||
}
|
||||
if (h_errnop)
|
||||
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#define INIT_GETHOSTBYNAME_R \
|
||||
INTERCEPT_FUNCTION(gethostent_r); \
|
||||
INTERCEPT_FUNCTION(gethostbyaddr_r); \
|
||||
INTERCEPT_FUNCTION(gethostbyname_r); \
|
||||
INTERCEPT_FUNCTION(gethostbyname2_r);
|
||||
#else
|
||||
#define INIT_GETHOSTBYNAME_R
|
||||
#endif
|
||||
|
||||
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
|
||||
INIT_STRCASECMP; \
|
||||
INIT_STRNCASECMP; \
|
||||
|
@ -820,4 +966,6 @@ INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
|
|||
INIT_INET; \
|
||||
INIT_PTHREAD_GETSCHEDPARAM; \
|
||||
INIT_GETADDRINFO; \
|
||||
INIT_GETSOCKNAME;
|
||||
INIT_GETSOCKNAME; \
|
||||
INIT_GETHOSTBYNAME; \
|
||||
INIT_GETHOSTBYNAME_R;
|
||||
|
|
|
@ -72,5 +72,7 @@
|
|||
# define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_GETSOCKNAME SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_GETHOSTBYNAME SI_NOT_WINDOWS
|
||||
# define SANITIZER_INTERCEPT_GETHOSTBYNAME_R SI_LINUX
|
||||
|
||||
#endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H
|
||||
|
|
|
@ -144,4 +144,12 @@ COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_canonname) ==
|
|||
COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_next) ==
|
||||
offsetof(struct addrinfo, ai_next));
|
||||
|
||||
COMPILER_CHECK(sizeof(struct __sanitizer_hostent) == sizeof(struct hostent));
|
||||
COMPILER_CHECK(offsetof(struct __sanitizer_hostent, h_name) ==
|
||||
offsetof(struct hostent, h_name));
|
||||
COMPILER_CHECK(offsetof(struct __sanitizer_hostent, h_aliases) ==
|
||||
offsetof(struct hostent, h_aliases));
|
||||
COMPILER_CHECK(offsetof(struct __sanitizer_hostent, h_addr_list) ==
|
||||
offsetof(struct hostent, h_addr_list));
|
||||
|
||||
#endif // SANITIZER_LINUX || SANITIZER_MAC
|
||||
|
|
|
@ -101,6 +101,15 @@ namespace __sanitizer {
|
|||
#endif
|
||||
struct __sanitizer_addrinfo *ai_next;
|
||||
};
|
||||
|
||||
struct __sanitizer_hostent {
|
||||
char *h_name;
|
||||
char **h_aliases;
|
||||
int h_addrtype;
|
||||
int h_length;
|
||||
char **h_addr_list;
|
||||
};
|
||||
|
||||
} // namespace __sanitizer
|
||||
|
||||
#endif
|
||||
|
|
|
@ -313,6 +313,14 @@ void StatOutput(u64 *stat) {
|
|||
name[StatInt_inet_pton] = " inet_pton ";
|
||||
name[StatInt_getaddrinfo] = " getaddrinfo ";
|
||||
name[StatInt_getsockname] = " getsockname ";
|
||||
name[StatInt_gethostent] = " gethostent ";
|
||||
name[StatInt_gethostbyname] = " gethostbyname ";
|
||||
name[StatInt_gethostbyname2] = " gethostbyname2 ";
|
||||
name[StatInt_gethostbyaddr] = " gethostbyaddr ";
|
||||
name[StatInt_gethostent_r] = " gethostent_r ";
|
||||
name[StatInt_gethostbyname_r] = " gethostbyname_r ";
|
||||
name[StatInt_gethostbyname2_r] = " gethostbyname2_r ";
|
||||
name[StatInt_gethostbyaddr_r] = " gethostbyaddr_r ";
|
||||
|
||||
name[StatAnnotation] = "Dynamic annotations ";
|
||||
name[StatAnnotateHappensBefore] = " HappensBefore ";
|
||||
|
|
|
@ -308,6 +308,14 @@ enum StatType {
|
|||
StatInt_inet_pton,
|
||||
StatInt_getaddrinfo,
|
||||
StatInt_getsockname,
|
||||
StatInt_gethostent,
|
||||
StatInt_gethostbyname,
|
||||
StatInt_gethostbyname2,
|
||||
StatInt_gethostbyaddr,
|
||||
StatInt_gethostent_r,
|
||||
StatInt_gethostbyname_r,
|
||||
StatInt_gethostbyname2_r,
|
||||
StatInt_gethostbyaddr_r,
|
||||
|
||||
// Dynamic annotations.
|
||||
StatAnnotation,
|
||||
|
|
Loading…
Reference in New Issue