[compiler-rt] d9b3691 - [DFSAN] Add support for strncat

Andrew Browne via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 21 14:21:32 PDT 2023


Author: Tomasz Kuchta
Date: 2023-06-21T21:21:13Z
New Revision: d9b3691166f1cf60c2c6746fd6ed777787740c84

URL: https://github.com/llvm/llvm-project/commit/d9b3691166f1cf60c2c6746fd6ed777787740c84
DIFF: https://github.com/llvm/llvm-project/commit/d9b3691166f1cf60c2c6746fd6ed777787740c84.diff

LOG: [DFSAN] Add support for strncat

This patch adds a support for the libc strncat() function in DFSAN

Reviewed by: browneee

Differential Revision: https://reviews.llvm.org/D152196

Added: 
    

Modified: 
    compiler-rt/lib/dfsan/dfsan_custom.cpp
    compiler-rt/lib/dfsan/done_abilist.txt
    compiler-rt/test/dfsan/custom.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp
index e63e68084fa32..f41dd50617fbc 100644
--- a/compiler-rt/lib/dfsan/dfsan_custom.cpp
+++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp
@@ -682,6 +682,37 @@ SANITIZER_INTERFACE_ATTRIBUTE char *__dfso_strcat(
   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);

diff  --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt
index cc3578b95cd49..df5eedcafeb86 100644
--- a/compiler-rt/lib/dfsan/done_abilist.txt
+++ b/compiler-rt/lib/dfsan/done_abilist.txt
@@ -268,6 +268,7 @@ fun:strtoll=custom
 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.

diff  --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp
index 62483c1ed96f2..c67602d4538e6 100644
--- a/compiler-rt/test/dfsan/custom.cpp
+++ b/compiler-rt/test/dfsan/custom.cpp
@@ -340,6 +340,7 @@ void test_strcat() {
   dfsan_origin dst_o = dfsan_get_origin((long)dst[0]);
   (void)dst_o;
   char *ret = strcat(p, src);
+
   ASSERT_LABEL(ret, k_label);
   ASSERT_EQ_ORIGIN(ret, p);
   assert(ret == dst);
@@ -367,6 +368,56 @@ void test_strcat() {
   ASSERT_LABEL(dst[11], j_label);
 }
 
+void test_strncat(int n) {
+  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, n);
+
+  ASSERT_LABEL(ret, k_label);
+  ASSERT_EQ_ORIGIN(ret, p);
+  assert(ret == dst);
+  assert(strncmp(src, dst + 6, n) == 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.
+  int pad = n % 4;
+  if (pad)
+    pad = 4 - pad;
+
+  char *start_aligned_down = (char *)(((size_t)(dst + 6)) & ~3UL);
+  char *end_aligned_up = (char *)(((size_t)(dst + 6 + n + pad)) & ~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 < 6 + n; ++i) {
+    ASSERT_LABEL(dst[i], i_label);
+    assert(dfsan_get_label(dst[i]) == dfsan_get_label(src[i - 6]));
+  }
+  for (int i = 6 + n; i < strlen(dst); ++i) {
+    ASSERT_LABEL(dst[i], j_label);
+  }
+  ASSERT_LABEL(dst[11], j_label);
+}
+
 void test_strlen() {
   char str1[] = "str1";
   dfsan_set_label(i_label, &str1[3], 1);
@@ -2110,6 +2161,8 @@ int main(void) {
   test_strchr();
   test_strcmp();
   test_strcat();
+  test_strncat(5);
+  test_strncat(2);
   test_strcpy();
   test_strdup();
   test_strlen();


        


More information about the llvm-commits mailing list