From 6f96368d8620345a98e148436b96f4262ca73972 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Thu, 7 Jul 2022 11:37:52 +0200 Subject: Use malloc by default but allow bounded alloca MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- common.h | 6 ++++++ config.mk | 6 ++++++ sum_fd.c | 32 ++++++++++++++++++++++++++++++++ update.c | 2 +- 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/common.h b/common.h index ad3be05..864082c 100644 --- a/common.h +++ b/common.h @@ -4,11 +4,17 @@ #include #include #include +#include #include #include #include +#ifndef ALLOCA_LIMIT +# define ALLOCA_LIMIT 0 +#endif + + /** * Process a chunk using SHA-1 or SHA-0 * diff --git a/config.mk b/config.mk index 2062ea6..66efe55 100644 --- a/config.mk +++ b/config.mk @@ -6,3 +6,9 @@ CC = c99 CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 CFLAGS = -Wall -O3 LDFLAGS = -s + +# You can add -DALLOCA_LIMIT=# to CPPFLAGS, where # is a size_t +# value, to put a limit on how large allocation the library is +# allowed to make with alloca(3). For buffers that can have any +# size this limit will be used if it wants to allocate a larger +# buffer. Choose 0 to use malloc(3) instead of alloca(3). diff --git a/sum_fd.c b/sum_fd.c index bc2761d..a61bf71 100644 --- a/sum_fd.c +++ b/sum_fd.c @@ -16,17 +16,42 @@ libsha1_sum_fd(int fd, enum libsha1_algorithm algorithm, void *restrict hashsum) { struct libsha1_state state; ssize_t r; +#ifndef _WIN32 struct stat attr; +#endif size_t blksize = 4096; char *restrict chunk; if (libsha1_init(&state, algorithm) < 0) return -1; +#ifndef _WIN32 if (fstat(fd, &attr) == 0 && attr.st_blksize > 0) blksize = (size_t)(attr.st_blksize); +#endif +#if ALLOCA_LIMIT > 0 + if (blksize > (size_t)ALLOCA_LIMIT) { + blksize = (size_t)ALLOCA_LIMIT; + blksize -= blksize % sizeof(((struct libsha1_state)NULL)->chunk); + if (!blksize) + blksize = sizeof(((struct libsha1_state)NULL)->chunk); + } +# if defined(__clang__) + /* We are using a limit so it's just like declaring an array + * in a function, except we might use less of the stack. */ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Walloca" +# endif chunk = alloca(blksize); +# if defined(__clang__) +# pragma clang diagnostic pop +# endif +#else + chunk = malloc(blksize); + if (!chunk) + return -1; +#endif for (;;) { r = read(fd, chunk, blksize); @@ -35,11 +60,18 @@ libsha1_sum_fd(int fd, enum libsha1_algorithm algorithm, void *restrict hashsum) break; if (errno == EINTR) continue; +#if ALLOCA_LIMIT <= 0 + free(chunk); +#endif return -1; } libsha1_update(&state, chunk, (size_t)r * 8); } libsha1_digest(&state, NULL, 0, hashsum); + +#if ALLOCA_LIMIT <= 0 + free(chunk); +#endif return 0; } diff --git a/update.c b/update.c index 1725eb8..8799061 100644 --- a/update.c +++ b/update.c @@ -21,7 +21,7 @@ libsha1_update(struct libsha1_state *restrict state, const void *restrict messag if (off) { n = msglen < sizeof(state->chunk) - off ? msglen : sizeof(state->chunk) - off; - memcpy(state->chunk + off, message, n); + memcpy(&state->chunk[off], message, n); if (off + n == sizeof(state->chunk)) libsha1_process(state, state->chunk); message += n; -- cgit v1.2.3-70-g09d2