[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
This commit is contained in:
		
							parent
							
								
									04e2f43756
								
							
						
					
					
						commit
						99d3791a88
					
				| 
						 | 
					@ -1071,7 +1071,7 @@ INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
 | 
				
			||||||
  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
 | 
					  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
 | 
				
			||||||
  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
 | 
					  int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_passwd(ctx, pwd);
 | 
					    if (result && *result) unpoison_passwd(ctx, *result);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
 | 
				
			||||||
  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
 | 
					  int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_passwd(ctx, pwd);
 | 
					    if (result && *result) unpoison_passwd(ctx, *result);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
 | 
				
			||||||
  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
 | 
					  int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_group(ctx, grp);
 | 
					    if (result && *result) unpoison_group(ctx, *result);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
 | 
				
			||||||
  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
 | 
					  int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_group(ctx, grp);
 | 
					    if (result && *result) unpoison_group(ctx, *result);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
 | 
					  int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_passwd(ctx, pwbuf);
 | 
					    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
 | 
					  int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_passwd(ctx, pwbuf);
 | 
					    if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
 | 
					  int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_group(ctx, pwbuf);
 | 
					    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
 | 
					  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);
 | 
					  COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
 | 
					  int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
 | 
				
			||||||
  if (!res) {
 | 
					  if (!res) {
 | 
				
			||||||
    unpoison_group(ctx, pwbuf);
 | 
					    if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
 | 
				
			||||||
    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
					    COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
 | 
					  if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue