mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-29 08:42:28 +00:00
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:
parent
fdc3fa9148
commit
1ff9ab95ac
153 changed files with 2545 additions and 2077 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue