}
SANITIZER_INTERFACE_ATTRIBUTE
-long int __dfsw_strtol(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label) {
- char *tmp_endptr;
- long int ret = strtol(nptr, &tmp_endptr, base);
- if (endptr) {
- *endptr = tmp_endptr;
+char *__dfso_strcpy(char *dest, const char *src, dfsan_label dst_label,
+ dfsan_label src_label, dfsan_label *ret_label,
+ dfsan_origin dst_origin, dfsan_origin src_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = strcpy(dest, src); // NOLINT
+ if (ret) {
+ size_t str_len = strlen(src) + 1;
+ dfsan_mem_origin_transfer(dest, src, str_len);
+ internal_memcpy(shadow_for(dest), shadow_for(src),
+ sizeof(dfsan_label) * str_len);
}
+ *ret_label = dst_label;
+ *ret_origin = dst_origin;
+ return ret;
+}
+
+static long int dfsan_strtol(const char *nptr, char **endptr, int base,
+ char **tmp_endptr) {
+ assert(tmp_endptr);
+ long int ret = strtol(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+static void dfsan_strtolong_label(const char *nptr, const char *tmp_endptr,
+ dfsan_label base_label,
+ dfsan_label *ret_label) {
if (tmp_endptr > nptr) {
// If *tmp_endptr is '\0' include its label as well.
*ret_label = dfsan_union(
} else {
*ret_label = 0;
}
+}
+
+static void dfsan_strtolong_origin(const char *nptr, const char *tmp_endptr,
+ dfsan_label base_label,
+ dfsan_label *ret_label,
+ dfsan_origin base_origin,
+ dfsan_origin *ret_origin) {
+ if (tmp_endptr > nptr) {
+ // When multiple inputs are tainted, we propagate one of its origins.
+ // Because checking if base_label is tainted does not need additional
+ // computation, we prefer to propagating base_origin.
+ *ret_origin = base_label
+ ? base_origin
+ : dfsan_read_origin_of_first_taint(
+ nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
+ }
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long int __dfsw_strtol(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
return ret;
}
SANITIZER_INTERFACE_ATTRIBUTE
-double __dfsw_strtod(const char *nptr, char **endptr,
+long int __dfso_strtol(const char *nptr, char **endptr, int base,
dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label *ret_label) {
+ dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin base_origin, dfsan_origin *ret_origin) {
char *tmp_endptr;
- double ret = strtod(nptr, &tmp_endptr);
- if (endptr) {
- *endptr = tmp_endptr;
- }
+ long int ret = dfsan_strtol(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+static double dfsan_strtod(const char *nptr, char **endptr, char **tmp_endptr) {
+ assert(tmp_endptr);
+ double ret = strtod(nptr, tmp_endptr);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+static void dfsan_strtod_label(const char *nptr, const char *tmp_endptr,
+ dfsan_label *ret_label) {
if (tmp_endptr > nptr) {
// If *tmp_endptr is '\0' include its label as well.
*ret_label = dfsan_read_label(
} else {
*ret_label = 0;
}
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+double __dfsw_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
+ dfsan_strtod_label(nptr, tmp_endptr, ret_label);
return ret;
}
SANITIZER_INTERFACE_ATTRIBUTE
-long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
- dfsan_label nptr_label, dfsan_label endptr_label,
- dfsan_label base_label, dfsan_label *ret_label) {
+double __dfso_strtod(const char *nptr, char **endptr, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin *ret_origin) {
char *tmp_endptr;
- long long int ret = strtoll(nptr, &tmp_endptr, base);
- if (endptr) {
- *endptr = tmp_endptr;
- }
+ double ret = dfsan_strtod(nptr, endptr, &tmp_endptr);
+ dfsan_strtod_label(nptr, tmp_endptr, ret_label);
if (tmp_endptr > nptr) {
// If *tmp_endptr is '\0' include its label as well.
- *ret_label = dfsan_union(
- base_label,
- dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
+ *ret_origin = dfsan_read_origin_of_first_taint(
+ nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1));
} else {
- *ret_label = 0;
+ *ret_origin = 0;
}
return ret;
}
+static long long int dfsan_strtoll(const char *nptr, char **endptr, int base,
+ char **tmp_endptr) {
+ assert(tmp_endptr);
+ long long int ret = strtoll(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long int __dfsw_strtoll(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label) {
+ char *tmp_endptr;
+ long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long int __dfso_strtoll(const char *nptr, char **endptr, int base,
+ dfsan_label nptr_label, dfsan_label endptr_label,
+ dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin,
+ dfsan_origin endptr_origin,
+ dfsan_origin base_origin,
+ dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ long long int ret = dfsan_strtoll(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+static unsigned long int dfsan_strtoul(const char *nptr, char **endptr,
+ int base, char **tmp_endptr) {
+ assert(tmp_endptr);
+ unsigned long int ret = strtoul(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
+ return ret;
+}
+
SANITIZER_INTERFACE_ATTRIBUTE
unsigned long int __dfsw_strtoul(const char *nptr, char **endptr, int base,
dfsan_label nptr_label, dfsan_label endptr_label,
dfsan_label base_label, dfsan_label *ret_label) {
char *tmp_endptr;
- unsigned long int ret = strtoul(nptr, &tmp_endptr, base);
- if (endptr) {
- *endptr = tmp_endptr;
- }
- if (tmp_endptr > nptr) {
- // If *tmp_endptr is '\0' include its label as well.
- *ret_label = dfsan_union(
- base_label,
- dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
- } else {
- *ret_label = 0;
- }
+ unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+unsigned long int __dfso_strtoul(
+ const char *nptr, char **endptr, int base, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin base_origin, dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ unsigned long int ret = dfsan_strtoul(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
+ return ret;
+}
+
+static long long unsigned int dfsan_strtoull(const char *nptr, char **endptr,
+ int base, char **tmp_endptr) {
+ assert(tmp_endptr);
+ long long unsigned int ret = strtoull(nptr, tmp_endptr, base);
+ if (endptr)
+ *endptr = *tmp_endptr;
return ret;
}
dfsan_label base_label,
dfsan_label *ret_label) {
char *tmp_endptr;
- long long unsigned int ret = strtoull(nptr, &tmp_endptr, base);
- if (endptr) {
- *endptr = tmp_endptr;
- }
- if (tmp_endptr > nptr) {
- // If *tmp_endptr is '\0' include its label as well.
- *ret_label = dfsan_union(
- base_label,
- dfsan_read_label(nptr, tmp_endptr - nptr + (*tmp_endptr ? 0 : 1)));
- } else {
- *ret_label = 0;
- }
+ long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+long long unsigned int __dfso_strtoull(
+ const char *nptr, char **endptr, int base, dfsan_label nptr_label,
+ dfsan_label endptr_label, dfsan_label base_label, dfsan_label *ret_label,
+ dfsan_origin nptr_origin, dfsan_origin endptr_origin,
+ dfsan_origin base_origin, dfsan_origin *ret_origin) {
+ char *tmp_endptr;
+ long long unsigned int ret = dfsan_strtoull(nptr, endptr, base, &tmp_endptr);
+ dfsan_strtolong_label(nptr, tmp_endptr, base_label, ret_label);
+ dfsan_strtolong_origin(nptr, tmp_endptr, base_label, ret_label, base_origin,
+ ret_origin);
return ret;
}
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_gettimeofday(struct timeval *tv, struct timezone *tz,
+ dfsan_label tv_label, dfsan_label tz_label,
+ dfsan_label *ret_label, dfsan_origin tv_origin,
+ dfsan_origin tz_origin, dfsan_origin *ret_origin) {
+ return __dfsw_gettimeofday(tv, tz, tv_label, tz_label, ret_label);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE void *__dfsw_memchr(void *s, int c, size_t n,
dfsan_label s_label,
dfsan_label c_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE void *__dfso_memchr(
+ void *s, int c, size_t n, dfsan_label s_label, dfsan_label c_label,
+ dfsan_label n_label, dfsan_label *ret_label, dfsan_origin s_origin,
+ dfsan_origin c_origin, dfsan_origin n_origin, dfsan_origin *ret_origin) {
+ void *ret = __dfsw_memchr(s, c, n, s_label, c_label, n_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = s_origin;
+ } else {
+ size_t len =
+ ret ? reinterpret_cast<char *>(ret) - reinterpret_cast<char *>(s) + 1
+ : n;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s, len);
+ *ret_origin = o ? o : (s_label ? s_origin : c_origin);
+ }
+ return ret;
+}
+
SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strrchr(char *s, int c,
dfsan_label s_label,
dfsan_label c_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strrchr(
+ char *s, int c, dfsan_label s_label, dfsan_label c_label,
+ dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin c_origin,
+ dfsan_origin *ret_origin) {
+ char *ret = __dfsw_strrchr(s, c, s_label, c_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = s_origin;
+ } else {
+ size_t s_len = strlen(s) + 1;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(s, s_len);
+ *ret_origin = o ? o : (s_label ? s_origin : c_origin);
+ }
+
+ return ret;
+}
+
SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strstr(char *haystack, char *needle,
dfsan_label haystack_label,
dfsan_label needle_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strstr(char *haystack, char *needle,
+ dfsan_label haystack_label,
+ dfsan_label needle_label,
+ dfsan_label *ret_label,
+ dfsan_origin haystack_origin,
+ dfsan_origin needle_origin,
+ dfsan_origin *ret_origin) {
+ char *ret =
+ __dfsw_strstr(haystack, needle, haystack_label, needle_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (ret)
+ *ret_origin = haystack_origin;
+ } else {
+ size_t needle_len = strlen(needle);
+ size_t len = ret ? ret + needle_len - haystack : strlen(haystack) + 1;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(haystack, len);
+ if (o) {
+ *ret_origin = o;
+ } else {
+ o = dfsan_read_origin_of_first_taint(needle, needle_len + 1);
+ *ret_origin = o ? o : (haystack_label ? haystack_origin : needle_origin);
+ }
+ }
+
+ return ret;
+}
+
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_nanosleep(const struct timespec *req,
struct timespec *rem,
dfsan_label req_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_nanosleep(
+ const struct timespec *req, struct timespec *rem, dfsan_label req_label,
+ dfsan_label rem_label, dfsan_label *ret_label, dfsan_origin req_origin,
+ dfsan_origin rem_origin, dfsan_origin *ret_origin) {
+ return __dfsw_nanosleep(req, rem, req_label, rem_label, ret_label);
+}
+
static void clear_msghdr_labels(size_t bytes_written, struct msghdr *msg) {
dfsan_set_label(0, msg, sizeof(*msg));
dfsan_set_label(0, msg->msg_name, msg->msg_namelen);
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_recvmmsg(
+ int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags,
+ struct timespec *timeout, dfsan_label sockfd_label,
+ dfsan_label msgvec_label, dfsan_label vlen_label, dfsan_label flags_label,
+ dfsan_label timeout_label, dfsan_label *ret_label,
+ dfsan_origin sockfd_origin, dfsan_origin msgvec_origin,
+ dfsan_origin vlen_origin, dfsan_origin flags_origin,
+ dfsan_origin timeout_origin, dfsan_origin *ret_origin) {
+ return __dfsw_recvmmsg(sockfd, msgvec, vlen, flags, timeout, sockfd_label,
+ msgvec_label, vlen_label, flags_label, timeout_label,
+ ret_label);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfsw_recvmsg(
int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label) {
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE ssize_t __dfso_recvmsg(
+ int sockfd, struct msghdr *msg, int flags, dfsan_label sockfd_label,
+ dfsan_label msg_label, dfsan_label flags_label, dfsan_label *ret_label,
+ dfsan_origin sockfd_origin, dfsan_origin msg_origin,
+ dfsan_origin flags_origin, dfsan_origin *ret_origin) {
+ return __dfsw_recvmsg(sockfd, msg, flags, sockfd_label, msg_label,
+ flags_label, ret_label);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE int
__dfsw_socketpair(int domain, int type, int protocol, int sv[2],
dfsan_label domain_label, dfsan_label type_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_socketpair(
+ int domain, int type, int protocol, int sv[2], dfsan_label domain_label,
+ dfsan_label type_label, dfsan_label protocol_label, dfsan_label sv_label,
+ dfsan_label *ret_label, dfsan_origin domain_origin,
+ dfsan_origin type_origin, dfsan_origin protocol_origin,
+ dfsan_origin sv_origin, dfsan_origin *ret_origin) {
+ return __dfsw_socketpair(domain, type, protocol, sv, domain_label, type_label,
+ protocol_label, sv_label, ret_label);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockopt(
int sockfd, int level, int optname, void *optval, socklen_t *optlen,
dfsan_label sockfd_label, dfsan_label level_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockopt(
+ int sockfd, int level, int optname, void *optval, socklen_t *optlen,
+ dfsan_label sockfd_label, dfsan_label level_label,
+ dfsan_label optname_label, dfsan_label optval_label,
+ dfsan_label optlen_label, dfsan_label *ret_label,
+ dfsan_origin sockfd_origin, dfsan_origin level_origin,
+ dfsan_origin optname_origin, dfsan_origin optval_origin,
+ dfsan_origin optlen_origin, dfsan_origin *ret_origin) {
+ return __dfsw_getsockopt(sockfd, level, optname, optval, optlen, sockfd_label,
+ level_label, optname_label, optval_label,
+ optlen_label, ret_label);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getsockname(
int sockfd, struct sockaddr *addr, socklen_t *addrlen,
dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getsockname(
+ int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
+ dfsan_label *ret_label, dfsan_origin sockfd_origin,
+ dfsan_origin addr_origin, dfsan_origin addrlen_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_getsockname(sockfd, addr, addrlen, sockfd_label, addr_label,
+ addrlen_label, ret_label);
+}
+
SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_getpeername(
int sockfd, struct sockaddr *addr, socklen_t *addrlen,
dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE int __dfso_getpeername(
+ int sockfd, struct sockaddr *addr, socklen_t *addrlen,
+ dfsan_label sockfd_label, dfsan_label addr_label, dfsan_label addrlen_label,
+ dfsan_label *ret_label, dfsan_origin sockfd_origin,
+ dfsan_origin addr_origin, dfsan_origin addrlen_origin,
+ dfsan_origin *ret_origin) {
+ return __dfsw_getpeername(sockfd, addr, addrlen, sockfd_label, addr_label,
+ addrlen_label, ret_label);
+}
+
// Type of the trampoline function passed to the custom version of
// dfsan_set_write_callback.
typedef void (*write_trampoline_t)(
// positional arguments.
static int format_buffer(char *str, size_t size, const char *fmt,
dfsan_label *va_labels, dfsan_label *ret_label,
+ dfsan_origin *va_origins, dfsan_origin *ret_origin,
va_list ap) {
Formatter formatter(str, fmt, size);
default:
retval = formatter.format(va_arg(ap, int));
}
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
end_fmt = true;
break;
} else {
retval = formatter.format(va_arg(ap, double));
}
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
end_fmt = true;
break;
case 'c':
retval = formatter.format(va_arg(ap, int));
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
end_fmt = true;
break;
case 's': {
char *arg = va_arg(ap, char *);
retval = formatter.format(arg);
+ if (va_origins) {
+ va_origins++;
+ dfsan_mem_origin_transfer(formatter.str_cur(), arg,
+ formatter.num_written_bytes(retval));
+ }
va_labels++;
internal_memcpy(shadow_for(formatter.str_cur()), shadow_for(arg),
sizeof(dfsan_label) *
case 'p':
retval = formatter.format(va_arg(ap, void *));
- dfsan_set_label(*va_labels++, formatter.str_cur(),
- formatter.num_written_bytes(retval));
+ if (va_origins == nullptr)
+ dfsan_set_label(*va_labels++, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ else
+ dfsan_set_label_origin(*va_labels++, *va_origins++,
+ formatter.str_cur(),
+ formatter.num_written_bytes(retval));
end_fmt = true;
break;
int *ptr = va_arg(ap, int *);
*ptr = (int)formatter.str_off;
va_labels++;
+ if (va_origins)
+ va_origins++;
dfsan_set_label(0, ptr, sizeof(ptr));
end_fmt = true;
break;
case '*':
formatter.width = va_arg(ap, int);
va_labels++;
+ if (va_origins)
+ va_origins++;
break;
default:
}
*ret_label = 0;
+ if (ret_origin)
+ *ret_origin = 0;
// Number of bytes written in total.
return formatter.str_off;
dfsan_label *ret_label, ...) {
va_list ap;
va_start(ap, ret_label);
- int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, ap);
+ int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
+ nullptr, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sprintf(char *str, const char *format, dfsan_label str_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, dfsan_origin str_origin,
+ dfsan_origin format_origin, dfsan_origin *va_origins,
+ dfsan_origin *ret_origin, ...) {
+ va_list ap;
+ va_start(ap, ret_origin);
+ int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, va_origins,
+ ret_origin, ap);
va_end(ap);
return ret;
}
dfsan_label *ret_label, ...) {
va_list ap;
va_start(ap, ret_label);
- int ret = format_buffer(str, size, format, va_labels, ret_label, ap);
+ int ret = format_buffer(str, size, format, va_labels, ret_label, nullptr,
+ nullptr, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_snprintf(char *str, size_t size, const char *format,
+ dfsan_label str_label, dfsan_label size_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, dfsan_origin str_origin,
+ dfsan_origin size_origin, dfsan_origin format_origin,
+ dfsan_origin *va_origins, dfsan_origin *ret_origin, ...) {
+ va_list ap;
+ va_start(ap, ret_origin);
+ int ret = format_buffer(str, size, format, va_labels, ret_label, va_origins,
+ ret_origin, ap);
va_end(ap);
return ret;
}
free(crv);
}
-#if !defined(ORIGIN_TRACKING)
void test_recvmmsg() {
int sockfds[2];
int ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sockfds);
dfsan_set_label(i_label, &rmmsg[1].msg_len, sizeof(rmmsg[1].msg_len));
dfsan_set_label(i_label, &timeout, sizeof(timeout));
+ dfsan_origin msg_len0_o = dfsan_get_origin((long)(rmmsg[0].msg_len));
+ dfsan_origin msg_len1_o = dfsan_get_origin((long)(rmmsg[1].msg_len));
+
// Receive messages and check labels.
int received_msgs = recvmmsg(sockfds[1], rmmsg, 2, 0, &timeout);
assert(received_msgs == sent_msgs);
ASSERT_LABEL(timeout.tv_sec, i_label);
ASSERT_LABEL(timeout.tv_nsec, i_label);
+ ASSERT_ORIGIN((long)(rmmsg[0].msg_len), msg_len0_o);
+ ASSERT_ORIGIN((long)(rmmsg[1].msg_len), msg_len1_o);
+
close(sockfds[0]);
close(sockfds[1]);
}
dfsan_set_label(i_label, rbuf, sizeof(rbuf));
dfsan_set_label(i_label, &rmsg, sizeof(rmsg));
+ DEFINE_AND_SAVE_ORIGINS(rmsg)
+
ssize_t received = recvmsg(sockfds[1], &rmsg, 0);
assert(received == sent);
assert(memcmp(sbuf, rbuf, 8) == 0);
ASSERT_READ_ZERO_LABEL(&rbuf[0], 8);
ASSERT_READ_LABEL(&rbuf[8], 1, i_label);
+ ASSERT_SAVED_ORIGINS(rmsg)
+
close(sockfds[0]);
close(sockfds[1]);
}
-#endif // !defined(ORIGIN_TRACKING)
void test_read() {
char buf[16];
assert(getrusage(RUSAGE_SELF, &usage) == 0);
ASSERT_READ_ZERO_LABEL(&usage, sizeof(usage));
}
+#endif // !defined(ORIGIN_TRACKING)
void test_strcpy() {
char src[] = "hello world";
}
void test_strtol() {
- char buf[] = "1234578910";
+ char non_number_buf[] = "ab ";
char *endptr = NULL;
+ long int ret = strtol(non_number_buf, &endptr, 10);
+ assert(ret == 0);
+ assert(endptr == non_number_buf);
+ ASSERT_ZERO_LABEL(ret);
+
+ char buf[] = "1234578910";
+ int base = 10;
+ dfsan_set_label(k_label, &base, sizeof(base));
+ ret = strtol(buf, &endptr, base);
+ assert(ret == 1234578910);
+ assert(endptr == buf + 10);
+ ASSERT_LABEL(ret, k_label);
+ ASSERT_EQ_ORIGIN(ret, base);
+
dfsan_set_label(i_label, buf + 1, 1);
dfsan_set_label(j_label, buf + 10, 1);
- long int ret = strtol(buf, &endptr, 10);
+ ret = strtol(buf, &endptr, 10);
assert(ret == 1234578910);
assert(endptr == buf + 10);
ASSERT_LABEL(ret, i_j_label);
+ ASSERT_EQ_ORIGIN(ret, buf[1]);
}
void test_strtoll() {
- char buf[] = "1234578910 ";
+ char non_number_buf[] = "ab ";
char *endptr = NULL;
+ long long int ret = strtoll(non_number_buf, &endptr, 10);
+ assert(ret == 0);
+ assert(endptr == non_number_buf);
+ ASSERT_ZERO_LABEL(ret);
+
+ char buf[] = "1234578910 ";
+ int base = 10;
+ dfsan_set_label(k_label, &base, sizeof(base));
+ ret = strtoll(buf, &endptr, base);
+ assert(ret == 1234578910);
+ assert(endptr == buf + 10);
+ ASSERT_LABEL(ret, k_label);
+ ASSERT_EQ_ORIGIN(ret, base);
+
dfsan_set_label(i_label, buf + 1, 1);
dfsan_set_label(j_label, buf + 2, 1);
- long long int ret = strtoll(buf, &endptr, 10);
+ ret = strtoll(buf, &endptr, 10);
assert(ret == 1234578910);
assert(endptr == buf + 10);
ASSERT_LABEL(ret, i_j_label);
+ ASSERT_EQ_ORIGIN(ret, buf[1]);
}
void test_strtoul() {
- char buf[] = "ffffffffffffaa";
+ char non_number_buf[] = "xy ";
char *endptr = NULL;
+ long unsigned int ret = strtoul(non_number_buf, &endptr, 16);
+ assert(ret == 0);
+ assert(endptr == non_number_buf);
+ ASSERT_ZERO_LABEL(ret);
+
+ char buf[] = "ffffffffffffaa";
+ int base = 16;
+ dfsan_set_label(k_label, &base, sizeof(base));
+ ret = strtoul(buf, &endptr, base);
+ assert(ret == 72057594037927850);
+ assert(endptr == buf + 14);
+ ASSERT_LABEL(ret, k_label);
+ ASSERT_EQ_ORIGIN(ret, base);
+
dfsan_set_label(i_label, buf + 1, 1);
dfsan_set_label(j_label, buf + 2, 1);
- long unsigned int ret = strtol(buf, &endptr, 16);
+ ret = strtoul(buf, &endptr, 16);
assert(ret == 72057594037927850);
assert(endptr == buf + 14);
ASSERT_LABEL(ret, i_j_label);
+ ASSERT_EQ_ORIGIN(ret, buf[1]);
}
void test_strtoull() {
- char buf[] = "ffffffffffffffaa";
+ char non_number_buf[] = "xy ";
char *endptr = NULL;
+ long long unsigned int ret = strtoull(non_number_buf, &endptr, 16);
+ assert(ret == 0);
+ assert(endptr == non_number_buf);
+ ASSERT_ZERO_LABEL(ret);
+
+ char buf[] = "ffffffffffffffaa";
+ int base = 16;
+ dfsan_set_label(k_label, &base, sizeof(base));
+ ret = strtoull(buf, &endptr, base);
+ assert(ret == 0xffffffffffffffaa);
+ assert(endptr == buf + 16);
+ ASSERT_LABEL(ret, k_label);
+ ASSERT_EQ_ORIGIN(ret, base);
+
dfsan_set_label(i_label, buf + 1, 1);
dfsan_set_label(j_label, buf + 2, 1);
- long long unsigned int ret = strtoull(buf, &endptr, 16);
+ ret = strtoull(buf, &endptr, 16);
assert(ret == 0xffffffffffffffaa);
assert(endptr == buf + 16);
ASSERT_LABEL(ret, i_j_label);
+ ASSERT_EQ_ORIGIN(ret, buf[1]);
}
void test_strtod() {
- char buf[] = "12345.76 foo";
+ char non_number_buf[] = "ab ";
char *endptr = NULL;
+ double ret = strtod(non_number_buf, &endptr);
+ assert(ret == 0);
+ assert(endptr == non_number_buf);
+ ASSERT_ZERO_LABEL(ret);
+
+ char buf[] = "12345.76 foo";
dfsan_set_label(i_label, buf + 1, 1);
dfsan_set_label(j_label, buf + 6, 1);
- double ret = strtod(buf, &endptr);
+ ret = strtod(buf, &endptr);
assert(ret == 12345.76);
assert(endptr == buf + 8);
ASSERT_LABEL(ret, i_j_label);
+ ASSERT_EQ_ORIGIN(ret, buf[1]);
}
+#if !defined(ORIGIN_TRACKING)
void test_time() {
time_t t = 0;
dfsan_set_label(i_label, &t, 1);
ASSERT_SAVED_ORIGINS(old_altstack)
}
-#if !defined(ORIGIN_TRACKING)
void test_gettimeofday() {
struct timeval tv;
struct timezone tz;
dfsan_set_label(i_label, &tv, sizeof(tv));
dfsan_set_label(j_label, &tz, sizeof(tz));
+ DEFINE_AND_SAVE_ORIGINS(tv)
+ DEFINE_AND_SAVE_ORIGINS(tz)
int ret = gettimeofday(&tv, &tz);
assert(ret == 0);
ASSERT_READ_ZERO_LABEL(&tv, sizeof(tv));
ASSERT_READ_ZERO_LABEL(&tz, sizeof(tz));
+ ASSERT_SAVED_ORIGINS(tv)
+ ASSERT_SAVED_ORIGINS(tz)
}
-#endif // !defined(ORIGIN_TRACKING)
void *pthread_create_test_cb(void *p) {
assert(p == (void *)1);
ASSERT_ORIGIN(alignp, alignp_o);
}
-#if !defined(ORIGIN_TRACKING)
void test_strrchr() {
char str1[] = "str1str1";
+
+ char *p = str1;
+ dfsan_set_label(j_label, &p, sizeof(p));
+
+ char *rv = strrchr(p, 'r');
+ assert(rv == &str1[6]);
+ ASSERT_LABEL(rv, j_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, p);
+
+ char c = 'r';
+ dfsan_set_label(k_label, &c, sizeof(c));
+ rv = strrchr(str1, c);
+ assert(rv == &str1[6]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(rv);
+#else
+ ASSERT_LABEL(rv, k_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, c);
+#endif
+
dfsan_set_label(i_label, &str1[7], 1);
- char *rv = strrchr(str1, 'r');
+ rv = strrchr(str1, 'r');
assert(rv == &str1[6]);
#ifdef STRICT_DATA_DEPENDENCIES
ASSERT_ZERO_LABEL(rv);
#else
ASSERT_LABEL(rv, i_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str1[7]);
#endif
}
void test_strstr() {
char str1[] = "str1str1";
+
+ char *p1 = str1;
+ dfsan_set_label(k_label, &p1, sizeof(p1));
+ char *rv = strstr(p1, "1s");
+ assert(rv == &str1[3]);
+ ASSERT_LABEL(rv, k_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, p1);
+
+ char str2[] = "1s";
+ char *p2 = str2;
+ dfsan_set_label(m_label, &p2, sizeof(p2));
+ rv = strstr(str1, p2);
+ assert(rv == &str1[3]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(rv);
+#else
+ ASSERT_LABEL(rv, m_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, p2);
+#endif
+
+ dfsan_set_label(n_label, &str2[0], 1);
+ rv = strstr(str1, str2);
+ assert(rv == &str1[3]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(rv);
+#else
+ ASSERT_LABEL(rv, n_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str2[0]);
+#endif
+
dfsan_set_label(i_label, &str1[3], 1);
dfsan_set_label(j_label, &str1[5], 1);
- char *rv = strstr(str1, "1s");
+ rv = strstr(str1, "1s");
assert(rv == &str1[3]);
#ifdef STRICT_DATA_DEPENDENCIES
ASSERT_ZERO_LABEL(rv);
#else
ASSERT_LABEL(rv, i_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str1[3]);
#endif
rv = strstr(str1, "2s");
ASSERT_ZERO_LABEL(rv);
#else
ASSERT_LABEL(rv, i_j_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, str1[3]);
#endif
}
-#endif // !defined(ORIGIN_TRACKING)
void test_strpbrk() {
char s[] = "abcdefg";
#endif
}
-#if !defined(ORIGIN_TRACKING)
void test_memchr() {
char str1[] = "str1";
dfsan_set_label(i_label, &str1[3], 1);
assert(crv == &str1[2]);
ASSERT_ZERO_LABEL(crv);
+ char c = 'r';
+ dfsan_set_label(k_label, &c, sizeof(c));
+ crv = (char *)memchr(str1, c, sizeof(str1));
+ assert(crv == &str1[2]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(crv);
+#else
+ ASSERT_LABEL(crv, k_label);
+ ASSERT_EQ_ORIGIN(crv, c);
+#endif
+
+ char *ptr = str1;
+ dfsan_set_label(k_label, &ptr, sizeof(ptr));
+ crv = (char *)memchr(ptr, 'r', sizeof(str1));
+ assert(crv == &str1[2]);
+ ASSERT_LABEL(crv, k_label);
+ ASSERT_EQ_ORIGIN(crv, ptr);
+
crv = (char *) memchr(str1, '1', sizeof(str1));
assert(crv == &str1[3]);
#ifdef STRICT_DATA_DEPENDENCIES
ASSERT_ZERO_LABEL(crv);
#else
ASSERT_LABEL(crv, i_label);
+ ASSERT_EQ_ORIGIN(crv, str1[3]);
#endif
crv = (char *) memchr(str1, 'x', sizeof(str1));
ASSERT_ZERO_LABEL(crv);
#else
ASSERT_LABEL(crv, i_j_label);
+ ASSERT_EQ_ORIGIN(crv, str1[3]);
#endif
}
req.tv_sec = 1;
req.tv_nsec = 0;
dfsan_set_label(i_label, &rem, sizeof(rem));
+ DEFINE_AND_SAVE_ORIGINS(rem)
// non interrupted
int rv = nanosleep(&req, &rem);
assert(rv == 0);
ASSERT_ZERO_LABEL(rv);
ASSERT_READ_LABEL(&rem, 1, i_label);
+ ASSERT_SAVED_ORIGINS(rem)
// interrupted by an alarm
signal(SIGALRM, alarm_handler);
assert(rv == -1);
ASSERT_ZERO_LABEL(rv);
ASSERT_READ_ZERO_LABEL(&rem, sizeof(rem));
+ ASSERT_SAVED_ORIGINS(rem)
}
void test_socketpair() {
int fd[2];
+ dfsan_origin fd_o[2];
dfsan_set_label(i_label, fd, sizeof(fd));
+ fd_o[0] = dfsan_get_origin((long)(fd[0]));
+ fd_o[1] = dfsan_get_origin((long)(fd[1]));
int rv = socketpair(PF_LOCAL, SOCK_STREAM, 0, fd);
assert(rv == 0);
ASSERT_ZERO_LABEL(rv);
ASSERT_READ_ZERO_LABEL(fd, sizeof(fd));
+ ASSERT_ORIGIN(fd[0], fd_o[0]);
+ ASSERT_ORIGIN(fd[1], fd_o[1]);
}
void test_getpeername() {
socklen_t addrlen = sizeof(addr);
dfsan_set_label(i_label, &addr, addrlen);
dfsan_set_label(i_label, &addrlen, sizeof(addrlen));
+ DEFINE_AND_SAVE_ORIGINS(addr)
+ DEFINE_AND_SAVE_ORIGINS(addrlen)
ret = getpeername(sockfds[0], &addr, &addrlen);
assert(ret != -1);
assert(addrlen < sizeof(addr));
ASSERT_READ_ZERO_LABEL(&addr, addrlen);
ASSERT_READ_LABEL(((char *)&addr) + addrlen, 1, i_label);
+ ASSERT_SAVED_ORIGINS(addr)
+ ASSERT_SAVED_ORIGINS(addrlen)
close(sockfds[0]);
close(sockfds[1]);
socklen_t addrlen = sizeof(addr);
dfsan_set_label(i_label, &addr, addrlen);
dfsan_set_label(i_label, &addrlen, sizeof(addrlen));
-
+ DEFINE_AND_SAVE_ORIGINS(addr)
+ DEFINE_AND_SAVE_ORIGINS(addrlen)
int ret = getsockname(sockfd, &addr, &addrlen);
assert(ret != -1);
ASSERT_ZERO_LABEL(ret);
assert(addrlen < sizeof(addr));
ASSERT_READ_ZERO_LABEL(&addr, addrlen);
ASSERT_READ_LABEL(((char *)&addr) + addrlen, 1, i_label);
+ ASSERT_SAVED_ORIGINS(addr)
+ ASSERT_SAVED_ORIGINS(addrlen)
close(sockfd);
}
socklen_t optlen = sizeof(optval);
dfsan_set_label(i_label, &optval, sizeof(optval));
dfsan_set_label(i_label, &optlen, sizeof(optlen));
+ DEFINE_AND_SAVE_ORIGINS(optval)
+ DEFINE_AND_SAVE_ORIGINS(optlen)
int ret = getsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen);
assert(ret != -1);
assert(optlen == sizeof(int));
ASSERT_ZERO_LABEL(optlen);
ASSERT_ZERO_LABEL(optval[0]);
ASSERT_LABEL(optval[1], i_label);
+ ASSERT_SAVED_ORIGINS(optval)
+ ASSERT_SAVED_ORIGINS(optlen)
close(sockfd);
}
-#endif // !defined(ORIGIN_TRACKING)
void test_write() {
int fd = open("/dev/null", O_WRONLY);
close(fd);
}
-#if !defined(ORIGIN_TRACKING)
template <class T>
void test_sprintf_chunk(const char* expected, const char* format, T arg) {
char buf[512];
// Labelled arg.
dfsan_set_label(i_label, &arg, sizeof(arg));
+ dfsan_origin a_o = dfsan_get_origin((long)(arg));
assert(sprintf(buf, padded_format, arg) == strlen(padded_expected));
assert(strcmp(buf, padded_expected) == 0);
ASSERT_READ_LABEL(buf, 4, 0);
ASSERT_READ_LABEL(buf + 4, strlen(padded_expected) - 8, i_label);
+ ASSERT_INIT_ORIGINS(buf + 4, strlen(padded_expected) - 8, a_o);
ASSERT_READ_LABEL(buf + (strlen(padded_expected) - 4), 4, 0);
}
int m = 8;
int d = 27;
dfsan_set_label(k_label, (void *) (s + 1), 2);
+ dfsan_origin s_o = dfsan_get_origin((long)(s[1]));
dfsan_set_label(i_label, &m, sizeof(m));
+ dfsan_origin m_o = dfsan_get_origin((long)m);
dfsan_set_label(j_label, &d, sizeof(d));
+ dfsan_origin d_o = dfsan_get_origin((long)d);
int n;
int r = sprintf(buf, "hello %s, %-d/%d/%d %f %% %n%d", s, 2014, m, d,
12345.6781234, &n, 1000);
assert(strcmp(buf, "hello world, 2014/8/27 12345.678123 % 1000") == 0);
ASSERT_READ_LABEL(buf, 7, 0);
ASSERT_READ_LABEL(buf + 7, 2, k_label);
+ ASSERT_INIT_ORIGINS(buf + 7, 2, s_o);
ASSERT_READ_LABEL(buf + 9, 9, 0);
ASSERT_READ_LABEL(buf + 18, 1, i_label);
+ ASSERT_INIT_ORIGINS(buf + 18, 1, m_o);
ASSERT_READ_LABEL(buf + 19, 1, 0);
ASSERT_READ_LABEL(buf + 20, 2, j_label);
+ ASSERT_INIT_ORIGINS(buf + 20, 2, d_o);
ASSERT_READ_LABEL(buf + 22, 15, 0);
ASSERT_LABEL(r, 0);
assert(n == 38);
int m = 8;
int d = 27;
dfsan_set_label(k_label, (void *) (s + 1), 2);
+ dfsan_origin s_o = dfsan_get_origin((long)(s[1]));
dfsan_set_label(i_label, &y, sizeof(y));
+ dfsan_origin y_o = dfsan_get_origin((long)y);
dfsan_set_label(j_label, &m, sizeof(m));
- int r = snprintf(buf, 19, "hello %s, %-d/%d/%d %f", s, y, m, d,
+ dfsan_origin m_o = dfsan_get_origin((long)m);
+ int r = snprintf(buf, 19, "hello %s, %-d/ %d/%d %f", s, y, m, d,
12345.6781234);
// The return value is the number of bytes that would have been written to
// the final string if enough space had been available.
- assert(r == 35);
+ assert(r == 38);
assert(memcmp(buf, "hello world, 2014/", 19) == 0);
ASSERT_READ_LABEL(buf, 7, 0);
ASSERT_READ_LABEL(buf + 7, 2, k_label);
+ ASSERT_INIT_ORIGINS(buf + 7, 2, s_o);
ASSERT_READ_LABEL(buf + 9, 4, 0);
ASSERT_READ_LABEL(buf + 13, 4, i_label);
+ ASSERT_INIT_ORIGINS(buf + 13, 4, y_o);
ASSERT_READ_LABEL(buf + 17, 2, 0);
ASSERT_LABEL(r, 0);
}
-#endif // !defined(ORIGIN_TRACKING)
// Tested by a seperate source file. This empty function is here to appease the
// check-wrappers script.
test_get_current_dir_name();
test_getcwd();
test_gethostname();
+#endif // !defined(ORIGIN_TRACKING)
test_getpeername();
+#if !defined(ORIGIN_TRACKING)
test_getpwuid_r();
test_getrlimit();
test_getrusage();
+#endif // !defined(ORIGIN_TRACKING)
test_getsockname();
test_getsockopt();
test_gettimeofday();
+#if !defined(ORIGIN_TRACKING)
test_inet_pton();
test_localtime_r();
- test_memchr();
#endif // !defined(ORIGIN_TRACKING)
+ test_memchr();
test_memcmp();
test_memcpy();
test_memmove();
test_memset();
-#if !defined(ORIGIN_TRACKING)
test_nanosleep();
+#if !defined(ORIGIN_TRACKING)
test_poll();
#endif // !defined(ORIGIN_TRACKING)
test_pread();
test_pthread_create();
test_pthread_join();
test_read();
-#if !defined(ORIGIN_TRACKING)
test_recvmmsg();
test_recvmsg();
+#if !defined(ORIGIN_TRACKING)
test_sched_getaffinity();
test_select();
#endif // !defined(ORIGIN_TRACKING)
test_signal();
test_sigaltstack();
test_sigemptyset();
-#if !defined(ORIGIN_TRACKING)
test_snprintf();
test_socketpair();
test_sprintf();
-#endif // !defined(ORIGIN_TRACKING)
test_stat();
test_strcasecmp();
test_strchr();
test_strncmp();
test_strncpy();
test_strpbrk();
-#if !defined(ORIGIN_TRACKING)
test_strrchr();
test_strstr();
test_strtod();
test_strtoll();
test_strtoul();
test_strtoull();
+#if !defined(ORIGIN_TRACKING)
test_time();
#endif // !defined(ORIGIN_TRACKING)
test_write();