forked from OSchip/llvm-project
[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:
parent
8d225205e3
commit
c54cf07fd7
|
@ -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++)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue