diff options
author | EuAndreh <eu@euandre.org> | 2021-08-20 08:02:33 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2021-08-20 08:02:33 -0300 |
commit | 97abd351ebd000f2d3c15157f4c2762200a42dca (patch) | |
tree | 0377c4c9573fed81b2c41748bdc5373a0f3a7b71 /src/gistatic.c | |
parent | src/gistatic.c: Reword comment on date format (diff) | |
download | gistatic-97abd351ebd000f2d3c15157f4c2762200a42dca.tar.gz gistatic-97abd351ebd000f2d3c15157f4c2762200a42dca.tar.xz |
src/gistatic.c: Handle overflow of size_t values
Diffstat (limited to 'src/gistatic.c')
-rw-r--r-- | src/gistatic.c | 79 |
1 files changed, 73 insertions, 6 deletions
diff --git a/src/gistatic.c b/src/gistatic.c index b6040e8..a2c9c14 100644 --- a/src/gistatic.c +++ b/src/gistatic.c @@ -518,7 +518,15 @@ static char *strjoin(const char *const s1, const char *const s2) { return NULL; } - const size_t size = strlen(s1) + strlen(s2) + sizeof('\0'); + const size_t size1 = strnlen(s1, SIZE_MAX); + const size_t size2 = strnlen(s2, SIZE_MAX - sizeof('\0')) + + sizeof('\0'); + if (SIZE_MAX - size1 < size2) { + errno = EOVERFLOW; + logerr("strjoin()", strerror(errno), __LINE__); + return NULL; + } + const size_t size = size1 + size2; char *const s = malloc(size); if (!s) { logerrl("malloc(", size, ")", strerror(errno), __LINE__); @@ -658,6 +666,39 @@ static void test_formatted_date(void) { } #endif +static size_t max(const size_t size1, const size_t size2) { + return size1 > size2 ? size1 : size2; +} + +#ifdef TEST +static void test_max(void) { + test_start("max()"); + { + testing("equal values"); + assert(max(1, 1) == 1); + assert(max(3, 3) == 3); + assert(max(0, 0) == 0); + assert(max(999, 999) == 999); + assert(max(SIZE_MAX, SIZE_MAX) == SIZE_MAX); + test_ok(); + } + { + testing("first is bigger"); + assert(max(SIZE_MAX, SIZE_MAX - 1) == SIZE_MAX); + assert(max(SIZE_MAX - 1, SIZE_MAX - 2) == SIZE_MAX - 1); + assert(max(1, 0) == 1); + assert(max(999, 3) == 999); + test_ok(); + } + { + testing("second is bigger"); + assert(max(123, 321) == 321); + assert(max(1, 999) == 999); + test_ok(); + } +} +#endif + static char *escape_html(const char *s) { if (!s) { return NULL; @@ -681,10 +722,17 @@ static char *escape_html(const char *s) { const size_t DQUOT_SIZE = strlen(DQUOT); const size_t SQUOT_SIZE = strlen(SQUOT); - const size_t input_size = strlen(s); + const size_t BIGGEST = max(AMP_SIZE, max(LT_SIZE, max(GT_SIZE, + max(DQUOT_SIZE, SQUOT_SIZE)))); + const size_t input_size = strnlen(s, SIZE_MAX); size_t escaped_size = 0; for (size_t i = 0; i < input_size; i++) { + if (SIZE_MAX - escaped_size < BIGGEST) { + errno = EOVERFLOW; + logerr("escape_html()", strerror(errno), __LINE__); + return NULL; + } switch (s[i]) { case AMPCHAR: escaped_size += AMP_SIZE; @@ -867,7 +915,7 @@ static void strtrim(char *const s) { return; } - size_t len = strlen(s); + size_t len = strnlen(s, SIZE_MAX); while (len != 0 && should_trim(s[len - 1])) { s[len - 1] = '\0'; len--; @@ -1041,8 +1089,21 @@ static int index_write_header(FILE *const fd, const char *const idx_title) { } static char *footer_signature_string(void) { - const size_t signature_size = strlen(_(MSG_FOOTER_TEMPLATE)) - - strlen("%s") + strlen(PROJECT_HOMEPAGE_LINK) + sizeof('\0'); + const size_t template_size = strnlen( + _(MSG_FOOTER_TEMPLATE), + SIZE_MAX + ) - strlen("%s"); + const size_t link_size = strnlen( + PROJECT_HOMEPAGE_LINK, + SIZE_MAX - sizeof('\0') + ) + sizeof('\0'); + if (SIZE_MAX - template_size < link_size) { + errno = EOVERFLOW; + logerr("footer_signature_string()", strerror(errno), __LINE__); + return NULL; + } + const size_t signature_size = template_size + link_size; + char *const signature_text = malloc(signature_size); if (!signature_text) { logerrl("malloc(", signature_size, ")", strerror(errno), @@ -1050,7 +1111,12 @@ static char *footer_signature_string(void) { return NULL; } - sprintf(signature_text, _(MSG_FOOTER_TEMPLATE), PROJECT_HOMEPAGE_LINK); + snprintf( + signature_text, + signature_size, + _(MSG_FOOTER_TEMPLATE), + PROJECT_HOMEPAGE_LINK + ); return signature_text; } @@ -1974,6 +2040,7 @@ static void unit_tests(){ test_remove_suffix(); test_strjoin(); test_formatted_date(); + test_max(); test_escape_html(); test_should_trim(); test_strtrim(); |