Index: lib/sanitizer_common/sanitizer_libc.h =================================================================== --- lib/sanitizer_common/sanitizer_libc.h +++ lib/sanitizer_common/sanitizer_libc.h @@ -43,8 +43,10 @@ char *internal_strdup(const char *s); char *internal_strndup(const char *s, uptr n); uptr internal_strlen(const char *s); +uptr internal_strlcat(char *dst, const char *src, uptr maxlen); char *internal_strncat(char *dst, const char *src, uptr n); int internal_strncmp(const char *s1, const char *s2, uptr n); +uptr internal_strlcpy(char *dst, const char *src, uptr maxlen); char *internal_strncpy(char *dst, const char *src, uptr n); uptr internal_strnlen(const char *s, uptr maxlen); char *internal_strrchr(const char *s, int c); Index: lib/sanitizer_common/sanitizer_libc.cc =================================================================== --- lib/sanitizer_common/sanitizer_libc.cc +++ lib/sanitizer_common/sanitizer_libc.cc @@ -175,6 +175,19 @@ return i; } +uptr internal_strlcat(char *dst, const char *src, uptr maxlen) { + const uptr srclen = internal_strlen(src); + const uptr dstlen = internal_strnlen(dst, maxlen); + if (dstlen == maxlen) return maxlen+srclen; + if (srclen < maxlen-dstlen) { + internal_memcpy(dst+dstlen, src, srclen+1); + } else { + internal_memcpy(dst+dstlen, src, maxlen-dstlen-1); + dst[maxlen-1] = '\0'; + } + return dstlen + srclen; +} + char *internal_strncat(char *dst, const char *src, uptr n) { uptr len = internal_strlen(dst); uptr i; @@ -184,6 +197,17 @@ return dst; } +uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) { + const uptr srclen = internal_strlen(src); + if (srclen < maxlen) { + internal_memcpy(dst, src, srclen+1); + } else if (maxlen != 0) { + internal_memcpy(dst, src, maxlen-1); + dst[maxlen-1] = '\0'; + } + return srclen; +} + char *internal_strncpy(char *dst, const char *src, uptr n) { uptr i; for (i = 0; i < n && src[i]; i++) Index: lib/sanitizer_common/tests/sanitizer_libc_test.cc =================================================================== --- lib/sanitizer_common/tests/sanitizer_libc_test.cc +++ lib/sanitizer_common/tests/sanitizer_libc_test.cc @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// // Tests for sanitizer_libc.h. //===----------------------------------------------------------------------===// +#include #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" @@ -145,12 +146,65 @@ #endif } +#define STRLCPY_BUF_SIZE 8 +void test_internal_strlcpy(char *dbuf, const char *sbuf) { + uptr retval = 0; + retval = internal_strlcpy(dbuf, sbuf, STRLCPY_BUF_SIZE); + EXPECT_EQ(internal_strncmp(dbuf, sbuf, STRLCPY_BUF_SIZE - 1), 0); + EXPECT_EQ(internal_strlen(dbuf), + std::min(internal_strlen(sbuf), (uptr)(STRLCPY_BUF_SIZE - 1))); + EXPECT_EQ(retval, internal_strlen(sbuf)); + + // Test with shorter maxlen. + uptr maxlen = 2; + if (internal_strlen(sbuf) > maxlen) { + retval = internal_strlcpy(dbuf, sbuf, maxlen); + EXPECT_EQ(internal_strncmp(dbuf, sbuf, maxlen - 1), 0); + EXPECT_EQ(internal_strlen(dbuf), maxlen - 1); + } +} + TEST(SanitizerCommon, InternalStrFunctions) { const char *haystack = "haystack"; EXPECT_EQ(haystack + 2, internal_strchr(haystack, 'y')); EXPECT_EQ(haystack + 2, internal_strchrnul(haystack, 'y')); EXPECT_EQ(0, internal_strchr(haystack, 'z')); EXPECT_EQ(haystack + 8, internal_strchrnul(haystack, 'z')); + + char dbuf[STRLCPY_BUF_SIZE] = {}; + const char *samesizestr = "1234567"; + const char *shortstr = "123"; + const char *longerstr = "123456789"; + + // Test internal_strlcpy. + internal_strlcpy(dbuf, shortstr, 0); + EXPECT_EQ(dbuf[0], 0); + EXPECT_EQ(dbuf[0], 0); + test_internal_strlcpy(dbuf, samesizestr); + test_internal_strlcpy(dbuf, shortstr); + test_internal_strlcpy(dbuf, longerstr); + + // Test internal_strlcat. + char dcatbuf[STRLCPY_BUF_SIZE] = {}; + uptr retval = 0; + retval = internal_strlcat(dcatbuf, "aaa", 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)0); + EXPECT_EQ(retval, (uptr)3); + + retval = internal_strlcat(dcatbuf, "123", STRLCPY_BUF_SIZE); + EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3); + EXPECT_EQ(retval, (uptr)3); + + retval = internal_strlcat(dcatbuf, "123", STRLCPY_BUF_SIZE); + EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6); + EXPECT_EQ(retval, (uptr)6); + + retval = internal_strlcat(dcatbuf, "123", STRLCPY_BUF_SIZE); + EXPECT_EQ(internal_strcmp(dcatbuf, "1231231"), 0); + EXPECT_EQ(internal_strlen(dcatbuf), (uptr)7); + EXPECT_EQ(retval, (uptr)9); } // FIXME: File manipulations are not yet supported on Windows