tkuchta updated this revision to Diff 487936.
tkuchta added a comment.
applied newer version of clang-format
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D141389/new/
https://reviews.llvm.org/D141389
Files:
compiler-rt/lib/dfsan/dfsan_custom.cpp
compiler-rt/lib/dfsan/done_abilist.txt
compiler-rt/test/dfsan/custom.cpp
Index: compiler-rt/test/dfsan/custom.cpp
===================================================================
--- compiler-rt/test/dfsan/custom.cpp
+++ compiler-rt/test/dfsan/custom.cpp
@@ -364,6 +364,47 @@
ASSERT_LABEL(dst[11], j_label);
}
+void test_strncat() {
+ char src[] = "world";
+ int volatile x = 0; // buffer to ensure src and dst do not share origins
+ (void)x;
+ char dst[] = "hello \0 ";
+ int volatile y = 0; // buffer to ensure dst and p do not share origins
+ (void)y;
+ char *p = dst;
+ dfsan_set_label(k_label, &p, sizeof(p));
+ dfsan_set_label(i_label, src, sizeof(src));
+ dfsan_set_label(j_label, dst, sizeof(dst));
+ dfsan_origin dst_o = dfsan_get_origin((long)dst[0]);
+ (void)dst_o;
+ char *ret = strncat(p, src, strlen(src));
+ ASSERT_LABEL(ret, k_label);
+ ASSERT_EQ_ORIGIN(ret, p);
+ assert(ret == dst);
+ assert(strcmp(src, dst + 6) == 0);
+ // Origins are assigned for every 4 contiguous 4-aligned bytes. After
+ // appending src to dst, origins of src can overwrite origins of dst if their
+ // application adddresses are within [start_aligned_down, end_aligned_up).
+ // Other origins are not changed.
+ char *start_aligned_down = (char *)(((size_t)(dst + 6)) & ~3UL);
+ char *end_aligned_up = (char *)(((size_t)(dst + 11 + 4)) & ~3UL);
+ for (int i = 0; i < 12; ++i) {
+ if (dst + i < start_aligned_down || dst + i >= end_aligned_up) {
+ ASSERT_INIT_ORIGIN(&dst[i], dst_o);
+ } else {
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&dst[i], src[0]);
+ }
+ }
+ for (int i = 0; i < 6; ++i) {
+ ASSERT_LABEL(dst[i], j_label);
+ }
+ for (int i = 6; i < strlen(dst); ++i) {
+ ASSERT_LABEL(dst[i], i_label);
+ assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i - 6]));
+ }
+ ASSERT_LABEL(dst[11], j_label);
+}
+
void test_strlen() {
char str1[] = "str1";
dfsan_set_label(i_label, &str1[3], 1);
@@ -378,6 +419,20 @@
#endif
}
+void test_strnlen() {
+ char str1[] = "str1";
+ dfsan_set_label(i_label, &str1[3], 1);
+
+ int rv = strnlen(str1, 4);
+ assert(rv == 4);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(rv);
+#else
+ ASSERT_LABEL(rv, i_label);
+ ASSERT_EQ_ORIGIN(rv, str1[3]);
+#endif
+}
+
void test_strdup() {
char str1[] = "str1";
dfsan_set_label(i_label, &str1[3], 1);
@@ -1627,6 +1682,77 @@
#endif
}
+void test_strsep() {
+ char *s = strdup("Hello world/");
+ char *delim = strdup(" /");
+
+ char *p_s = s;
+ char *base = s;
+ char *p_delim = delim;
+
+ dfsan_set_label(n_label, p_delim, sizeof(p_delim));
+
+ char *rv = strsep(&p_s, p_delim);
+ assert(rv == &base[0]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(rv);
+#else
+ ASSERT_LABEL(rv, n_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, *p_delim);
+#endif
+
+ dfsan_set_label(m_label, p_s, sizeof(p_s));
+ rv = strsep(&p_s, p_delim);
+
+ assert(rv == &base[6]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_LABEL(rv, m_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, base[6]);
+#else
+ ASSERT_LABEL(rv, dfsan_union(m_label, n_label));
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, base[6]);
+#endif
+
+ free(s);
+ s = strdup("Hello world/");
+ base = s;
+ free(delim);
+ delim = strdup(" /");
+ p_delim = delim;
+ dfsan_set_label(i_label, &s[7], 1);
+ dfsan_set_label(j_label, &delim[0], 1);
+
+ rv = strsep(&s, delim);
+ assert(rv == &base[0]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(rv);
+#else
+ ASSERT_LABEL(rv, j_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, delim[1]);
+#endif
+
+ char *ps = s;
+ dfsan_set_label(dfsan_union(j_label, dfsan_read_label(ps, strlen(ps))), ps,
+ strlen(ps));
+ rv = strsep(&ps, " /");
+ assert(rv == &base[6]);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_LABEL(rv, i_j_label);
+#else
+ ASSERT_LABEL(rv, i_j_label);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, base[6]);
+#endif
+ rv = strsep(&ps, " /");
+ assert(strlen(rv) == 0);
+#ifdef STRICT_DATA_DEPENDENCIES
+ ASSERT_ZERO_LABEL(ps);
+#else
+ ASSERT_ZERO_LABEL(rv);
+ ASSERT_INIT_ORIGIN_EQ_ORIGIN(&rv, 0);
+
+#endif
+}
+
void test_memchr() {
char str1[] = "str1";
dfsan_set_label(i_label, &str1[3], 1);
@@ -1968,6 +2094,138 @@
ASSERT_LABEL(r, 0);
}
+template <class T>
+void test_sscanf_chunk(T expected, const char *format, const char *input) {
+ char padded_input[512];
+ strcpy(padded_input, "foo ");
+ strcat(padded_input, input);
+ strcat(padded_input, " bar");
+
+ char padded_format[512];
+ strcpy(padded_format, "foo ");
+ strcat(padded_format, format);
+ strcat(padded_format, " bar");
+
+ // Non labelled arg.
+ T arg;
+ memset(&arg, 0, sizeof(arg));
+ sscanf(padded_input, padded_format, &arg);
+ assert(arg == expected);
+ ASSERT_READ_LABEL(&arg, sizeof(arg), 0);
+
+ // Labelled arg.
+ memset(&arg, 0, sizeof(arg));
+ dfsan_set_label(i_label, (void *)(padded_input + 4), strlen(input));
+ dfsan_origin a_o = dfsan_get_origin((long)(padded_input + 4));
+#ifndef ORIGIN_TRACKING
+ (void)a_o;
+#endif
+ sscanf(padded_input, padded_format, &arg);
+ assert(arg == expected);
+ ASSERT_READ_LABEL(&arg, sizeof(arg), i_label);
+ ASSERT_INIT_ORIGINS(&arg, sizeof(arg), a_o);
+}
+
+void test_sscanf() {
+ char buf[2048];
+ char buf_out[2048];
+ memset(buf, 'a', sizeof(buf));
+ memset(buf_out, 'a', sizeof(buf_out));
+
+ // Test formatting
+ strcpy(buf, "Hello world!");
+ assert(sscanf(buf, "%s", buf_out) == 1);
+ assert(strcmp(buf, "Hello world!") == 0);
+ assert(strcmp(buf_out, "Hello") == 0);
+ ASSERT_READ_LABEL(buf, sizeof(buf), 0);
+ ASSERT_READ_LABEL(buf_out, sizeof(buf_out), 0);
+
+ // Test for extra arguments.
+ assert(sscanf(buf, "%s", buf_out, 42, "hello") == 1);
+ assert(strcmp(buf, "Hello world!") == 0);
+ assert(strcmp(buf_out, "Hello") == 0);
+ ASSERT_READ_LABEL(buf, sizeof(buf), 0);
+ ASSERT_READ_LABEL(buf_out, sizeof(buf_out), 0);
+
+ // Test formatting & label propagation (multiple conversion specifiers): %s,
+ // %d, %n, %f, and %%.
+ int n;
+ strcpy(buf, "hello world, 2014/8/27 12345.678123 % 1000");
+ char *s = buf + 6; //starts with world
+ int y = 0;
+ int m = 0;
+ int d = 0;
+ float fval;
+ int val = 0;
+ dfsan_set_label(k_label, (void *)(s + 1), 2);
+ dfsan_origin s_o = dfsan_get_origin((long)(s[1]));
+ dfsan_set_label(i_label, (void *)(s + 12), 1);
+ dfsan_origin m_o = dfsan_get_origin((long)m);
+ dfsan_set_label(j_label, (void *)(s + 14), 2);
+ dfsan_origin d_o = dfsan_get_origin((long)d);
+ dfsan_set_label(m_label, (void *)(s + 17), sizeof(fval));
+ dfsan_origin f_o = dfsan_get_origin((long)fval);
+
+#ifndef ORIGIN_TRACKING
+ (void)s_o;
+ (void)m_o;
+ (void)d_o;
+ (void)f_o;
+#endif
+
+ int r = sscanf(buf, "hello %s %d/%d/%d %f %% %n%d", buf_out, &y, &m, &d,
+ &fval, &n, &val);
+ assert(r == 6);
+ assert(strcmp(buf_out, "world,") == 0);
+ ASSERT_READ_LABEL(buf_out, 1, 0);
+ ASSERT_READ_LABEL(buf_out + 1, 2, k_label);
+ ASSERT_INIT_ORIGINS(buf_out + 1, 2, s_o);
+ ASSERT_READ_LABEL(buf + 9, 9, 0);
+ ASSERT_READ_LABEL(&m, 4, i_label);
+ ASSERT_INIT_ORIGINS(&m, 4, m_o);
+ ASSERT_READ_LABEL(&d, 4, j_label);
+ ASSERT_INIT_ORIGINS(&d, 4, d_o);
+ ASSERT_READ_LABEL(&fval, sizeof(fval), m_label);
+ ASSERT_INIT_ORIGINS(&fval, sizeof(fval), f_o);
+ ASSERT_READ_LABEL(&val, 4, 0);
+ ASSERT_LABEL(r, 0);
+ assert(n == 38);
+ assert(val == 1000);
+
+ // Test formatting & label propagation (single conversion specifier, with
+ // additional length and precision modifiers).
+ test_sscanf_chunk(-559038737, "%d", "-559038737");
+ test_sscanf_chunk(3735928559, "%u", "3735928559");
+ test_sscanf_chunk(12345, "%i", "12345");
+ test_sscanf_chunk(489, "%o", "0751");
+ test_sscanf_chunk(47806, "%x", "0xbabe");
+ test_sscanf_chunk(47806, "%10X", "0x0000BABE");
+ test_sscanf_chunk((char)-17, "%hhd", "3735928559");
+ test_sscanf_chunk((short)-16657, "%hd", "3735928559");
+ test_sscanf_chunk(0xdeadbeefdeadbeefL, "%lx", "0xdeadbeefdeadbeef");
+ test_sscanf_chunk((void *)0xdeadbeefdeadbeefL, "%p", "0xdeadbeefdeadbeef");
+ intmax_t _x = (intmax_t)-1;
+ char _buf[256];
+ memset(_buf, 0, sizeof(_buf));
+ sprintf(_buf, "%ju", _x);
+ test_sscanf_chunk((intmax_t)18446744073709551615, "%ju", _buf);
+ memset(_buf, 0, sizeof(_buf));
+ size_t _y = (size_t)-1;
+ sprintf(_buf, "%zu", _y);
+ test_sscanf_chunk((size_t)18446744073709551615, "%zu", _buf);
+ memset(_buf, 0, sizeof(_buf));
+ ptrdiff_t _z = (size_t)-1;
+ sprintf(_buf, "%tu", _z);
+ test_sscanf_chunk((ptrdiff_t)18446744073709551615, "%tu", _buf);
+
+ test_sscanf_chunk((float)0.123456, "%8f", "0.123456");
+ test_sscanf_chunk((float)0.123456, "%g", "0.123456");
+ test_sscanf_chunk((float)1.234560e-01, "%e", "0.123456");
+ test_sscanf_chunk((char)'z', "%c", "z");
+
+ // %n, %s, %d, %f, and %% already tested
+}
+
// Tested by a seperate source file. This empty function is here to appease the
// check-wrappers script.
void test_fork() {}
@@ -2029,18 +2287,22 @@
test_snprintf();
test_socketpair();
test_sprintf();
+ test_sscanf();
test_stat();
test_strcasecmp();
test_strchr();
test_strcmp();
test_strcat();
+ test_strncat();
test_strcpy();
test_strdup();
test_strlen();
+ test_strnlen();
test_strncasecmp();
test_strncmp();
test_strncpy();
test_strpbrk();
+ test_strsep();
test_strrchr();
test_strstr();
test_strtod();
Index: compiler-rt/lib/dfsan/done_abilist.txt
===================================================================
--- compiler-rt/lib/dfsan/done_abilist.txt
+++ compiler-rt/lib/dfsan/done_abilist.txt
@@ -88,6 +88,7 @@
fun:ispunct=functional
fun:isspace=functional
fun:tolower=functional
+fun:_tolower=functional
fun:toupper=functional
# Functions that return a value that is data-dependent on the input.
@@ -268,6 +269,7 @@
fun:strtoul=custom
fun:strtoull=custom
fun:strcat=custom
+fun:strncat=custom
# Functions that produce an output that is computed from the input, but is not
# necessarily data dependent.
@@ -278,11 +280,13 @@
fun:strchr=custom
fun:strcmp=custom
fun:strlen=custom
+fun:strnlen=custom
fun:strncasecmp=custom
fun:strncmp=custom
fun:strpbrk=custom
fun:strrchr=custom
fun:strstr=custom
+fun:strsep=custom
# Functions which take action based on global state, such as running a callback
# set by a separate function.
@@ -304,6 +308,10 @@
fun:sprintf=custom
fun:snprintf=custom
+# scanf-like
+fun:sscanf=custom
+fun:__isoc99_sscanf=custom
+
# TODO: custom
fun:asprintf=discard
fun:qsort=discard
Index: compiler-rt/lib/dfsan/dfsan_custom.cpp
===================================================================
--- compiler-rt/lib/dfsan/dfsan_custom.cpp
+++ compiler-rt/lib/dfsan/dfsan_custom.cpp
@@ -204,6 +204,59 @@
return const_cast<char *>(ret);
}
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strsep(char **s, const char *delim,
+ dfsan_label s_label,
+ dfsan_label delim_label,
+ dfsan_label *ret_label) {
+ char *base = *s;
+ char *res = strsep(s, delim);
+ s_label = dfsan_read_label(base, strlen(base));
+ if (res && (res != base)) {
+ char *token_start = res;
+ int token_length = strlen(res);
+ // the delimiter byte has been set to NULL
+ dfsan_set_label(0, token_start + token_length, 1);
+ }
+
+ if (flags().strict_data_dependencies) {
+ *ret_label = res ? s_label : 0;
+ } else {
+ size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1;
+ *ret_label =
+ dfsan_union(dfsan_read_label(base, s_bytes_read),
+ dfsan_union(dfsan_read_label(delim, strlen(delim) + 1),
+ dfsan_union(s_label, delim_label)));
+ }
+
+ return res;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strsep(
+ char **s, const char *delim, dfsan_label s_label, dfsan_label delim_label,
+ dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin delim_origin,
+ dfsan_origin *ret_origin) {
+ char *base = *s;
+ s_origin = dfsan_read_origin_of_first_taint(base, strlen(base) + 1);
+ char *res = __dfsw_strsep(s, delim, s_label, delim_label, ret_label);
+ if (flags().strict_data_dependencies) {
+ if (res)
+ *ret_origin = s_origin;
+ } else {
+ if (*ret_label) {
+ size_t s_bytes_read = (res ? strlen(res) : strlen(base)) + 1;
+ dfsan_origin o = dfsan_read_origin_of_first_taint(base, s_bytes_read);
+ if (o) {
+ *ret_origin = o;
+ } else {
+ o = dfsan_read_origin_of_first_taint(delim, strlen(delim) + 1);
+ *ret_origin = o ? o : (s_label ? s_origin : delim_origin);
+ }
+ }
+ }
+
+ return res;
+}
+
static int dfsan_memcmp_bcmp(const void *s1, const void *s2, size_t n,
size_t *bytes_read) {
const char *cs1 = (const char *) s1, *cs2 = (const char *) s2;
@@ -484,6 +537,30 @@
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE size_t __dfsw_strnlen(const char *s,
+ size_t maxlen,
+ dfsan_label s_label,
+ dfsan_label maxlen_label,
+ dfsan_label *ret_label) {
+ size_t ret = strnlen(s, maxlen);
+ if (flags().strict_data_dependencies) {
+ *ret_label = 0;
+ } else {
+ *ret_label = dfsan_read_label(s, ret + 1);
+ }
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE size_t __dfso_strnlen(
+ const char *s, size_t maxlen, dfsan_label s_label, dfsan_label maxlen_label,
+ dfsan_label *ret_label, dfsan_origin s_origin, dfsan_origin maxlen_origin,
+ dfsan_origin *ret_origin) {
+ size_t ret = __dfsw_strnlen(s, maxlen, s_label, maxlen_label, ret_label);
+ if (!flags().strict_data_dependencies)
+ *ret_origin = dfsan_read_origin_of_first_taint(s, ret + 1);
+ return ret;
+}
+
static void *dfsan_memmove(void *dest, const void *src, size_t n) {
dfsan_label *sdest = shadow_for(dest);
const dfsan_label *ssrc = shadow_for(src);
@@ -601,6 +678,37 @@
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strncat(
+ char *dest, const char *src, size_t num, dfsan_label dest_label,
+ dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label) {
+ size_t src_len = strlen(src);
+ src_len = src_len < num ? src_len : num;
+ size_t dest_len = strlen(dest);
+
+ char *ret = strncat(dest, src, num);
+ dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
+ *ret_label = dest_label;
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strncat(
+ char *dest, const char *src, size_t num, dfsan_label dest_label,
+ dfsan_label src_label, dfsan_label num_label, dfsan_label *ret_label,
+ dfsan_origin dest_origin, dfsan_origin src_origin, dfsan_origin num_origin,
+ dfsan_origin *ret_origin) {
+ size_t src_len = strlen(src);
+ src_len = src_len < num ? src_len : num;
+ size_t dest_len = strlen(dest);
+
+ char *ret = strncat(dest, src, num);
+
+ dfsan_mem_origin_transfer(dest + dest_len, src, src_len);
+ dfsan_mem_shadow_transfer(dest + dest_len, src, src_len);
+ *ret_label = dest_label;
+ *ret_origin = dest_origin;
+ return ret;
+}
+
SANITIZER_INTERFACE_ATTRIBUTE char *
__dfsw_strdup(const char *s, dfsan_label s_label, dfsan_label *ret_label) {
size_t len = strlen(s);
@@ -2128,8 +2236,13 @@
// '%.3f').
struct Formatter {
Formatter(char *str_, const char *fmt_, size_t size_)
- : str(str_), str_off(0), size(size_), fmt_start(fmt_), fmt_cur(fmt_),
- width(-1) {}
+ : str(str_),
+ str_off(0),
+ size(size_),
+ fmt_start(fmt_),
+ fmt_cur(fmt_),
+ width(-1),
+ num_scanned(-1) {}
int format() {
char *tmp_fmt = build_format_string();
@@ -2154,12 +2267,50 @@
return retval;
}
- char *build_format_string() {
+ int scan() {
+ char *tmp_fmt = build_format_string(true);
+ int read_count = 0;
+ int retval = sscanf(str + str_off, tmp_fmt, &read_count);
+ if (retval > 0) {
+ if (-1 == num_scanned)
+ num_scanned = 0;
+ num_scanned += retval;
+ }
+ free(tmp_fmt);
+ return read_count;
+ }
+
+ template <typename T>
+ int scan(T arg) {
+ char *tmp_fmt = build_format_string(true);
+ int read_count = 0;
+ int retval = sscanf(str + str_off, tmp_fmt, arg, &read_count);
+ if (retval > 0) {
+ if (-1 == num_scanned)
+ num_scanned = 0;
+ num_scanned += retval;
+ }
+ free(tmp_fmt);
+ return read_count;
+ }
+
+ // with_n -> toggles adding %n on/off; off by default
+ char *build_format_string(bool with_n = false) {
size_t fmt_size = fmt_cur - fmt_start + 1;
- char *new_fmt = (char *)malloc(fmt_size + 1);
+ size_t add_size = 0;
+ if (with_n)
+ add_size = 2;
+ char *new_fmt = (char *)malloc(fmt_size + 1 + add_size);
assert(new_fmt);
internal_memcpy(new_fmt, fmt_start, fmt_size);
- new_fmt[fmt_size] = '\0';
+ if (!with_n) {
+ new_fmt[fmt_size] = '\0';
+ } else {
+ new_fmt[fmt_size] = '%';
+ new_fmt[fmt_size + 1] = 'n';
+ new_fmt[fmt_size + 2] = '\0';
+ }
+
return new_fmt;
}
@@ -2191,6 +2342,7 @@
const char *fmt_start;
const char *fmt_cur;
int width;
+ int num_scanned;
};
// Formats the input and propagates the input labels to the output. The output
@@ -2383,6 +2535,214 @@
return formatter.str_off;
}
+// This function is an inverse of format_buffer: we take the input buffer,
+// scan it in search for format strings and store the results in the varargs.
+// The labels are propagated from the input buffer to the varargs.
+static int scan_buffer(char *str, size_t size, const char *fmt,
+ dfsan_label *va_labels, dfsan_label *ret_label,
+ dfsan_origin *str_origin, dfsan_origin *ret_origin,
+ va_list ap) {
+ Formatter formatter(str, fmt, size);
+ while (*formatter.fmt_cur) {
+ formatter.fmt_start = formatter.fmt_cur;
+ formatter.width = -1;
+ int retval = 0;
+ dfsan_label l = 0;
+ void *dst_ptr = 0;
+ size_t write_size = 0;
+ if (*formatter.fmt_cur != '%') {
+ // Ordinary character. Consume all the characters until a '%' or the end
+ // of the string.
+ for (; *(formatter.fmt_cur + 1) && *(formatter.fmt_cur + 1) != '%';
+ ++formatter.fmt_cur) {
+ }
+ retval = formatter.scan();
+ dfsan_set_label(0, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ } else {
+ // Conversion directive. Consume all the characters until a conversion
+ // specifier or the end of the string.
+ bool end_fmt = false;
+ for (; *formatter.fmt_cur && !end_fmt;) {
+ switch (*++formatter.fmt_cur) {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ switch (*(formatter.fmt_cur - 1)) {
+ case 'h':
+ // Also covers the 'hh' case (since the size of the arg is still
+ // an int).
+ dst_ptr = va_arg(ap, int *);
+ retval = formatter.scan((int *)dst_ptr);
+ write_size = sizeof(int);
+ break;
+ case 'l':
+ if (formatter.fmt_cur - formatter.fmt_start >= 2 &&
+ *(formatter.fmt_cur - 2) == 'l') {
+ dst_ptr = va_arg(ap, long long int *);
+ retval = formatter.scan((long long int *)dst_ptr);
+ write_size = sizeof(long long int);
+ } else {
+ dst_ptr = va_arg(ap, long int *);
+ retval = formatter.scan((long int *)dst_ptr);
+ write_size = sizeof(long int);
+ }
+ break;
+ case 'q':
+ dst_ptr = va_arg(ap, long long int *);
+ retval = formatter.scan((long long int *)dst_ptr);
+ write_size = sizeof(long long int);
+ break;
+ case 'j':
+ dst_ptr = va_arg(ap, intmax_t *);
+ retval = formatter.scan((intmax_t *)dst_ptr);
+ write_size = sizeof(intmax_t);
+ break;
+ case 'z':
+ case 't':
+ dst_ptr = va_arg(ap, size_t *);
+ retval = formatter.scan((size_t *)dst_ptr);
+ write_size = sizeof(size_t);
+ break;
+ default:
+ dst_ptr = va_arg(ap, int *);
+ retval = formatter.scan((int *)dst_ptr);
+ write_size = sizeof(int);
+ }
+ // get the label associated with the string at the corresponding
+ // place
+ l = dfsan_read_label(formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ if (str_origin == nullptr)
+ dfsan_set_label(l, dst_ptr, write_size);
+ else
+ dfsan_set_label_origin(l, *str_origin, dst_ptr, write_size);
+ end_fmt = true;
+
+ break;
+
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ if (*(formatter.fmt_cur - 1) == 'L') {
+ dst_ptr = va_arg(ap, long double *);
+ retval = formatter.scan((long double *)dst_ptr);
+ write_size = sizeof(long double);
+ } else if (*(formatter.fmt_cur - 1) == 'l') {
+ dst_ptr = va_arg(ap, double *);
+ retval = formatter.scan((double *)dst_ptr);
+ write_size = sizeof(double);
+ } else {
+ dst_ptr = va_arg(ap, float *);
+ retval = formatter.scan((float *)dst_ptr);
+ write_size = sizeof(float);
+ }
+ l = dfsan_read_label(formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ if (str_origin == nullptr)
+ dfsan_set_label(l, dst_ptr, write_size);
+ else
+ dfsan_set_label_origin(l, *str_origin, dst_ptr, write_size);
+ end_fmt = true;
+ break;
+
+ case 'c':
+ dst_ptr = va_arg(ap, char *);
+ retval = formatter.scan((char *)dst_ptr);
+ write_size = sizeof(char);
+ l = dfsan_read_label(formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ if (str_origin == nullptr)
+ dfsan_set_label(l, dst_ptr, write_size);
+ else
+ dfsan_set_label_origin(l, *str_origin, dst_ptr, write_size);
+ end_fmt = true;
+ break;
+
+ case 's': {
+ dst_ptr = va_arg(ap, char *);
+ retval = formatter.scan((char *)dst_ptr);
+ if (1 == retval) {
+ // special case: we have parsed a single string and we need to
+ // update retval with the string size
+ retval = strlen((char *)dst_ptr);
+ }
+ if (str_origin) {
+ dfsan_mem_origin_transfer(dst_ptr, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ }
+ va_labels++;
+ dfsan_mem_shadow_transfer(dst_ptr, formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ end_fmt = true;
+ break;
+ }
+
+ case 'p':
+ dst_ptr = va_arg(ap, void *);
+ retval =
+ formatter.scan((int *)dst_ptr); // note: changing void* to int*
+ // since we need to call sizeof
+ write_size = sizeof(int);
+
+ l = dfsan_read_label(formatter.str_cur(),
+ formatter.num_written_bytes(retval));
+ if (str_origin == nullptr)
+ dfsan_set_label(l, dst_ptr, write_size);
+ else
+ dfsan_set_label_origin(l, *str_origin, dst_ptr, write_size);
+ end_fmt = true;
+ break;
+
+ case 'n': {
+ int *ptr = va_arg(ap, int *);
+ *ptr = (int)formatter.str_off;
+ va_labels++;
+ dfsan_set_label(0, ptr, sizeof(*ptr));
+ end_fmt = true;
+ break;
+ }
+
+ case '%':
+ retval = formatter.scan();
+ end_fmt = true;
+ break;
+
+ case '*':
+ formatter.width = va_arg(ap, int);
+ va_labels++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (retval < 0) {
+ return retval;
+ }
+
+ formatter.fmt_cur++;
+ formatter.str_off += retval;
+ }
+
+ *ret_label = 0;
+ if (ret_origin)
+ *ret_origin = 0;
+
+ // Number of items scanned in total.
+ return formatter.num_scanned;
+}
+
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
int __dfsw_sprintf(char *str, const char *format, dfsan_label str_label,
@@ -2390,6 +2750,7 @@
dfsan_label *ret_label, ...) {
va_list ap;
va_start(ap, ret_label);
+
int ret = format_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
nullptr, ap);
va_end(ap);
@@ -2438,6 +2799,58 @@
return ret;
}
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw_sscanf(char *str, const char *format, dfsan_label str_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, ...) {
+ va_list ap;
+ va_start(ap, ret_label);
+ int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
+ nullptr, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso_sscanf(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 = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,
+ ret_origin, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfsw___isoc99_sscanf(char *str, const char *format, dfsan_label str_label,
+ dfsan_label format_label, dfsan_label *va_labels,
+ dfsan_label *ret_label, ...) {
+ va_list ap;
+ va_start(ap, ret_label);
+ int ret = scan_buffer(str, ~0ul, format, va_labels, ret_label, nullptr,
+ nullptr, ap);
+ va_end(ap);
+ return ret;
+}
+
+SANITIZER_INTERFACE_ATTRIBUTE
+int __dfso___isoc99_sscanf(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 = scan_buffer(str, ~0ul, format, va_labels, ret_label, &str_origin,
+ ret_origin, ap);
+ va_end(ap);
+ return ret;
+}
+
static void BeforeFork() {
StackDepotLockAll();
GetChainedOriginDepot()->LockAll();
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits