forked from OSchip/llvm-project
241 lines
9.2 KiB
C++
241 lines
9.2 KiB
C++
//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Common function interceptors for tools like AddressSanitizer,
|
|
// ThreadSanitizer, MemorySanitizer, etc.
|
|
//
|
|
// This file should be included into the tool's interceptor file,
|
|
// which has to define it's own macros:
|
|
// COMMON_INTERCEPTOR_ENTER
|
|
// COMMON_INTERCEPTOR_READ_RANGE
|
|
// COMMON_INTERCEPTOR_WRITE_RANGE
|
|
// COMMON_INTERCEPTOR_FD_ACQUIRE
|
|
// COMMON_INTERCEPTOR_FD_RELEASE
|
|
// COMMON_INTERCEPTOR_SET_THREAD_NAME
|
|
//===----------------------------------------------------------------------===//
|
|
#include "interception/interception.h"
|
|
#include "sanitizer_platform_interceptors.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#ifdef _WIN32
|
|
#define va_copy(dst, src) ((dst) = (src))
|
|
#endif // _WIN32
|
|
|
|
#if SANITIZER_INTERCEPT_READ
|
|
INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
|
|
SSIZE_T res = REAL(read)(fd, ptr, count);
|
|
if (res > 0)
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
|
|
if (res >= 0 && fd >= 0)
|
|
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
return res;
|
|
}
|
|
#define INIT_READ INTERCEPT_FUNCTION(read)
|
|
#else
|
|
#define INIT_READ
|
|
#endif
|
|
|
|
#if SANITIZER_INTERCEPT_PREAD
|
|
INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
|
|
SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
|
|
if (res > 0)
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
|
|
if (res >= 0 && fd >= 0)
|
|
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
return res;
|
|
}
|
|
#define INIT_PREAD INTERCEPT_FUNCTION(pread)
|
|
#else
|
|
#define INIT_PREAD
|
|
#endif
|
|
|
|
#if SANITIZER_INTERCEPT_PREAD64
|
|
INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
|
|
SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
|
|
if (res > 0)
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
|
|
if (res >= 0 && fd >= 0)
|
|
COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
return res;
|
|
}
|
|
#define INIT_PREAD64 INTERCEPT_FUNCTION(pread64)
|
|
#else
|
|
#define INIT_PREAD64
|
|
#endif
|
|
|
|
#if SANITIZER_INTERCEPT_WRITE
|
|
INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
|
|
if (fd >= 0)
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
SSIZE_T res = REAL(write)(fd, ptr, count);
|
|
if (res > 0)
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
|
|
return res;
|
|
}
|
|
#define INIT_WRITE INTERCEPT_FUNCTION(write)
|
|
#else
|
|
#define INIT_WRITE
|
|
#endif
|
|
|
|
#if SANITIZER_INTERCEPT_PWRITE
|
|
INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
|
|
if (fd >= 0)
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
|
|
if (res > 0)
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
|
|
return res;
|
|
}
|
|
#define INIT_PWRITE INTERCEPT_FUNCTION(pwrite)
|
|
#else
|
|
#define INIT_PWRITE
|
|
#endif
|
|
|
|
#if SANITIZER_INTERCEPT_PWRITE64
|
|
INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
|
|
OFF64_T offset) {
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
|
|
if (fd >= 0)
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
|
|
if (res > 0)
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
|
|
return res;
|
|
}
|
|
#define INIT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
|
|
#else
|
|
#define INIT_PWRITE64
|
|
#endif
|
|
|
|
#if SANITIZER_INTERCEPT_PRCTL
|
|
INTERCEPTOR(int, prctl, int option, unsigned long arg2,
|
|
unsigned long arg3, // NOLINT
|
|
unsigned long arg4, unsigned long arg5) { // NOLINT
|
|
void *ctx;
|
|
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
|
|
static const int PR_SET_NAME = 15;
|
|
int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
|
|
if (option == PR_SET_NAME) {
|
|
char buff[16];
|
|
internal_strncpy(buff, (char *)arg2, 15);
|
|
buff[15] = 0;
|
|
COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
|
|
}
|
|
return res;
|
|
}
|
|
#define INIT_PRCTL INTERCEPT_FUNCTION(prctl)
|
|
#else
|
|
#define INIT_PRCTL
|
|
#endif // SANITIZER_INTERCEPT_PRCTL
|
|
|
|
#if SANITIZER_INTERCEPT_SCANF
|
|
|
|
#include "sanitizer_common_interceptors_scanf.inc"
|
|
|
|
#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \
|
|
{ \
|
|
void *ctx; \
|
|
COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
|
|
va_list aq; \
|
|
va_copy(aq, ap); \
|
|
int res = REAL(vname)(__VA_ARGS__); \
|
|
if (res > 0) \
|
|
scanf_common(ctx, res, allowGnuMalloc, format, aq); \
|
|
va_end(aq); \
|
|
return res; \
|
|
}
|
|
|
|
INTERCEPTOR(int, vscanf, const char *format, va_list ap)
|
|
VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
|
|
|
|
INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
|
|
VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
|
|
|
|
INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
|
|
VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
|
|
|
|
INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
|
|
VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
|
|
|
|
INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
|
|
va_list ap)
|
|
VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
|
|
|
|
INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
|
|
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
|
|
|
|
#define SCANF_INTERCEPTOR_IMPL(name, vname, ...) \
|
|
{ \
|
|
void *ctx; \
|
|
COMMON_INTERCEPTOR_ENTER(ctx, name, __VA_ARGS__); \
|
|
va_list ap; \
|
|
va_start(ap, format); \
|
|
int res = vname(__VA_ARGS__, ap); \
|
|
va_end(ap); \
|
|
return res; \
|
|
}
|
|
|
|
INTERCEPTOR(int, scanf, const char *format, ...)
|
|
SCANF_INTERCEPTOR_IMPL(scanf, vscanf, format)
|
|
|
|
INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
|
|
SCANF_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
|
|
|
|
INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
|
|
SCANF_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
|
|
|
|
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
|
|
SCANF_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
|
|
|
|
INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
|
|
SCANF_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
|
|
|
|
INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
|
|
SCANF_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
|
|
|
|
#define INIT_SCANF \
|
|
INTERCEPT_FUNCTION(scanf); \
|
|
INTERCEPT_FUNCTION(sscanf); \
|
|
INTERCEPT_FUNCTION(fscanf); \
|
|
INTERCEPT_FUNCTION(vscanf); \
|
|
INTERCEPT_FUNCTION(vsscanf); \
|
|
INTERCEPT_FUNCTION(vfscanf); \
|
|
INTERCEPT_FUNCTION(__isoc99_scanf); \
|
|
INTERCEPT_FUNCTION(__isoc99_sscanf); \
|
|
INTERCEPT_FUNCTION(__isoc99_fscanf); \
|
|
INTERCEPT_FUNCTION(__isoc99_vscanf); \
|
|
INTERCEPT_FUNCTION(__isoc99_vsscanf); \
|
|
INTERCEPT_FUNCTION(__isoc99_vfscanf);
|
|
|
|
#else
|
|
#define INIT_SCANF
|
|
#endif
|
|
|
|
#define SANITIZER_COMMON_INTERCEPTORS_INIT \
|
|
INIT_READ; \
|
|
INIT_PREAD; \
|
|
INIT_PREAD64; \
|
|
INIT_PRCTL; \
|
|
INIT_WRITE; \
|
|
INIT_PWRITE; \
|
|
INIT_PWRITE64; \
|
|
INIT_SCANF;
|