summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/sanitizer_common/sanitizer_libc.cc24
-rw-r--r--lib/sanitizer_common/sanitizer_libc.h2
-rw-r--r--lib/sanitizer_common/tests/sanitizer_libc_test.cc54
3 files changed, 80 insertions, 0 deletions
diff --git a/lib/sanitizer_common/sanitizer_libc.cc b/lib/sanitizer_common/sanitizer_libc.cc
index 43e454694..cf31e6896 100644
--- a/lib/sanitizer_common/sanitizer_libc.cc
+++ b/lib/sanitizer_common/sanitizer_libc.cc
@@ -175,6 +175,19 @@ uptr internal_strlen(const char *s) {
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_memmove(dst + dstlen, src, srclen + 1);
+ } else {
+ internal_memmove(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 @@ char *internal_strncat(char *dst, const char *src, uptr n) {
return dst;
}
+uptr internal_strlcpy(char *dst, const char *src, uptr maxlen) {
+ const uptr srclen = internal_strlen(src);
+ if (srclen < maxlen) {
+ internal_memmove(dst, src, srclen + 1);
+ } else if (maxlen != 0) {
+ internal_memmove(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++)
diff --git a/lib/sanitizer_common/sanitizer_libc.h b/lib/sanitizer_common/sanitizer_libc.h
index 99de140ec..df28677c6 100644
--- a/lib/sanitizer_common/sanitizer_libc.h
+++ b/lib/sanitizer_common/sanitizer_libc.h
@@ -43,8 +43,10 @@ uptr internal_strcspn(const char *s, const char *reject);
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);
diff --git a/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
index c0230ec6a..b09d37352 100644
--- a/lib/sanitizer_common/tests/sanitizer_libc_test.cc
+++ b/lib/sanitizer_common/tests/sanitizer_libc_test.cc
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
// Tests for sanitizer_libc.h.
//===----------------------------------------------------------------------===//
+#include <algorithm>
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
@@ -145,12 +146,65 @@ TEST(SanitizerCommon, FileOps) {
#endif
}
+static const size_t kStrlcpyBufSize = 8;
+void test_internal_strlcpy(char *dbuf, const char *sbuf) {
+ uptr retval = 0;
+ retval = internal_strlcpy(dbuf, sbuf, kStrlcpyBufSize);
+ EXPECT_EQ(internal_strncmp(dbuf, sbuf, kStrlcpyBufSize - 1), 0);
+ EXPECT_EQ(internal_strlen(dbuf),
+ std::min(internal_strlen(sbuf), (uptr)(kStrlcpyBufSize - 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[kStrlcpyBufSize] = {};
+ 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[kStrlcpyBufSize] = {};
+ 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", kStrlcpyBufSize);
+ EXPECT_EQ(internal_strcmp(dcatbuf, "123"), 0);
+ EXPECT_EQ(internal_strlen(dcatbuf), (uptr)3);
+ EXPECT_EQ(retval, (uptr)3);
+
+ retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
+ EXPECT_EQ(internal_strcmp(dcatbuf, "123123"), 0);
+ EXPECT_EQ(internal_strlen(dcatbuf), (uptr)6);
+ EXPECT_EQ(retval, (uptr)6);
+
+ retval = internal_strlcat(dcatbuf, "123", kStrlcpyBufSize);
+ 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