Make C memory safe like Rust

This change enables Address Sanitizer systemically w/ `make MODE=dbg`.
Our version of Rust's `unsafe` keyword is named `noasan` which is used
for two functions that do aligned memory chunking, like `strcpy.c` and
we need to fix the tiny DEFLATE code, but that's it everything else is
fabulous you can have all the fischer price security blankets you need

Best of all is we're now able to use the ASAN data in Blinkenlights to
colorize the memory dumps. See the screenshot below of a test program:

  https://justine.lol/blinkenlights/asan.png

Which is operating on float arrays stored on the stack, with red areas
indicating poisoned memory, and the green areas indicate valid memory.
This commit is contained in:
Justine Tunney 2021-02-01 03:33:13 -08:00
parent fdc3fa9148
commit 1ff9ab95ac
153 changed files with 2545 additions and 2077 deletions

View file

@ -16,6 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/mem/mem.h"
#include "libc/rand/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
@ -40,19 +42,30 @@ TEST(memccpy, testZeroLength_doesNothing) {
}
TEST(memccpy, memcpy) {
unsigned n, n2;
unsigned n, n1, n2;
char *b1, *b2, *b3, *e1, *e2;
for (n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
b3 = tmalloc(n);
b1 = calloc(1, n);
b2 = calloc(1, n);
b3 = calloc(1, n);
rngset(b1, n, rand64, -1);
e1 = tinymemccpy(b2, b1, 31337, n);
e2 = memccpy(b3, b1, 31337, n);
n2 = e1 ? e1 - b1 : n;
ASSERT_EQ(e1, e2);
n1 = e1 ? e1 - b2 : n;
n2 = e2 ? e2 - b3 : n;
ASSERT_LE(n1, n);
ASSERT_LE(n2, n);
ASSERT_EQ(n1, n2,
"n=%ld\r\n\t"
"n1=%8ld e1=%p b2=%p %p\r\n\t"
"n2=%8ld e2=%p b3=%p %p\r\n\t"
"%#.*s\r\n\t"
"%#.*s\r\n\t"
"%#.*s",
n, n1, e1, b2, e1 - b2, n2, e2, b3, e2 - b3, n, b1, n, b2, n, b3);
ASSERT_EQ(0, memcmp(b2, b3, n2));
tfree(b3);
tfree(b2);
tfree(b1);
free(b3);
free(b2);
free(b1);
}
}

View file

@ -24,61 +24,61 @@
TEST(memcpy, memcpy) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
b1 = malloc(n);
b2 = malloc(n);
ASSERT_EQ(b1, memcpy(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
free(b2);
free(b1);
}
}
TEST(memcpy, memcpyDirect) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
b1 = malloc(n);
b2 = malloc(n);
ASSERT_EQ(b1, (memcpy)(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
free(b2);
free(b1);
}
}
TEST(memcpy, mempcpy) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
b1 = malloc(n);
b2 = malloc(n);
ASSERT_EQ(b1 + n, mempcpy(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
free(b2);
free(b1);
}
}
TEST(memcpy, mempcpyDirect) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = tmalloc(n);
b2 = tmalloc(n);
b1 = malloc(n);
b2 = malloc(n);
ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
tfree(b2);
tfree(b1);
free(b2);
free(b1);
}
}
TEST(memcpy, overlapping_isFineIfCopyingBackwards) {
for (size_t i = 0; i < 32; ++i) {
char *b1 = tmalloc(64 + i);
char *b2 = tmalloc(64 + i);
char *b1 = malloc(64 + i);
char *b2 = malloc(64 + i);
memcpy(b1, b2, 64);
memcpy(b1, b1 + i, 64 - i);
memmove(b2, b2 + i, 64 - i);
ASSERT_EQ(0, memcmp(b1, b2, 64));
tfree(b2);
tfree(b1);
free(b2);
free(b1);
}
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/alg/alg.h"
#include "libc/bits/bits.h"
#include "libc/mem/mem.h"
#include "libc/str/internal.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
@ -27,7 +28,7 @@ FIXTURE(memmem, tiny) {
memmemi = tinymemmem;
}
#define MakeMemory(SL) memcpy(tmalloc(sizeof(SL) - 1), SL, sizeof(SL) - 1)
#define MakeMemory(SL) memcpy(malloc(sizeof(SL) - 1), SL, sizeof(SL) - 1)
TEST(memmem, test) {
char *needle = MakeMemory("abcdefgh");
@ -36,40 +37,40 @@ TEST(memmem, test) {
memcpy(needle, "aaaaaaaa", 8);
memcpy(haystk, "acccccccbbbbbbbbaaaaaaaadddddddd", 32);
EXPECT_BINEQ(u"aaaaaaaadddddddd", memmemi(haystk, 32, needle, 8));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testNoMatch) {
char *needle = MakeMemory("abcdefzh");
char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd");
EXPECT_EQ(NULL, memmemi(haystk, 32, needle, 8));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testStartOfMemory) {
char *needle = MakeMemory("acccc");
char *haystk = MakeMemory("acccccccbbbbbbbbabcdefghdddddddd");
EXPECT_EQ(&haystk[0], memmemi(haystk, 32, needle, 5));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testEndOfMemory) {
char *needle = MakeMemory("123");
char *haystk = MakeMemory("abc123");
EXPECT_EQ(&haystk[3], memmemi(haystk, 6, needle, 3));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testCrossesSseRegister) {
char *needle = MakeMemory("eeeeeeeeeeeeefffffffffffff");
char *haystk = MakeMemory("eeeeeeeeeeeeeeeeffffffffffffffffrrrrrrrrrrrrrrrr");
EXPECT_EQ(&haystk[3], memmemi(haystk, 16 * 3, needle, 26));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testHasNulCharacters) {
@ -77,39 +78,39 @@ TEST(memmem, testHasNulCharacters) {
char *haystk =
MakeMemory("eeeeeeeeeeeeeeee\0fffffffffffffffrrrrrrrrrrrrrrrr");
EXPECT_EQ(&haystk[3], memmemi(haystk, 16 * 3, needle, 26));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testWeird) {
char *needle = MakeMemory("-*-+-+-+-+-+-+-+");
char *haystk = MakeMemory("-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-+");
EXPECT_EQ(14, (intptr_t)memmemi(haystk, 32, needle, 16) - (intptr_t)haystk);
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testEmptyNeedle_matchesStartOfHaystack) {
char *needle = tmalloc(0);
char *needle = malloc(0);
char *haystk = MakeMemory("-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-+");
EXPECT_EQ(0, (intptr_t)memmemi(haystk, 32, needle, 0) - (intptr_t)haystk);
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testEmptyHaystack_alwaysReturnsNull) {
char *needle = MakeMemory("-*-+-+-+-+-+-+-+");
char *haystk = tmalloc(0);
char *haystk = malloc(0);
EXPECT_EQ(NULL, memmemi(haystk, 0, needle, 16));
EXPECT_EQ(NULL, memmemi(haystk, 0, needle, 1));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}
TEST(memmem, testEmptyHaystackAndNeedle_returnsHaystack) {
char *needle = tmalloc(0);
char *haystk = tmalloc(0);
char *needle = malloc(0);
char *haystk = malloc(0);
EXPECT_EQ(haystk, memmemi(haystk, 0, needle, 0));
tfree(haystk);
tfree(needle);
free(haystk);
free(needle);
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/mem/mem.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
@ -34,38 +35,38 @@ TEST(pututf16, testEmpty) {
TEST(pututf16, testNul) {
size = 1;
buf = tmalloc(size * sizeof(char16_t));
buf = malloc(size * sizeof(char16_t));
EXPECT_EQ(1, pututf16(buf, size, u'\0', false));
EXPECT_EQ(u'\0', buf[0]);
buf[0] = '\7';
EXPECT_EQ(1, (pututf16)(buf, size, u'\0', false));
EXPECT_EQ(u'\0', buf[0]);
tfree(buf);
free(buf);
}
TEST(pututf16, testAscii) {
size = 1;
buf = tmalloc(size * sizeof(char16_t));
buf = malloc(size * sizeof(char16_t));
EXPECT_EQ(1, pututf16(buf, size, u'j', false));
EXPECT_EQ(u'j', buf[0]);
EXPECT_EQ(1, (pututf16)(buf, size, u't', false));
EXPECT_EQ(u't', buf[0]);
tfree(buf);
free(buf);
}
TEST(pututf16, testGothicSupplementaryPlane) {
size = 2;
buf = tmalloc(size * sizeof(char16_t));
buf = malloc(size * sizeof(char16_t));
EXPECT_EQ(2, pututf16(buf, size, L'𐌰', false));
EXPECT_STREQN(u"𐌰", buf, 1);
EXPECT_EQ(2, (pututf16)(buf, size, L'𐌱', false));
EXPECT_STREQN(u"𐌱", buf, 1);
tfree(buf);
free(buf);
}
TEST(pututf16, testEmojiAndEmojiPresentationModifier_areBothInAstralPlanes) {
n = 8;
b = tgc(tmalloc(sizeof(char16_t) * n));
b = gc(malloc(sizeof(char16_t) * n));
str = L"\U0001F466\U0001F3FF";
memset(b, 0, n * sizeof(char16_t));
EXPECT_EQ(2, pututf16(b, n, str[0], false));

View file

@ -19,9 +19,11 @@
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/cachesize.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
@ -64,27 +66,27 @@ TEST(wcscasecmp, emptyString) {
}
TEST(strncmp, emptyString) {
char *s1 = strcpy(tmalloc(1), "");
char *s2 = strcpy(tmalloc(1), "");
char *s1 = strcpy(malloc(1), "");
char *s2 = strcpy(malloc(1), "");
ASSERT_EQ(0, strncmp(s1, s2, 0));
ASSERT_EQ(0, strncmp(s1, s2, 1));
ASSERT_EQ(0, strncmp(s1, s2, -1));
ASSERT_EQ(0, strncmp(s1, s1, -1));
ASSERT_EQ(0, strncmp(s2, s2, -1));
tfree(s2);
tfree(s1);
free(s2);
free(s1);
}
TEST(strncasecmp, emptyString) {
char *s1 = strcpy(tmalloc(1), "");
char *s2 = strcpy(tmalloc(1), "");
char *s1 = strcpy(malloc(1), "");
char *s2 = strcpy(malloc(1), "");
ASSERT_EQ(0, strncasecmp(s1, s2, 0));
ASSERT_EQ(0, strncasecmp(s1, s2, 1));
ASSERT_EQ(0, strncasecmp(s1, s2, -1));
ASSERT_EQ(0, strncasecmp(s1, s1, -1));
ASSERT_EQ(0, strncasecmp(s2, s2, -1));
tfree(s2);
tfree(s1);
free(s2);
free(s1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -92,13 +94,13 @@ TEST(strncasecmp, emptyString) {
*/
TEST(strncmp, testInequality) {
char *s1 = strcpy(tmalloc(2), "1");
char *s2 = strcpy(tmalloc(1), "");
char *s1 = strcpy(malloc(2), "1");
char *s2 = strcpy(malloc(1), "");
ASSERT_EQ(0, strncmp(s1, s2, 0));
ASSERT_EQ('1', strncmp(s1, s2, 1));
ASSERT_EQ(-'1', strncmp(s2, s1, 1));
tfree(s2);
tfree(s1);
free(s2);
free(s1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -318,8 +320,8 @@ TEST(strcasecmp8to16, testItWorksCase) {
*/
TEST(strncmp, testEqualManyNs) {
char *s1 = tmalloc(PAGESIZE);
char *s2 = tmalloc(PAGESIZE);
char *s1 = malloc(PAGESIZE);
char *s2 = malloc(PAGESIZE);
memset(s1, 7, PAGESIZE);
memset(s2, 7, PAGESIZE);
s1[PAGESIZE - 1] = '\0';
@ -328,13 +330,13 @@ TEST(strncmp, testEqualManyNs) {
ASSERT_EQ(0, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 0));
ASSERT_EQ(0, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 1));
}
tfree(s2);
tfree(s1);
free(s2);
free(s1);
}
TEST(strncmp, testNotEqualManyNs) {
char *s1 = tmalloc(PAGESIZE);
char *s2 = tmalloc(PAGESIZE);
char *s1 = malloc(PAGESIZE);
char *s2 = malloc(PAGESIZE);
for (unsigned i = 1; i <= 128; ++i) {
memset(s1, 7, PAGESIZE);
memset(s2, 7, PAGESIZE);
@ -343,8 +345,8 @@ TEST(strncmp, testNotEqualManyNs) {
ASSERT_EQ(-255, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 0));
ASSERT_EQ(-255, strncmp(s1 + PAGESIZE - i, s2 + PAGESIZE - i, i + 1));
}
tfree(s2);
tfree(s1);
free(s2);
free(s1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -354,40 +356,40 @@ TEST(strncmp, testNotEqualManyNs) {
TEST(strncmp, testStringNulTerminatesBeforeExplicitLength) {
const char kRdi[] = "";
const char kRsi[] = "TZ=America/Los_Angeles";
char *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
char *rdi = memcpy(malloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char *rsi = memcpy(malloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
size_t rdx = 3;
EXPECT_EQ(strncmp(rdi, rdi, rdx), 0);
EXPECT_LT(strncmp(rdi, rsi, rdx), 0);
EXPECT_GT(strncmp(rsi, rdi, rdx), 0);
tfree(rsi);
tfree(rdi);
free(rsi);
free(rdi);
}
TEST(strncasecmp, testStringNulTerminatesBeforeExplicitLength) {
const char kRdi[] = "";
const char kRsi[] = "TZ=America/Los_Angeles";
char *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
char *rdi = memcpy(malloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char *rsi = memcpy(malloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
size_t rdx = 3;
EXPECT_EQ(strncasecmp(rdi, rdi, rdx), 0);
EXPECT_LT(strncasecmp(rdi, rsi, rdx), 0);
EXPECT_GT(strncasecmp(rsi, rdi, rdx), 0);
tfree(rsi);
tfree(rdi);
free(rsi);
free(rdi);
}
TEST(strncmp16, testStringNulTerminatesBeforeExplicitLength) {
const char16_t kRdi[] = u"";
const char16_t kRsi[] = u"TZ=America/Los_Angeles";
char16_t *rdi = memcpy(tmalloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char16_t *rsi = memcpy(tmalloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
char16_t *rdi = memcpy(malloc(sizeof(kRdi)), kRdi, sizeof(kRdi));
char16_t *rsi = memcpy(malloc(sizeof(kRsi)), kRsi, sizeof(kRsi));
size_t rdx = 3;
EXPECT_EQ(strncmp16(rdi, rdi, rdx), 0);
EXPECT_LT(strncmp16(rdi, rsi, rdx), 0);
EXPECT_GT(strncmp16(rsi, rdi, rdx), 0);
tfree(rsi);
tfree(rdi);
free(rsi);
free(rdi);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -422,33 +424,33 @@ TEST(memcmp, testTwosComplementBane_unsignedBehavior) {
}
TEST(strcmp16, testTwosComplementBane_hasUnsignedBehavior) {
char16_t *B1 = tmalloc(8);
char16_t *B2 = tmalloc(8);
char16_t *B1 = malloc(8);
char16_t *B2 = malloc(8);
B1[1] = L'\0';
B2[1] = L'\0';
EXPECT_EQ(strcmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\x00\x80", 2)), 0);
EXPECT_LT(strcmp16(memcpy(B1, "\xff\x7f", 2), memcpy(B2, "\x00\x80", 2)), 0);
EXPECT_GT(strcmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\xff\x7f", 2)), 0);
tfree(B2);
tfree(B1);
free(B2);
free(B1);
}
TEST(strncmp16, testTwosComplementBane_hasUnsignedBehavior) {
char16_t *B1 = tmalloc(4);
char16_t *B2 = tmalloc(4);
char16_t *B1 = malloc(4);
char16_t *B2 = malloc(4);
EXPECT_EQ(strncmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\x00\x80", 2), 1),
0);
EXPECT_LT(strncmp16(memcpy(B1, "\xff\x7f", 2), memcpy(B2, "\x00\x80", 2), 1),
0);
EXPECT_GT(strncmp16(memcpy(B1, "\x00\x80", 2), memcpy(B2, "\xff\x7f", 2), 1),
0);
tfree(B2);
tfree(B1);
free(B2);
free(B1);
}
TEST(wcscmp, testTwosComplementBane) {
wchar_t *B1 = tmalloc(8);
wchar_t *B2 = tmalloc(8);
wchar_t *B1 = malloc(8);
wchar_t *B2 = malloc(8);
B1[1] = L'\0';
B2[1] = L'\0';
EXPECT_EQ(wcscmp(memcpy(B1, "\x00\x00\x00\x80", 4),
@ -459,13 +461,13 @@ TEST(wcscmp, testTwosComplementBane) {
EXPECT_EQ(wcscmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\xff\xff\xff\x7f", 4)),
1);
tfree(B2);
tfree(B1);
free(B2);
free(B1);
}
TEST(wcsncmp, testTwosComplementBane) {
wchar_t *B1 = tmalloc(4);
wchar_t *B2 = tmalloc(4);
wchar_t *B1 = malloc(4);
wchar_t *B2 = malloc(4);
EXPECT_EQ(wcsncmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\x00\x00\x00\x80", 4), 1),
0);
@ -475,8 +477,8 @@ TEST(wcsncmp, testTwosComplementBane) {
EXPECT_EQ(wcsncmp(memcpy(B1, "\x00\x00\x00\x80", 4),
memcpy(B2, "\xff\xff\xff\x7f", 4), 1),
1);
tfree(B2);
tfree(B1);
free(B2);
free(B1);
}
/*───────────────────────────────────────────────────────────────────────────│─╗
@ -530,8 +532,8 @@ BENCH(bench_00_strcmp, bench) {
char *dupe, *data;
size = ROUNDDOWN(MAX(FRAMESIZE, getcachesize(kCpuCacheTypeData, 1)) / 2,
PAGESIZE);
data = tgc(tmalloc(size));
dupe = tgc(tmalloc(size));
data = gc(malloc(size));
dupe = gc(malloc(size));
fprintf(stderr, "\n");
EZBENCH2("strcmp [identity]", longstringislong(size, data),
@ -579,8 +581,8 @@ BENCH(bench_01_strcasecmp, bench) {
char *dupe, *data;
size = ROUNDDOWN(MAX(FRAMESIZE, getcachesize(kCpuCacheTypeData, 1)) / 2,
PAGESIZE);
data = tgc(tmalloc(size));
dupe = tgc(tmalloc(size));
data = gc(malloc(size));
dupe = gc(malloc(size));
fprintf(stderr, "\n");
EZBENCH2("strcasecmp [identity]", longstringislong(size, data),

View file

@ -18,7 +18,9 @@
*/
#include "libc/bits/bits.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/tinystrlen.internal.h"
#include "libc/rand/rand.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
@ -88,10 +90,10 @@ TEST(strnlen_s, null_ReturnsZero) {
TEST(strnlen, nulNotFound_ReturnsSize) {
int sizes[] = {1, 2, 7, 8, 15, 16, 31, 32, 33};
for (unsigned i = 0; i < ARRAYLEN(sizes); ++i) {
char *buf = tmalloc(sizes[i]);
char *buf = malloc(sizes[i]);
memset(buf, ' ', sizes[i]);
ASSERT_EQ(sizes[i], strnlen(buf, sizes[i]), "%d", sizes[i]);
tfree(buf);
free(buf);
}
}
@ -134,15 +136,38 @@ TEST(tinystrnlen16, test) {
EXPECT_EQ(3, tinystrnlen16(u"123", 4));
}
TEST(strlen, fuzz) {
char *b;
size_t n, n1, n2;
for (n = 2; n < 1026; ++n) {
b = rngset(calloc(1, n), n - 1, rand64, -1);
n1 = strlen(b);
n2 = strlen$pure(b);
ASSERT_EQ(n1, n2);
n1 = strlen(b + 1);
n2 = strlen$pure(b + 1);
ASSERT_EQ(n1, n2);
free(b);
}
}
BENCH(strlen, bench) {
extern size_t strlen_(const char *) asm("strlen");
extern size_t strlen$pure_(const char *) asm("strlen$pure");
static char b[2048];
memset(b, -1, sizeof(b) - 1);
EZBENCH2("strlen 1", donothing, strlen_(""));
EZBENCH2("strlen$pure 1", donothing, strlen$pure_(""));
EZBENCH2("strlen 2", donothing, strlen_("1"));
EZBENCH2("strlen$pure 2", donothing, strlen$pure_("1"));
EZBENCH2("strlen 7", donothing, strlen_("123456"));
EZBENCH2("strlen$pure 7", donothing, strlen$pure_("123456"));
EZBENCH2("strlen 8", donothing, strlen_("1234567"));
EZBENCH2("strlen$pure 8", donothing, strlen$pure_("1234567"));
EZBENCH2("strlen 9", donothing, strlen_("12345678"));
EZBENCH2("strlen$pure 9", donothing, strlen$pure_("12345678"));
EZBENCH2("strlen 16", donothing, strlen_("123456781234567"));
EZBENCH2("strlen$pure 16", donothing, strlen$pure_("123456781234567"));
EZBENCH2("strlen 1023", donothing, strlen_(b));
EZBENCH2("strlen$pure 1023", donothing, strlen$pure_(b));
}

View file

@ -26,7 +26,7 @@
#include "libc/testlib/testlib.h"
#define MAKESTRING(NAME, VALUE) \
char *NAME = strcpy(tmalloc(sizeof(VALUE) + 16), VALUE)
char *NAME = strcpy(malloc(sizeof(VALUE) + 16), VALUE)
char *strstr$kmp(const char *haystak, const char *needle) {
return memmem(haystak, strlen(haystak), needle, strlen(needle));
@ -44,40 +44,40 @@ TEST(strstr, test_emptyString_isFoundAtBeginning) {
MAKESTRING(haystack, "abc123def");
ASSERT_STREQ(&haystack[0], strstri(haystack, gc(strdup(""))));
ASSERT_STREQ(&haystack[0], strstr(haystack, gc(strdup(""))));
tfree(haystack);
free(haystack);
}
TEST(strstr, test_notFound) {
MAKESTRING(haystack, "abc123def");
ASSERT_EQ(NULL, strstri(haystack, gc(strdup("xyz"))));
ASSERT_EQ(NULL, strstr(haystack, gc(strdup("xyz"))));
tfree(haystack);
free(haystack);
}
TEST(strstr, test_middleOfString) {
MAKESTRING(haystack, "abc123def");
ASSERT_STREQ(&haystack[3], strstri(haystack, gc(strdup("123"))));
ASSERT_STREQ(&haystack[3], strstr(haystack, gc(strdup("123"))));
tfree(haystack);
free(haystack);
}
TEST(strstr, test_endOfString) {
MAKESTRING(haystack, "abc123def");
ASSERT_STREQ(&haystack[8], strstri(haystack, gc(strdup("f"))));
ASSERT_STREQ(&haystack[8], strstr(haystack, gc(strdup("f"))));
tfree(haystack);
free(haystack);
}
TEST(strstr, test_secondXmmWord) {
MAKESTRING(haystack, "eeeeeeeeeeeeeeeebbbbbbbbbbb123");
ASSERT_STREQ(&haystack[27], strstri(haystack, gc(strdup("123"))));
ASSERT_STREQ(&haystack[27], strstr(haystack, gc(strdup("123"))));
tfree(haystack);
free(haystack);
}
TEST(strstr, test_overlapsXmmWords) {
MAKESTRING(haystack, "eeeeeeeeeeeeeeeebbbbbbbbbbbbbbb");
ASSERT_STREQ(&haystack[15], strstri(haystack, gc(strdup("eb"))));
ASSERT_STREQ(&haystack[15], strstr(haystack, gc(strdup("eb"))));
tfree(haystack);
free(haystack);
}

View file

@ -16,49 +16,50 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
TEST(strtok_r, testEmpty) {
static const char *const kInput = "";
static const char *const kSeparators = "/";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *s = strcpy(malloc(strlen(kInput) + 1), kInput);
char *state;
EXPECT_EQ(NULL, strtok_r(s, kSeparators, &state));
tfree(s);
free(s);
}
TEST(strtok_r, test) {
static const char *const kInput = ".,lol..cat..";
static const char *const kSeparators = ".,";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *s = strcpy(malloc(strlen(kInput) + 1), kInput);
char *state;
EXPECT_STREQ("lol", strtok_r(s, kSeparators, &state));
EXPECT_STREQ("cat", strtok_r(NULL, kSeparators, &state));
EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state));
EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state));
tfree(s);
free(s);
}
TEST(strtok, test) {
static const char *const kInput = ".,lol..cat..";
static const char *const kSeparators = ".,";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *s = strcpy(malloc(strlen(kInput) + 1), kInput);
EXPECT_STREQ("lol", strtok(s, kSeparators));
EXPECT_STREQ("cat", strtok(NULL, kSeparators));
EXPECT_EQ(NULL, strtok(NULL, kSeparators));
EXPECT_EQ(NULL, strtok(NULL, kSeparators));
tfree(s);
free(s);
}
TEST(strtok_r, testHostsTxtLine) {
static const char *const kInput = "203.0.113.1 lol.example. lol";
static const char *const kSeparators = " \t";
char *s = strcpy(tmalloc(strlen(kInput) + 1), kInput);
char *s = strcpy(malloc(strlen(kInput) + 1), kInput);
char *state;
EXPECT_STREQ("203.0.113.1", strtok_r(s, kSeparators, &state));
EXPECT_STREQ("lol.example.", strtok_r(NULL, kSeparators, &state));
EXPECT_STREQ("lol", strtok_r(NULL, kSeparators, &state));
EXPECT_EQ(NULL, strtok_r(NULL, kSeparators, &state));
tfree(s);
free(s);
}

View file

@ -47,11 +47,11 @@ TEST(tprecode16to8, testTooLittle_stillNulTerminates) {
TEST(tprecode16to8, testAscii_vectorSpeedupWorks) {
size_t size = 32;
char *buf = tmalloc(size);
char *buf = malloc(size);
EXPECT_EQ(31,
tprecode16to8(buf, size, u"babaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").ax);
EXPECT_STREQ("babaaaaaaaaaaaaaaaaaaaaaaaaaaaa", buf);
tfree(buf);
free(buf);
}
BENCH(tprecode16to8, bench) {

View file

@ -25,10 +25,10 @@
TEST(tprecode8to16, test) {
size_t size = 8;
char16_t *buf = tmalloc(size * sizeof(char16_t));
char16_t *buf = malloc(size * sizeof(char16_t));
EXPECT_EQ(7, tprecode8to16(buf, size, "hello☻♥").ax);
EXPECT_STREQ(u"hello☻♥", buf);
tfree(buf);
free(buf);
}
TEST(tprecode8to16, testEmptyOut_doesNothingButStillCountsSrcLength) {
@ -65,11 +65,11 @@ TEST(tprecode8to16, test2) {
TEST(tprecode8to16, testAscii_vectorSpeedupWorks) {
size_t size = 32;
char16_t *buf = tmalloc(size * sizeof(char16_t));
char16_t *buf = malloc(size * sizeof(char16_t));
EXPECT_EQ(31,
tprecode8to16(buf, size, "babaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").ax);
EXPECT_STREQ(u"babaaaaaaaaaaaaaaaaaaaaaaaaaaaa", buf);
tfree(buf);
free(buf);
}
BENCH(tprecode8to16, bench) {