forked from OSchip/llvm-project
[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:
parent
9e46396ecc
commit
f29aec76dd
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue