From 1bcc672503351f6b7c3c1f4a6632f0589f230929 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Fri, 16 Dec 2016 23:40:44 +0100 Subject: [PATCH] Reimplemented memory management in dirlisting generation This should eliminate all bufferoverflows introduced by the previous usage of strcat() and various assumptions. --- include/util.h | 1 + src/dirlisting.c | 74 ++++++++++++++---------------------------------- src/util.c | 34 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 52 deletions(-) diff --git a/include/util.h b/include/util.h index 13838bd..bc6ee3a 100644 --- a/include/util.h +++ b/include/util.h @@ -17,5 +17,6 @@ void remove_trailing_slash(char *str); void urlencode(const char *str, char *result); +char* safe_append(char *target, size_t *targetsize, const char *src); #endif // UTIL_H diff --git a/src/dirlisting.c b/src/dirlisting.c index 62df779..82ed552 100644 --- a/src/dirlisting.c +++ b/src/dirlisting.c @@ -79,21 +79,20 @@ char* gen_html(const char *url, struct Entry *entries, size_t numentries, int up result = malloc(allocated * sizeof(char)); result[0] = '\0'; - // this is still safe - strcat(result, HEADER1); + result = safe_append(result, &allocated, HEADER1); snprintf(buf, BUFSIZE, "Directory listing for %s", url); - strcat(result, buf); + result = safe_append(result, &allocated, buf); - strcat(result, HEADER2); + result = safe_append(result, &allocated, HEADER2); snprintf(buf, BUFSIZE, "

Directory listing for %s

", url); - strcat(result, buf); + result = safe_append(result, &allocated, buf); int isrootdir = strcmp(url, "/") == 0; // Begin Navigation - strcat(result, "

Navigation: "); + result = safe_append(result, &allocated, "

Navigation: "); // tokenize the URL: init char *token, *urlclone; @@ -103,30 +102,31 @@ char* gen_html(const char *url, struct Entry *entries, size_t numentries, int up strcpy(fullpath, "/"); if(isrootdir) { - strcat(result, "/"); + result = safe_append(result, &allocated, "/"); } else { - strcat(result, "/"); + result = safe_append(result, &allocated, "/"); // create a link for each token in URL do { LOG(LVL_DUMP, "Found token of %s: %s", url, token); + // TODO: check if this is safe strcat(fullpath, token); strcat(fullpath, "/"); snprintf(buf, BUFSIZE, " %s /", fullpath, token); - strcat(result, buf); + result = safe_append(result, &allocated, buf); } while((token = strtok(NULL, "/")) != NULL); } free(urlclone); - strcat(result, "

"); + result = safe_append(result, &allocated, "

"); // begin listing subdirs - strcat(result, "

Sub-directories

"); - strcat(result, ""); // begin listing files - strcat(result, "

Files

"); - strcat(result, ""); if(uploadEnabled) { - strcat(result, "

Upload

"); - strcat(result, "

Upload a file to this directory:

"); - strcat(result, + result = safe_append(result, &allocated, "

Upload

"); + result = safe_append(result, &allocated, "

Upload a file to this directory:

"); + result = safe_append(result, &allocated, "

" "

" " " @@ -214,7 +184,7 @@ char* gen_html(const char *url, struct Entry *entries, size_t numentries, int up ); } - strcat(result, FOOTER); + result = safe_append(result, &allocated, FOOTER); LOG(LVL_DEBUG, "result string (files) usage: %lu/%lu bytes", strlen(result), allocated); diff --git a/src/util.c b/src/util.c index b42eb29..665eca5 100644 --- a/src/util.c +++ b/src/util.c @@ -11,8 +11,11 @@ #include #include #include +#include +#include #include "util.h" +#include "logger.h" void remove_trailing_slash(char *str) { size_t offset = strlen(str)-1; @@ -49,3 +52,34 @@ void urlencode(const char *str, char *result) { str++; } } + +/*! + * Append src to target, reallocating target on the way if necessary. + * + * \param target The string to append to. + * \param targetsize A pointer to the size of target. Will be updated by this + * function when target is reallocated. + * \param src The string to append to target. + * \returns A pointer to new string (target becomes invalid in the + * event of reallocation) or NULL on a realloc error. + */ +char* safe_append(char *target, size_t *targetsize, const char *src) { + size_t targetlen = strlen(target); + size_t srclen = strlen(src); + size_t newsize = targetlen + 2*srclen + 1; + + // check if reallocation is necessary + if((targetlen + srclen) > *targetsize) { + LOG(LVL_DEBUG, "safe_append: reallocating target string: %lu -> %lu characters", *targetsize, newsize); + + target = realloc(target, newsize * sizeof(char)); + if(target == NULL) { + LOG(LVL_ERR, "safe_append: realloc failed: %s", strerror(errno)); + return NULL; + } + + *targetsize = newsize; + } + + return strcat(target, src); +}