Path: blob/main/contrib/llvm-project/compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp
35262 views
//===-- FuzzerInterceptors.cpp --------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7// Intercept certain libc functions to aid fuzzing.8// Linked only when other RTs that define their own interceptors are not linked.9//===----------------------------------------------------------------------===//1011#include "FuzzerPlatform.h"1213#if LIBFUZZER_LINUX1415#define GET_CALLER_PC() __builtin_return_address(0)1617#define PTR_TO_REAL(x) real_##x18#define REAL(x) __interception::PTR_TO_REAL(x)19#define FUNC_TYPE(x) x##_type20#define DEFINE_REAL(ret_type, func, ...) \21typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \22namespace __interception { \23FUNC_TYPE(func) PTR_TO_REAL(func); \24}2526#include <cassert>27#include <cstddef> // for size_t28#include <cstdint>29#include <dlfcn.h> // for dlsym()3031static void *getFuncAddr(const char *name, uintptr_t wrapper_addr) {32void *addr = dlsym(RTLD_NEXT, name);33if (!addr) {34// If the lookup using RTLD_NEXT failed, the sanitizer runtime library is35// later in the library search order than the DSO that we are trying to36// intercept, which means that we cannot intercept this function. We still37// want the address of the real definition, though, so look it up using38// RTLD_DEFAULT.39addr = dlsym(RTLD_DEFAULT, name);4041// In case `name' is not loaded, dlsym ends up finding the actual wrapper.42// We don't want to intercept the wrapper and have it point to itself.43if (reinterpret_cast<uintptr_t>(addr) == wrapper_addr)44addr = nullptr;45}46return addr;47}4849static int FuzzerInited = 0;50static bool FuzzerInitIsRunning;5152static void fuzzerInit();5354static void ensureFuzzerInited() {55assert(!FuzzerInitIsRunning);56if (!FuzzerInited) {57fuzzerInit();58}59}6061static int internal_strcmp_strncmp(const char *s1, const char *s2, bool strncmp,62size_t n) {63size_t i = 0;64while (true) {65if (strncmp) {66if (i == n)67break;68i++;69}70unsigned c1 = *s1;71unsigned c2 = *s2;72if (c1 != c2)73return (c1 < c2) ? -1 : 1;74if (c1 == 0)75break;76s1++;77s2++;78}79return 0;80}8182static int internal_strncmp(const char *s1, const char *s2, size_t n) {83return internal_strcmp_strncmp(s1, s2, true, n);84}8586static int internal_strcmp(const char *s1, const char *s2) {87return internal_strcmp_strncmp(s1, s2, false, 0);88}8990static int internal_memcmp(const void *s1, const void *s2, size_t n) {91const uint8_t *t1 = static_cast<const uint8_t *>(s1);92const uint8_t *t2 = static_cast<const uint8_t *>(s2);93for (size_t i = 0; i < n; ++i, ++t1, ++t2)94if (*t1 != *t2)95return *t1 < *t2 ? -1 : 1;96return 0;97}9899static size_t internal_strlen(const char *s) {100size_t i = 0;101while (s[i])102i++;103return i;104}105106static char *internal_strstr(const char *haystack, const char *needle) {107// This is O(N^2), but we are not using it in hot places.108size_t len1 = internal_strlen(haystack);109size_t len2 = internal_strlen(needle);110if (len1 < len2)111return nullptr;112for (size_t pos = 0; pos <= len1 - len2; pos++) {113if (internal_memcmp(haystack + pos, needle, len2) == 0)114return const_cast<char *>(haystack) + pos;115}116return nullptr;117}118119extern "C" {120121// Weak hooks forward-declared to avoid dependency on122// <sanitizer/common_interface_defs.h>.123void __sanitizer_weak_hook_memcmp(void *called_pc, const void *s1,124const void *s2, size_t n, int result);125void __sanitizer_weak_hook_strncmp(void *called_pc, const char *s1,126const char *s2, size_t n, int result);127void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,128const char *s2, size_t n, int result);129void __sanitizer_weak_hook_strcmp(void *called_pc, const char *s1,130const char *s2, int result);131void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,132const char *s2, int result);133void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,134const char *s2, char *result);135void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,136const char *s2, char *result);137void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,138const void *s2, size_t len2, void *result);139140DEFINE_REAL(int, bcmp, const void *, const void *, size_t)141DEFINE_REAL(int, memcmp, const void *, const void *, size_t)142DEFINE_REAL(int, strncmp, const char *, const char *, size_t)143DEFINE_REAL(int, strcmp, const char *, const char *)144DEFINE_REAL(int, strncasecmp, const char *, const char *, size_t)145DEFINE_REAL(int, strcasecmp, const char *, const char *)146DEFINE_REAL(char *, strstr, const char *, const char *)147DEFINE_REAL(char *, strcasestr, const char *, const char *)148DEFINE_REAL(void *, memmem, const void *, size_t, const void *, size_t)149150ATTRIBUTE_INTERFACE int bcmp(const char *s1, const char *s2, size_t n) {151if (!FuzzerInited)152return internal_memcmp(s1, s2, n);153int result = REAL(bcmp)(s1, s2, n);154__sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result);155return result;156}157158ATTRIBUTE_INTERFACE int memcmp(const void *s1, const void *s2, size_t n) {159if (!FuzzerInited)160return internal_memcmp(s1, s2, n);161int result = REAL(memcmp)(s1, s2, n);162__sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result);163return result;164}165166ATTRIBUTE_INTERFACE int strncmp(const char *s1, const char *s2, size_t n) {167if (!FuzzerInited)168return internal_strncmp(s1, s2, n);169int result = REAL(strncmp)(s1, s2, n);170__sanitizer_weak_hook_strncmp(GET_CALLER_PC(), s1, s2, n, result);171return result;172}173174ATTRIBUTE_INTERFACE int strcmp(const char *s1, const char *s2) {175if (!FuzzerInited)176return internal_strcmp(s1, s2);177int result = REAL(strcmp)(s1, s2);178__sanitizer_weak_hook_strcmp(GET_CALLER_PC(), s1, s2, result);179return result;180}181182ATTRIBUTE_INTERFACE int strncasecmp(const char *s1, const char *s2, size_t n) {183ensureFuzzerInited();184int result = REAL(strncasecmp)(s1, s2, n);185__sanitizer_weak_hook_strncasecmp(GET_CALLER_PC(), s1, s2, n, result);186return result;187}188189ATTRIBUTE_INTERFACE int strcasecmp(const char *s1, const char *s2) {190ensureFuzzerInited();191int result = REAL(strcasecmp)(s1, s2);192__sanitizer_weak_hook_strcasecmp(GET_CALLER_PC(), s1, s2, result);193return result;194}195196ATTRIBUTE_INTERFACE char *strstr(const char *s1, const char *s2) {197if (!FuzzerInited)198return internal_strstr(s1, s2);199char *result = REAL(strstr)(s1, s2);200__sanitizer_weak_hook_strstr(GET_CALLER_PC(), s1, s2, result);201return result;202}203204ATTRIBUTE_INTERFACE char *strcasestr(const char *s1, const char *s2) {205ensureFuzzerInited();206char *result = REAL(strcasestr)(s1, s2);207__sanitizer_weak_hook_strcasestr(GET_CALLER_PC(), s1, s2, result);208return result;209}210211ATTRIBUTE_INTERFACE212void *memmem(const void *s1, size_t len1, const void *s2, size_t len2) {213ensureFuzzerInited();214void *result = REAL(memmem)(s1, len1, s2, len2);215__sanitizer_weak_hook_memmem(GET_CALLER_PC(), s1, len1, s2, len2, result);216return result;217}218219__attribute__((section(".preinit_array"),220used)) static void (*__local_fuzzer_preinit)(void) = fuzzerInit;221222} // extern "C"223224static void fuzzerInit() {225assert(!FuzzerInitIsRunning);226if (FuzzerInited)227return;228FuzzerInitIsRunning = true;229230REAL(bcmp) = reinterpret_cast<memcmp_type>(231getFuncAddr("bcmp", reinterpret_cast<uintptr_t>(&bcmp)));232REAL(memcmp) = reinterpret_cast<memcmp_type>(233getFuncAddr("memcmp", reinterpret_cast<uintptr_t>(&memcmp)));234REAL(strncmp) = reinterpret_cast<strncmp_type>(235getFuncAddr("strncmp", reinterpret_cast<uintptr_t>(&strncmp)));236REAL(strcmp) = reinterpret_cast<strcmp_type>(237getFuncAddr("strcmp", reinterpret_cast<uintptr_t>(&strcmp)));238REAL(strncasecmp) = reinterpret_cast<strncasecmp_type>(239getFuncAddr("strncasecmp", reinterpret_cast<uintptr_t>(&strncasecmp)));240REAL(strcasecmp) = reinterpret_cast<strcasecmp_type>(241getFuncAddr("strcasecmp", reinterpret_cast<uintptr_t>(&strcasecmp)));242REAL(strstr) = reinterpret_cast<strstr_type>(243getFuncAddr("strstr", reinterpret_cast<uintptr_t>(&strstr)));244REAL(strcasestr) = reinterpret_cast<strcasestr_type>(245getFuncAddr("strcasestr", reinterpret_cast<uintptr_t>(&strcasestr)));246REAL(memmem) = reinterpret_cast<memmem_type>(247getFuncAddr("memmem", reinterpret_cast<uintptr_t>(&memmem)));248249FuzzerInitIsRunning = false;250FuzzerInited = 1;251}252253#endif254255256