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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to