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 @@ -353,6 +353,20 @@ return s; } +SANITIZER_INTERFACE_ATTRIBUTE char *__dfsw_strcat(char *dest, const char *src, + dfsan_label dest_label, + dfsan_label src_label, + dfsan_label *ret_label) { + size_t dest_len = strlen(dest); + char *ret = strcat(dest, src); + dfsan_label *sdest = shadow_for(dest + dest_len); + const dfsan_label *ssrc = shadow_for(src); + internal_memcpy((void *)sdest, (const void *)ssrc, + strlen(src) * sizeof(dfsan_label)); + *ret_label = dest_label; + 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 @@ -224,6 +224,7 @@ fun:strtoll=custom fun:strtoul=custom fun:strtoull=custom +fun:strcat=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 @@ -155,6 +155,27 @@ #endif } +void test_strcat() { + char src[] = "world"; + char dst[] = "hello \0 "; + 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)); + char *ret = strcat(p, src); + ASSERT_LABEL(ret, k_label); + assert(ret == dst); + assert(strcmp(src, dst + 6) == 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); @@ -1360,6 +1381,7 @@ test_strcasecmp(); test_strchr(); test_strcmp(); + test_strcat(); test_strcpy(); test_strdup(); test_strlen();