From 00dbefdb3a2e7a89931f1ff480a995dd787217e6 Mon Sep 17 00:00:00 2001 From: Chuck Coffing Date: Thu, 7 Dec 2023 19:22:59 -0800 Subject: [PATCH 1/3] ELKS formatting; no code changes --- elkscmd/test/libc/malloc.c | 124 ++++++++++++++++++------------------- libc/malloc/calloc.c | 12 ++-- libc/malloc/noise.c | 46 +++++++------- 3 files changed, 89 insertions(+), 93 deletions(-) diff --git a/elkscmd/test/libc/malloc.c b/elkscmd/test/libc/malloc.c index fb40c772e..0baf4e873 100644 --- a/elkscmd/test/libc/malloc.c +++ b/elkscmd/test/libc/malloc.c @@ -4,85 +4,81 @@ #include #include -TEST_CASE(malloc_malloc_free) -{ - void *p; - - /* malloc(0) may return NULL or a pointer which can be passed to free */ - errno = 0; - p = malloc(0); - EXPECT_EQ(errno, 0); - if (p != NULL) { - free(p); - } - - /* TODO:BUG: causes hang at 100% CPU */ +TEST_CASE(malloc_malloc_free) { + void *p; + + /* malloc(0) may return NULL or a pointer which can be passed to free */ + errno = 0; + p = malloc(0); + EXPECT_EQ(errno, 0); + if (p != NULL) { + free(p); + } + + /* TODO:BUG: causes hang at 100% CPU */ #if 0 - errno = 0; - p = malloc((size_t)-1); - if (p == NULL) { - EXPECT_EQ(errno, ENOMEM); - } else { - EXPECT_EQ(errno, 0); - memset(p, 0xff, (size_t)-1); - free(p); - } + errno = 0; + p = malloc((size_t) - 1); + if (p == NULL) { + EXPECT_EQ(errno, ENOMEM); + } else { + EXPECT_EQ(errno, 0); + memset(p, 0xff, (size_t) - 1); + free(p); + } #endif - /* strange sizes are fine; memory is writable and free-able */ - for (int i = 1; i < 1024; i += 123) { - errno = 0; - p = malloc(i); - EXPECT_EQ(errno, 0); - ASSERT_NE_P(p, NULL); - memset(p, 0xff, i); - free(p); - } + /* strange sizes are fine; memory is writable and free-able */ + for (int i = 1; i < 1024; i += 123) { + errno = 0; + p = malloc(i); + EXPECT_EQ(errno, 0); + ASSERT_NE_P(p, NULL); + memset(p, 0xff, i); + free(p); + } } -TEST_CASE(malloc_calloc) -{ - void *p; +TEST_CASE(malloc_calloc) { + void *p; - errno = 0; - p = calloc(0, 1); - EXPECT_EQ(errno, 0); - if (p != NULL) { - free(p); - } + errno = 0; + p = calloc(0, 1); + EXPECT_EQ(errno, 0); + if (p != NULL) { + free(p); + } - /* TODO check for mult overflow */ + /* TODO check for mult overflow */ } -TEST_CASE(malloc_realloc) -{ - char *p; +TEST_CASE(malloc_realloc) { + char *p; - p = realloc(NULL, 32); - ASSERT_NE_P(p, NULL); - memset(p, 'A', 32); + p = realloc(NULL, 32); + ASSERT_NE_P(p, NULL); + memset(p, 'A', 32); - /* shrink */ - p = realloc(p, 1); - ASSERT_NE_P(p, NULL); - memset(p, 'B', 1); + /* shrink */ + p = realloc(p, 1); + ASSERT_NE_P(p, NULL); + memset(p, 'B', 1); - /* grow */ - p = realloc(p, 64); - ASSERT_NE_P(p, NULL); - EXPECT_EQ(p[0], 'B'); - memset(p, 'C', 64); + /* grow */ + p = realloc(p, 64); + ASSERT_NE_P(p, NULL); + EXPECT_EQ(p[0], 'B'); + memset(p, 'C', 64); - free(p); + free(p); } -TEST_CASE(malloc_alloca) -{ - void *p; +TEST_CASE(malloc_alloca) { + void *p; - p = alloca(1); - EXPECT_NE_P(p, NULL); + p = alloca(1); + EXPECT_NE_P(p, NULL); - /* TODO nested function calls */ - /* TODO vs setjmp / longjmp */ + /* TODO nested function calls */ + /* TODO vs setjmp / longjmp */ } diff --git a/libc/malloc/calloc.c b/libc/malloc/calloc.c index 8db8ac581..e4b612017 100644 --- a/libc/malloc/calloc.c +++ b/libc/malloc/calloc.c @@ -4,12 +4,12 @@ void * calloc(unsigned int elm, unsigned int sz) { - register unsigned int v; - register void *ptr; + register unsigned int v; + register void *ptr; - ptr = malloc(v = elm * sz); - if(ptr) - memset(ptr, 0, v); + ptr = malloc(v = elm * sz); + if (ptr) + memset(ptr, 0, v); - return ptr; + return ptr; } diff --git a/libc/malloc/noise.c b/libc/malloc/noise.c index 573166921..135562e60 100644 --- a/libc/malloc/noise.c +++ b/libc/malloc/noise.c @@ -1,37 +1,37 @@ #if defined(VERBOSE) -# include -# include +#include +#include -# include "_malloc.h" +#include "_malloc.h" /* NB: Careful here, stdio may use malloc - so we can't */ static void phex(int val) { - static char hex[] = "0123456789ABCDEF"; - int i; + static char hex[] = "0123456789ABCDEF"; + int i; - for (i = sizeof(int) * 8 - 4; i >= 0; i -= 4) - write(2, hex + ((val >> i) & 0xF), 1); + for (i = sizeof(int) * 8 - 4; i >= 0; i -= 4) + write(2, hex + ((val >> i) & 0xF), 1); } void -__noise(char *y, mem *x) +__noise(char *y, mem * x) { - write(2, "Malloc ", 7); - phex((int)x); - write(2, " sz ", 4); - if(x) - phex(m_size(x)); - else - phex(0); - write(2, " nxt ", 5); - if (x) - phex((int)m_next(x)); - else - phex(0); - write(2, " is ", 4); - write(2, y, strlen(y)); - write(2, "\n", 1); + write(2, "Malloc ", 7); + phex((int)x); + write(2, " sz ", 4); + if (x) + phex(m_size(x)); + else + phex(0); + write(2, " nxt ", 5); + if (x) + phex((int)m_next(x)); + else + phex(0); + write(2, " is ", 4); + write(2, y, strlen(y)); + write(2, "\n", 1); } #endif From d3b43f95210c6dbd6f7868021eef4ef2c60bdb13 Mon Sep 17 00:00:00 2001 From: Chuck Coffing Date: Thu, 7 Dec 2023 19:23:06 -0800 Subject: [PATCH 2/3] [libc] free must not change errno (SUSv2) --- elkscmd/test/libc/malloc.c | 4 ++++ libc/malloc/noise.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/elkscmd/test/libc/malloc.c b/elkscmd/test/libc/malloc.c index 0baf4e873..180084cc3 100644 --- a/elkscmd/test/libc/malloc.c +++ b/elkscmd/test/libc/malloc.c @@ -35,7 +35,11 @@ TEST_CASE(malloc_malloc_free) { EXPECT_EQ(errno, 0); ASSERT_NE_P(p, NULL); memset(p, 0xff, i); + + /* free must not change errno */ + errno = 123; free(p); + EXPECT_EQ(errno, 123); } } diff --git a/libc/malloc/noise.c b/libc/malloc/noise.c index 135562e60..feb5603a8 100644 --- a/libc/malloc/noise.c +++ b/libc/malloc/noise.c @@ -1,4 +1,5 @@ #if defined(VERBOSE) +#include #include #include @@ -18,6 +19,7 @@ phex(int val) void __noise(char *y, mem * x) { + int saved_errno = errno; write(2, "Malloc ", 7); phex((int)x); write(2, " sz ", 4); @@ -33,5 +35,6 @@ __noise(char *y, mem * x) write(2, " is ", 4); write(2, y, strlen(y)); write(2, "\n", 1); + errno = saved_errno; } #endif From 58fa2b7f798d044d819eaf4650a4306e2c1e77bb Mon Sep 17 00:00:00 2001 From: Chuck Coffing Date: Thu, 7 Dec 2023 19:23:11 -0800 Subject: [PATCH 3/3] [libc] calloc must check for overflow (C99) I think this was first standardized in C99, but was commonly checked for earlier than that. --- elkscmd/test/libc/malloc.c | 4 +++- libc/malloc/calloc.c | 20 +++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/elkscmd/test/libc/malloc.c b/elkscmd/test/libc/malloc.c index 180084cc3..5375da4cf 100644 --- a/elkscmd/test/libc/malloc.c +++ b/elkscmd/test/libc/malloc.c @@ -53,7 +53,9 @@ TEST_CASE(malloc_calloc) { free(p); } - /* TODO check for mult overflow */ + p = calloc(((unsigned)-1)>>2, 5); + EXPECT_EQ(errno, ENOMEM); + EXPECT_EQ_P(p, NULL); } TEST_CASE(malloc_realloc) { diff --git a/libc/malloc/calloc.c b/libc/malloc/calloc.c index e4b612017..539c9ec7d 100644 --- a/libc/malloc/calloc.c +++ b/libc/malloc/calloc.c @@ -1,13 +1,27 @@ +#include #include #include void * calloc(unsigned int elm, unsigned int sz) { - register unsigned int v; - register void *ptr; + unsigned int v; + void *ptr; - ptr = malloc(v = elm * sz); +#ifdef __GNUC__ + if (__builtin_umul_overflow(elm, sz, &v)) { + errno = ENOMEM; + return 0; + } +#else + v = elm * sz; + if (sz != 0 && v / sz != elm) { + errno = ENOMEM; + return 0; + } +#endif + + ptr = malloc(v); if (ptr) memset(ptr, 0, v);