summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2014-05-14 12:32:40 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2014-05-14 12:32:40 +0000
commit99d3791a880c41a6ff0ba8f25ff90c48622eac2c (patch)
treed854e96b2b1dde6252b13073eda1bdbebd060515
parent04e2f43756c8892cba747fd650588bdaee807b13 (diff)
downloadbcm5719-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.inc16
-rw-r--r--compiler-rt/test/sanitizer_common/TestCases/Linux/getpwnam_r_invalid_user.cc19
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;
+}
OpenPOWER on IntegriCloud