Skip to content

Commit 6485600

Browse files
authored
[dfsan] Wrap glibc 2.38 __isoc23_* functions (llvm#79958)
Fix llvm#79283: `test/dfsan/custom.cpp` has undefined symbol linker errors on glibc 2.38 due to lack of wrappers for `__isoc23_strtol` and `__isoc23_scanf` family functions. Implement these wrappers as aliases to existing wrappers, similar to https://reviews.llvm.org/D158943 for other sanitizers. `strtol` in a user program, whether or not `_ISOC2X_SOURCE` is defined, uses the C23 semantics (`strtol("0b1", 0, 0)` => 1), when `libclang_rt.dfsan.a` is built on glibc 2.38+.
1 parent 9b91c54 commit 6485600

File tree

3 files changed

+59
-155
lines changed

3 files changed

+59
-155
lines changed

compiler-rt/lib/dfsan/dfsan_custom.cpp

+48-155
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ using namespace __dfsan;
5555
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
5656
SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void f(__VA_ARGS__);
5757

58+
#define WRAPPER_ALIAS(fun, real) \
59+
SANITIZER_INTERFACE_ATTRIBUTE void __dfsw_##fun() ALIAS(__dfsw_##real); \
60+
SANITIZER_INTERFACE_ATTRIBUTE void __dfso_##fun() ALIAS(__dfso_##real);
61+
5862
// Async-safe, non-reentrant spin lock.
5963
class SignalSpinLocker {
6064
public:
@@ -1197,16 +1201,20 @@ char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
11971201
*ret_origin = dst_origin;
11981202
return ret;
11991203
}
1204+
}
12001205

1201-
static long int dfsan_strtol(const char *nptr, char **endptr, int base,
1202-
char **tmp_endptr) {
1206+
template <typename Fn>
1207+
static ALWAYS_INLINE auto dfsan_strtol_impl(
1208+
Fn real, const char *nptr, char **endptr, int base,
1209+
char **tmp_endptr) -> decltype(real(nullptr, nullptr, 0)) {
12031210
assert(tmp_endptr);
1204-
long int ret = strtol(nptr, tmp_endptr, base);
1211+
auto ret = real(nptr, tmp_endptr, base);
12051212
if (endptr)
12061213
*endptr = *tmp_endptr;
12071214
return ret;
12081215
}
12091216

1217+
extern "C" {
12101218
static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
12111219
dfsan_label base_label,
12121220
dfsan_label *ret_label) {
@@ -1236,30 +1244,6 @@ static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
12361244
}
12371245
}
12381246

1239-
SANITIZER_INTERFACE_ATTRIBUTE
1240-
long int __dfsw_strtol(const char *nptr, char **endptr, int base,
1241-
dfsan_label nptr_label, dfsan_label endptr_label,
1242-
dfsan_label base_label, dfsan_label *ret_label) {
1243-
char *tmp_endptr;
1244-
long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
1245-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1246-
return ret;
1247-
}
1248-
1249-
SANITIZER_INTERFACE_ATTRIBUTE
1250-
long int __dfso_strtol(const char *nptr, char **endptr, int base,
1251-
dfsan_label nptr_label, dfsan_label endptr_label,
1252-
dfsan_label base_label, dfsan_label *ret_label,
1253-
dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1254-
dfsan_origin base_origin, dfsan_origin *ret_origin) {
1255-
char *tmp_endptr;
1256-
long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
1257-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1258-
dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1259-
ret_origin);
1260-
return ret;
1261-
}
1262-
12631247
static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
12641248
assert(tmp_endptr);
12651249
double ret = strtod(nptr, tmp_endptr);
@@ -1307,108 +1291,40 @@ double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
13071291
return ret;
13081292
}
13091293

1310-
static long long int dfsan_strtoll(const char *nptr, char **endptr, int base,
1311-
char **tmp_endptr) {
1312-
assert(tmp_endptr);
1313-
long long int ret = strtoll(nptr, tmp_endptr, base);
1314-
if (endptr)
1315-
*endptr = *tmp_endptr;
1316-
return ret;
1317-
}
1318-
1319-
SANITIZER_INTERFACE_ATTRIBUTE
1320-
long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
1321-
dfsan_label nptr_label, dfsan_label endptr_label,
1322-
dfsan_label base_label, dfsan_label *ret_label) {
1323-
char *tmp_endptr;
1324-
long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
1325-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1326-
return ret;
1327-
}
1328-
1329-
SANITIZER_INTERFACE_ATTRIBUTE
1330-
long long int __dfso_strtoll(const char *nptr, char **endptr, int base,
1331-
dfsan_label nptr_label, dfsan_label endptr_label,
1332-
dfsan_label base_label, dfsan_label *ret_label,
1333-
dfsan_origin nptr_origin,
1334-
dfsan_origin endptr_origin,
1335-
dfsan_origin base_origin,
1336-
dfsan_origin *ret_origin) {
1337-
char *tmp_endptr;
1338-
long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
1339-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1340-
dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1341-
ret_origin);
1342-
return ret;
1343-
}
1344-
1345-
static unsigned long int dfsan_strtoul(const char *nptr, char **endptr,
1346-
int base, char **tmp_endptr) {
1347-
assert(tmp_endptr);
1348-
unsigned long int ret = strtoul(nptr, tmp_endptr, base);
1349-
if (endptr)
1350-
*endptr = *tmp_endptr;
1351-
return ret;
1352-
}
1353-
1354-
SANITIZER_INTERFACE_ATTRIBUTE
1355-
unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
1356-
dfsan_label nptr_label, dfsan_label endptr_label,
1357-
dfsan_label base_label, dfsan_label *ret_label) {
1358-
char *tmp_endptr;
1359-
unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
1360-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1361-
return ret;
1362-
}
1363-
1364-
SANITIZER_INTERFACE_ATTRIBUTE
1365-
unsigned long int __dfso_strtoul(
1366-
const char *nptr, char **endptr, int base, dfsan_label nptr_label,
1367-
dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
1368-
dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1369-
dfsan_origin base_origin, dfsan_origin *ret_origin) {
1370-
char *tmp_endptr;
1371-
unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
1372-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1373-
dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1374-
ret_origin);
1375-
return ret;
1376-
}
1377-
1378-
static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr,
1379-
int base, char **tmp_endptr) {
1380-
assert(tmp_endptr);
1381-
long long unsigned int ret = strtoull(nptr, tmp_endptr, base);
1382-
if (endptr)
1383-
*endptr = *tmp_endptr;
1384-
return ret;
1385-
}
1386-
1387-
SANITIZER_INTERFACE_ATTRIBUTE
1388-
long long unsigned int __dfsw_strtoull(const char *nptr, char **endptr,
1389-
int base, dfsan_label nptr_label,
1390-
dfsan_label endptr_label,
1391-
dfsan_label base_label,
1392-
dfsan_label *ret_label) {
1393-
char *tmp_endptr;
1394-
long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
1395-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1396-
return ret;
1397-
}
1398-
1399-
SANITIZER_INTERFACE_ATTRIBUTE
1400-
long long unsigned int __dfso_strtoull(
1401-
const char *nptr, char **endptr, int base, dfsan_label nptr_label,
1402-
dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
1403-
dfsan_origin nptr_origin, dfsan_origin endptr_origin,
1404-
dfsan_origin base_origin, dfsan_origin *ret_origin) {
1405-
char *tmp_endptr;
1406-
long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
1407-
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
1408-
dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
1409-
ret_origin);
1410-
return ret;
1411-
}
1294+
WRAPPER_ALIAS(__isoc23_strtod, strtod)
1295+
1296+
#define WRAPPER_STRTO(ret_type, fun) \
1297+
SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfsw_##fun( \
1298+
const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
1299+
dfsan_label endptr_label, dfsan_label base_label, \
1300+
dfsan_label *ret_label) { \
1301+
char *tmp_endptr; \
1302+
auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \
1303+
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \
1304+
return ret; \
1305+
} \
1306+
SANITIZER_INTERFACE_ATTRIBUTE ret_type __dfso_##fun( \
1307+
const char *nptr, char **endptr, int base, dfsan_label nptr_label, \
1308+
dfsan_label endptr_label, dfsan_label base_label, \
1309+
dfsan_label *ret_label, dfsan_origin nptr_origin, \
1310+
dfsan_origin endptr_origin, dfsan_origin base_origin, \
1311+
dfsan_origin *ret_origin) { \
1312+
char *tmp_endptr; \
1313+
auto ret = dfsan_strtol_impl(fun, nptr, endptr, base, &tmp_endptr); \
1314+
dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label); \
1315+
dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, \
1316+
base_origin, ret_origin); \
1317+
return ret; \
1318+
}
1319+
1320+
WRAPPER_STRTO(long, strtol)
1321+
WRAPPER_STRTO(long long, strtoll)
1322+
WRAPPER_STRTO(unsigned long, strtoul)
1323+
WRAPPER_STRTO(unsigned long long, strtoull)
1324+
WRAPPER_ALIAS(__isoc23_strtol, strtol)
1325+
WRAPPER_ALIAS(__isoc23_strtoll, strtoll)
1326+
WRAPPER_ALIAS(__isoc23_strtoul, strtoul)
1327+
WRAPPER_ALIAS(__isoc23_strtoull, strtoull)
14121328

14131329
SANITIZER_INTERFACE_ATTRIBUTE
14141330
time_t __dfsw_time(time_t *t, dfsan_label t_label, dfsan_label *ret_label) {
@@ -2231,7 +2147,7 @@ SANITIZER_INTERFACE_ATTRIBUTE int __dfso_write(
22312147
*ret_label = 0;
22322148
return write(fd, buf, count);
22332149
}
2234-
} // namespace __dfsan
2150+
} // namespace __dfsan
22352151

22362152
// Type used to extract a dfsan_label with va_arg()
22372153
typedef int dfsan_label_va;
@@ -2866,31 +2782,8 @@ int __dfso_sscanf(char *str, const char *format, dfsan_label str_label,
28662782
return ret;
28672783
}
28682784

2869-
SANITIZER_INTERFACE_ATTRIBUTE
2870-
int __dfsw___isoc99_sscanf(char *str, const char *format, dfsan_label str_label,
2871-
dfsan_label format_label, dfsan_label *va_labels,
2872-
dfsan_label *ret_label, ...) {
2873-
va_list ap;
2874-
va_start(ap, ret_label);
2875-
int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
2876-
nullptr, ap);
2877-
va_end(ap);
2878-
return ret;
2879-
}
2880-
2881-
SANITIZER_INTERFACE_ATTRIBUTE
2882-
int __dfso___isoc99_sscanf(char *str, const char *format, dfsan_label str_label,
2883-
dfsan_label format_label, dfsan_label *va_labels,
2884-
dfsan_label *ret_label, dfsan_origin str_origin,
2885-
dfsan_origin format_origin, dfsan_origin *va_origins,
2886-
dfsan_origin *ret_origin, ...) {
2887-
va_list ap;
2888-
va_start(ap, ret_origin);
2889-
int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,
2890-
ret_origin, ap);
2891-
va_end(ap);
2892-
return ret;
2893-
}
2785+
WRAPPER_ALIAS(__isoc99_sscanf, sscanf)
2786+
WRAPPER_ALIAS(__isoc23_sscanf, sscanf)
28942787

28952788
static void BeforeFork() {
28962789
StackDepotLockBeforeFork();

compiler-rt/lib/dfsan/done_abilist.txt

+6
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ fun:strtoul=custom
270270
fun:strtoull=custom
271271
fun:strcat=custom
272272
fun:strncat=custom
273+
fun:__isoc23_strtod=custom
274+
fun:__isoc23_strtol=custom
275+
fun:__isoc23_strtoll=custom
276+
fun:__isoc23_strtoul=custom
277+
fun:__isoc23_strtoull=custom
273278

274279
# Functions that produce an output that is computed from the input, but is not
275280
# necessarily data dependent.
@@ -311,6 +316,7 @@ fun:snprintf=custom
311316
# scanf-like
312317
fun:sscanf=custom
313318
fun:__isoc99_sscanf=custom
319+
fun:__isoc23_sscanf=custom
314320

315321
# TODO: custom
316322
fun:asprintf=discard

compiler-rt/lib/dfsan/libc_ubuntu1404_abilist.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
fun:__isoc23_sscanf=uninstrumented
2+
fun:__isoc23_strtol=uninstrumented
3+
fun:__isoc23_strtoll=uninstrumented
4+
fun:__isoc23_strtoul=uninstrumented
5+
fun:__isoc23_strtoull=uninstrumented
16
fun:_Exit=uninstrumented
27
fun:_IO_adjust_column=uninstrumented
38
fun:_IO_adjust_wcolumn=uninstrumented

0 commit comments

Comments
 (0)