[sanitizer] Move fread and fwrite interceptors to sanitizer_common

{M, T, E}San have fread and fwrite interceptors, let's move them to sanitizer_common to enable ASan checks as well.

Differential Revision: https://reviews.llvm.org/D31456

llvm-svn: 299061
This commit is contained in:
Maxim Ostapenko 2017-03-30 07:25:33 +00:00
parent 9e46396ecc
commit f29aec76dd
7 changed files with 104 additions and 40 deletions

View File

@ -304,20 +304,6 @@ INTERCEPTOR(int, unlink, char *path) {
return REAL(unlink)(path);
}
INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, f);
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size * nmemb);
return REAL(fread)(ptr, size, nmemb, f);
}
INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, f);
COMMON_INTERCEPTOR_READ_RANGE(ctx, p, size * nmemb);
return REAL(fwrite)(p, size, nmemb, f);
}
INTERCEPTOR(int, puts, const char *s) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, puts, s);

View File

@ -123,14 +123,6 @@ static void *AllocateFromLocalPool(uptr size_in_bytes) {
#define CHECK_UNPOISONED_STRING(x, n) \
CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
ENSURE_MSAN_INITED();
SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
if (res > 0)
__msan_unpoison(ptr, res *size);
return res;
}
#if !SANITIZER_FREEBSD
INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
void *file) {

View File

@ -888,6 +888,23 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
#define INIT_READ
#endif
#if SANITIZER_INTERCEPT_FREAD
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
// libc file streams can call user-supplied functions, see fopencookie.
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
// FIXME: under ASan the call below may write to freed memory and corrupt
// its metadata. See
// https://github.com/google/sanitizers/issues/321.
SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
return res;
}
#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
#else
#define INIT_FREAD
#endif
#if SANITIZER_INTERCEPT_PREAD
INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
void *ctx;
@ -988,6 +1005,20 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
#define INIT_WRITE
#endif
#if SANITIZER_INTERCEPT_FWRITE
INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
// libc file streams can call user-supplied functions, see fopencookie.
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
return res;
}
#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
#else
#define INIT_FWRITE
#endif
#if SANITIZER_INTERCEPT_PWRITE
INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
void *ctx;
@ -6142,12 +6173,14 @@ static void InitializeCommonInterceptors() {
INIT_MEMRCHR;
INIT_MEMMEM;
INIT_READ;
INIT_FREAD;
INIT_PREAD;
INIT_PREAD64;
INIT_READV;
INIT_PREADV;
INIT_PREADV64;
INIT_WRITE;
INIT_FWRITE;
INIT_PWRITE;
INIT_PWRITE64;
INIT_WRITEV;

View File

@ -104,6 +104,9 @@
#define SANITIZER_INTERCEPT_WRITE SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_PWRITE SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_FREAD SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_FWRITE SI_NOT_WINDOWS
#define SANITIZER_INTERCEPT_PREAD64 SI_LINUX_NOT_ANDROID
#define SANITIZER_INTERCEPT_PWRITE64 SI_LINUX_NOT_ANDROID

View File

@ -1648,24 +1648,6 @@ TSAN_INTERCEPTOR(void*, tmpfile64, int fake) {
#define TSAN_MAYBE_INTERCEPT_TMPFILE64
#endif
TSAN_INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
// libc file streams can call user-supplied functions, see fopencookie.
{
SCOPED_TSAN_INTERCEPTOR(fread, ptr, size, nmemb, f);
MemoryAccessRange(thr, pc, (uptr)ptr, size * nmemb, true);
}
return REAL(fread)(ptr, size, nmemb, f);
}
TSAN_INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
// libc file streams can call user-supplied functions, see fopencookie.
{
SCOPED_TSAN_INTERCEPTOR(fwrite, p, size, nmemb, f);
MemoryAccessRange(thr, pc, (uptr)p, size * nmemb, false);
}
return REAL(fwrite)(p, size, nmemb, f);
}
static void FlushStreams() {
// Flushing all the streams here may freeze the process if a child thread is
// performing file stream operations at the same time.

View File

@ -0,0 +1,34 @@
// RUN: %clangxx_asan -g %s -o %t
// RUN: not %t 2>&1 | FileCheck %s --check-prefix=CHECK-FWRITE
// RUN: not %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-FREAD
#include <stdio.h>
#include <stdlib.h>
int test_fread() {
FILE *f = fopen("/dev/zero", "r");
char buf[2];
fread(buf, sizeof(buf), 2, f); // BOOM
fclose(f);
return 0;
}
int test_fwrite() {
FILE *f = fopen("/dev/null", "w");
char buf[2];
fwrite(buf, sizeof(buf), 2, f); // BOOM
return fclose(f);
}
int main(int argc, char *argv[]) {
if (argc > 1)
test_fread();
else
test_fwrite();
return 0;
}
// CHECK-FREAD: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}}
// CHECK-FREAD: #{{.*}} in {{(wrap_|__interceptor_)?}}fread
// CHECK-FWRITE: {{.*ERROR: AddressSanitizer: stack-buffer-overflow}}
// CHECK-FWRITE: #{{.*}} in {{(wrap_|__interceptor_)?}}fwrite

View File

@ -0,0 +1,34 @@
// RUN: %clangxx_msan -g %s -o %t
// RUN: not %t 2>&1 | FileCheck %s
// RUN: %t 1
#include <stdio.h>
#include <stdlib.h>
int test_fread() {
FILE *f = fopen("/dev/zero", "r");
char c;
unsigned read = fread(&c, sizeof(c), 1, f);
fclose(f);
if (c == '1') // No error
return 1;
return 0;
}
int test_fwrite() {
FILE *f = fopen("/dev/null", "w");
char c;
if (fwrite(&c, sizeof(c), 1, f) != sizeof(c)) // BOOM
return 1;
return fclose(f);
}
int main(int argc, char *argv[]) {
if (argc > 1)
test_fread();
else
test_fwrite();
return 0;
}
// CHECK: Uninitialized bytes in __interceptor_fwrite at offset 0 inside