[compiler-rt] Add internal implementations for strlcat and strlcpy

The compiler-rt should make use of strlcpy() rather than strncpy(). Using internal_strncpy() may be fine with appropriate bounds checking or enforcement of nul-termination elsewhere, but it's just good practice these days to avoid using strncpy() in new code.

A patch by Jeremy Sequoia!

Differential Revision: http://reviews.llvm.org/D14714

llvm-svn: 253690
This commit is contained in:
Anna Zaks 2015-11-20 18:42:05 +00:00
parent 8d225205e3
commit c54cf07fd7
3 changed files with 80 additions and 0 deletions

View File

@ -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++)

View File

@ -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);

View File

@ -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