diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -652,6 +652,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); diff --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt --- a/compiler-rt/lib/dfsan/done_abilist.txt +++ b/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. diff --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp --- a/compiler-rt/test/dfsan/custom.cpp +++ b/compiler-rt/test/dfsan/custom.cpp @@ -326,7 +326,7 @@ #endif } -void test_strcat() { +void _test_strcat(int _strncat) { char src[] = "world"; int volatile x = 0; // buffer to ensure src and dst do not share origins (void)x; @@ -339,7 +339,12 @@ dfsan_set_label(j_label, dst, sizeof(dst)); dfsan_origin dst_o = dfsan_get_origin((long)dst[0]); (void)dst_o; - char *ret = strcat(p, src); + char *ret = 0; + if (!_strncat) + ret = strcat(p, src); + else + ret = strncat(p, src, strlen(src)); + ASSERT_LABEL(ret, k_label); ASSERT_EQ_ORIGIN(ret, p); assert(ret == dst); @@ -367,6 +372,10 @@ ASSERT_LABEL(dst[11], j_label); } +void test_strcat() { _test_strcat(0); } + +void test_strncat() { _test_strcat(1); } + void test_strlen() { char str1[] = "str1"; dfsan_set_label(i_label, &str1[3], 1); @@ -2082,6 +2091,7 @@ test_strchr(); test_strcmp(); test_strcat(); + test_strncat(); test_strcpy(); test_strdup(); test_strlen();