summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-08-14 05:20:03 -0700
committerVito Caputo <vcaputo@pengaru.com>2023-08-14 05:20:03 -0700
commit9db90b0f8cdf41d5f8241babe50bed1578e8cfa1 (patch)
treeb348d4cecb30456cabcee895960551ea78cd3ca0
parent210580bb0bbd14c02c2ba929012399ec32885de1 (diff)
til_str: handle overflows in til_str_appendf()
In the wholesale transition to til_module_setup_full() there's been a lot more problematic randomized setups either extremely deep or plain infinite. Due to the primitive escaping mechanism performed by til_settings_as_arg(), where escape patterns grow exponentially with depth, it's quite realistic (and observed) for these problematic setups to exceed SIZE_MAX. So I'm putting some guard rails in to cap a given til_str_t to SIZE_MAX. It might make more sense to move the limit well below SIZE_MAX, but this should at least prevent overflows.
-rw-r--r--src/til_str.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/src/til_str.c b/src/til_str.c
index 4c8a0ad..0a4a640 100644
--- a/src/til_str.c
+++ b/src/til_str.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stdarg.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -25,6 +26,7 @@ struct til_str_t {
#define TIL_STR_MIN_SIZE 64
+#define TIL_STR_MAX_GROWBY (TIL_STR_MIN_SIZE * 1024)
/* alloc always returns a buf w/nul terminator present */
@@ -118,11 +120,18 @@ int til_str_appendf(til_str_t *str, const char *format, ...)
len = vsnprintf(NULL, 0, format, ap);
va_end(ap);
+ if (SIZE_MAX - len < str->size.used)
+ return -EOVERFLOW;
+
if (str->size.used + len > str->size.allocated) {
char *new;
- str->size.growby += TIL_STR_MIN_SIZE;
+ if (str->size.growby < TIL_STR_MAX_GROWBY)
+ str->size.growby += TIL_STR_MIN_SIZE;
+
len = MAX(str->size.growby, len);
+ if (SIZE_MAX - len < str->size.used)
+ len = SIZE_MAX - str->size.used;
new = realloc(str->buf, str->size.used + len);
if (!new)
© All Rights Reserved