diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2014-05-14 12:32:40 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2014-05-14 12:32:40 +0000 |
commit | 99d3791a880c41a6ff0ba8f25ff90c48622eac2c (patch) | |
tree | d854e96b2b1dde6252b13073eda1bdbebd060515 | |
parent | 04e2f43756c8892cba747fd650588bdaee807b13 (diff) | |
download | bcm5719-llvm-99d3791a880c41a6ff0ba8f25ff90c48622eac2c.tar.gz bcm5719-llvm-99d3791a880c41a6ff0ba8f25ff90c48622eac2c.zip |
[sanitizer] Fix crash in getgrnam_r and similar interceptors.
When no matching record is found, getgrnam_r return 0 but sets result to NULL.
Should fix PR19734.
llvm-svn: 208773
-rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc | 16 | ||||
-rw-r--r-- | compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc | 19 |
2 files changed, 27 insertions, 8 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 9193c2586c6..999e0437d09 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -1071,7 +1071,7 @@ INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd, COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result); if (!res) { - unpoison_passwd(ctx, pwd); + if (result && *result) unpoison_passwd(ctx, *result); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -1083,7 +1083,7 @@ INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result); int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result); if (!res) { - unpoison_passwd(ctx, pwd); + if (result && *result) unpoison_passwd(ctx, *result); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -1096,7 +1096,7 @@ INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp, COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1); int res = REAL(getgrnam_r)(name, grp, buf, buflen, result); if (!res) { - unpoison_group(ctx, grp); + if (result && *result) unpoison_group(ctx, *result); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -1108,7 +1108,7 @@ INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result); int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result); if (!res) { - unpoison_group(ctx, grp); + if (result && *result) unpoison_group(ctx, *result); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result)); @@ -1174,7 +1174,7 @@ INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp); int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp); if (!res) { - unpoison_passwd(ctx, pwbuf); + if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); @@ -1186,7 +1186,7 @@ INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp); int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp); if (!res) { - unpoison_passwd(ctx, pwbuf); + if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); @@ -1198,7 +1198,7 @@ INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen, COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp); int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp); if (!res) { - unpoison_group(ctx, pwbuf); + if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); @@ -1210,7 +1210,7 @@ INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf, COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp); int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp); if (!res) { - unpoison_group(ctx, pwbuf); + if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp); COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen); } if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp)); diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc b/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc new file mode 100644 index 00000000000..a8b51d7a99c --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc @@ -0,0 +1,19 @@ +// Regression test for a crash in getpwnam_r and similar interceptors. +// RUN: %clangxx -O0 -g %s -o %t && %run %t + +#include <assert.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <sys/types.h> +#include <unistd.h> + +int main(void) { + struct passwd pwd; + struct passwd *pwdres; + char buf[10000]; + int res = getpwnam_r("no-such-user", &pwd, buf, sizeof(buf), &pwdres); + assert(res == 0); + assert(pwdres == 0); + return 0; +} |