Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/compiler-rt/lib/nsan/nsan_interceptors.cpp
35233 views
1
//===- nsan_interceptors.cpp ----------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Interceptors for standard library functions.
10
//
11
// A note about `printf`: Make sure none of the interceptor code calls any
12
// part of the nsan framework that can call `printf`, since this could create
13
// a loop (`printf` itself uses the libc). printf-free functions are documented
14
// as such in nsan.h.
15
//
16
//===----------------------------------------------------------------------===//
17
18
#include "interception/interception.h"
19
#include "nsan/nsan.h"
20
#include "sanitizer_common/sanitizer_common.h"
21
22
#include <wchar.h>
23
24
using namespace __sanitizer;
25
using __nsan::nsan_init_is_running;
26
using __nsan::nsan_initialized;
27
28
template <typename T> T min(T a, T b) { return a < b ? a : b; }
29
30
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
31
// NOTE: This guard is needed because nsan's initialization code might call
32
// memset.
33
if (!nsan_initialized && REAL(memset) == nullptr)
34
return internal_memset(dst, v, size);
35
36
void *res = REAL(memset)(dst, v, size);
37
__nsan_set_value_unknown(static_cast<u8 *>(dst), size);
38
return res;
39
}
40
41
INTERCEPTOR(wchar_t *, wmemset, wchar_t *dst, wchar_t v, uptr size) {
42
wchar_t *res = REAL(wmemset)(dst, v, size);
43
__nsan_set_value_unknown((u8 *)dst, sizeof(wchar_t) * size);
44
return res;
45
}
46
47
INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
48
// NOTE: This guard is needed because nsan's initialization code might call
49
// memmove.
50
if (!nsan_initialized && REAL(memmove) == nullptr)
51
return internal_memmove(dst, src, size);
52
53
void *res = REAL(memmove)(dst, src, size);
54
__nsan_copy_values(static_cast<u8 *>(dst), static_cast<const u8 *>(src),
55
size);
56
return res;
57
}
58
59
INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dst, const wchar_t *src, uptr size) {
60
wchar_t *res = REAL(wmemmove)(dst, src, size);
61
__nsan_copy_values((u8 *)dst, (const u8 *)src, sizeof(wchar_t) * size);
62
return res;
63
}
64
65
INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
66
// NOTE: This guard is needed because nsan's initialization code might call
67
// memcpy.
68
if (!nsan_initialized && REAL(memcpy) == nullptr) {
69
// memmove is used here because on some platforms this will also
70
// intercept the memmove implementation.
71
return internal_memmove(dst, src, size);
72
}
73
74
void *res = REAL(memcpy)(dst, src, size);
75
__nsan_copy_values(static_cast<u8 *>(dst), static_cast<const u8 *>(src),
76
size);
77
return res;
78
}
79
80
INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dst, const wchar_t *src, uptr size) {
81
wchar_t *res = REAL(wmemcpy)(dst, src, size);
82
__nsan_copy_values((u8 *)dst, (const u8 *)src, sizeof(wchar_t) * size);
83
return res;
84
}
85
86
INTERCEPTOR(char *, strfry, char *s) {
87
const auto Len = internal_strlen(s);
88
char *res = REAL(strfry)(s);
89
if (res)
90
__nsan_set_value_unknown(reinterpret_cast<u8 *>(s), Len);
91
return res;
92
}
93
94
INTERCEPTOR(char *, strsep, char **Stringp, const char *delim) {
95
char *OrigStringp = REAL(strsep)(Stringp, delim);
96
if (Stringp != nullptr) {
97
// The previous character has been overwritten with a '\0' char.
98
__nsan_set_value_unknown(reinterpret_cast<u8 *>(*Stringp) - 1, 1);
99
}
100
return OrigStringp;
101
}
102
103
INTERCEPTOR(char *, strtok, char *str, const char *delim) {
104
// This is overly conservative, but the probability that modern code is using
105
// strtok on double data is essentially zero anyway.
106
if (str)
107
__nsan_set_value_unknown(reinterpret_cast<u8 *>(str), internal_strlen(str));
108
return REAL(strtok)(str, delim);
109
}
110
111
static void nsanCopyZeroTerminated(char *dst, const char *src, uptr n) {
112
__nsan_copy_values(reinterpret_cast<u8 *>(dst),
113
reinterpret_cast<const u8 *>(src), n); // Data.
114
__nsan_set_value_unknown(reinterpret_cast<u8 *>(dst) + n, 1); // Terminator.
115
}
116
117
static void nsanWCopyZeroTerminated(wchar_t *dst, const wchar_t *src, uptr n) {
118
__nsan_copy_values((u8 *)dst, (const u8 *)(src), sizeof(wchar_t) * n);
119
__nsan_set_value_unknown((u8 *)(dst + n), sizeof(wchar_t));
120
}
121
122
INTERCEPTOR(char *, strdup, const char *S) {
123
char *res = REAL(strdup)(S);
124
if (res) {
125
nsanCopyZeroTerminated(res, S, internal_strlen(S));
126
}
127
return res;
128
}
129
130
INTERCEPTOR(wchar_t *, wcsdup, const wchar_t *S) {
131
wchar_t *res = REAL(wcsdup)(S);
132
if (res) {
133
nsanWCopyZeroTerminated(res, S, wcslen(S));
134
}
135
return res;
136
}
137
138
INTERCEPTOR(char *, strndup, const char *S, uptr size) {
139
char *res = REAL(strndup)(S, size);
140
if (res) {
141
nsanCopyZeroTerminated(res, S, min(internal_strlen(S), size));
142
}
143
return res;
144
}
145
146
INTERCEPTOR(char *, strcpy, char *dst, const char *src) {
147
char *res = REAL(strcpy)(dst, src);
148
nsanCopyZeroTerminated(dst, src, internal_strlen(src));
149
return res;
150
}
151
152
INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dst, const wchar_t *src) {
153
wchar_t *res = REAL(wcscpy)(dst, src);
154
nsanWCopyZeroTerminated(dst, src, wcslen(src));
155
return res;
156
}
157
158
INTERCEPTOR(char *, strncpy, char *dst, const char *src, uptr size) {
159
char *res = REAL(strncpy)(dst, src, size);
160
nsanCopyZeroTerminated(dst, src, min(size, internal_strlen(src)));
161
return res;
162
}
163
164
INTERCEPTOR(char *, strcat, char *dst, const char *src) {
165
const auto DstLenBeforeCat = internal_strlen(dst);
166
char *res = REAL(strcat)(dst, src);
167
nsanCopyZeroTerminated(dst + DstLenBeforeCat, src, internal_strlen(src));
168
return res;
169
}
170
171
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
172
const auto DstLenBeforeCat = wcslen(dst);
173
wchar_t *res = REAL(wcscat)(dst, src);
174
nsanWCopyZeroTerminated(dst + DstLenBeforeCat, src, wcslen(src));
175
return res;
176
}
177
178
INTERCEPTOR(char *, strncat, char *dst, const char *src, uptr size) {
179
const auto DstLen = internal_strlen(dst);
180
char *res = REAL(strncat)(dst, src, size);
181
nsanCopyZeroTerminated(dst + DstLen, src, min(size, internal_strlen(src)));
182
return res;
183
}
184
185
INTERCEPTOR(char *, stpcpy, char *dst, const char *src) {
186
char *res = REAL(stpcpy)(dst, src);
187
nsanCopyZeroTerminated(dst, src, internal_strlen(src));
188
return res;
189
}
190
191
INTERCEPTOR(wchar_t *, wcpcpy, wchar_t *dst, const wchar_t *src) {
192
wchar_t *res = REAL(wcpcpy)(dst, src);
193
nsanWCopyZeroTerminated(dst, src, wcslen(src));
194
return res;
195
}
196
197
INTERCEPTOR(uptr, strxfrm, char *dst, const char *src, uptr size) {
198
// This is overly conservative, but this function should very rarely be used.
199
__nsan_set_value_unknown(reinterpret_cast<u8 *>(dst), internal_strlen(dst));
200
const uptr res = REAL(strxfrm)(dst, src, size);
201
return res;
202
}
203
204
void __nsan::InitializeInterceptors() {
205
static bool initialized = false;
206
CHECK(!initialized);
207
208
InitializeMallocInterceptors();
209
210
INTERCEPT_FUNCTION(memset);
211
INTERCEPT_FUNCTION(wmemset);
212
INTERCEPT_FUNCTION(memmove);
213
INTERCEPT_FUNCTION(wmemmove);
214
INTERCEPT_FUNCTION(memcpy);
215
INTERCEPT_FUNCTION(wmemcpy);
216
217
INTERCEPT_FUNCTION(strdup);
218
INTERCEPT_FUNCTION(wcsdup);
219
INTERCEPT_FUNCTION(strndup);
220
INTERCEPT_FUNCTION(stpcpy);
221
INTERCEPT_FUNCTION(wcpcpy);
222
INTERCEPT_FUNCTION(strcpy);
223
INTERCEPT_FUNCTION(wcscpy);
224
INTERCEPT_FUNCTION(strncpy);
225
INTERCEPT_FUNCTION(strcat);
226
INTERCEPT_FUNCTION(wcscat);
227
INTERCEPT_FUNCTION(strncat);
228
INTERCEPT_FUNCTION(strxfrm);
229
230
INTERCEPT_FUNCTION(strfry);
231
INTERCEPT_FUNCTION(strsep);
232
INTERCEPT_FUNCTION(strtok);
233
234
initialized = 1;
235
}
236
237