Reject HTTP requests with an invalid (e.g. negative) Content-Length header value.

Make sure to allocate enough memory in buffers for the operations they are used for, and to check/enforce buffer sizes when performing those memory operations.
Properly allocate and free memory.
Make a best effort at allocating memory for the network hardware address (remove code for Apple platforms).
Try to consume all of the remaining content if a valid Content-Length header was provided.
Check for success when attempting to acquire mutexes.
This commit is contained in:
Wesley Miaw
2019-10-07 14:38:16 -07:00
parent 8c13345a4d
commit 93756a84ea
10 changed files with 555 additions and 300 deletions

View File

@@ -30,12 +30,16 @@
#include <ctype.h>
#include <string.h>
char* smartstrcat(char* dest, char* src, size_t max_chars) {
size_t copied = 0;
while ((*(dest++) = *(src++)) && copied++ < max_chars) {
static const char * unknown_str = "unknown";
char* smartstrncpy(char* dest, char* src, size_t max_chars) {
size_t copied;
for (copied = 0; copied < max_chars; copied++, dest++, src++) {
*dest = *src;
if (*dest == 0)
break;
}
// In case we over-stepped the size, end the string nicely.
*(--dest) = '\0';
*dest = 0;
return dest;
}
@@ -89,23 +93,33 @@ void xmlencode(char *dst, const char *src, size_t max_size) {
while (*src && current_size < max_size) {
switch (*src) {
case '&':
dst = smartstrcat(dst, "&amp;", max_size - current_size);
if (current_size + 5 >= max_size)
break;
dst = smartstrncpy(dst, "&amp;", max_size - current_size);
current_size += 5;
break;
case '\"':
dst = smartstrcat(dst, "&quot;", max_size - current_size);
if (current_size + 6 >= max_size)
break;
dst = smartstrncpy(dst, "&quot;", max_size - current_size);
current_size += 6;
break;
case '\'':
dst = smartstrcat(dst, "&apos;", max_size - current_size);
if (current_size + 6 >= max_size)
break;
dst = smartstrncpy(dst, "&apos;", max_size - current_size);
current_size += 6;
break;
case '<':
dst = smartstrcat(dst, "&lt;", max_size - current_size);
if (current_size + 4 >= max_size)
break;
dst = smartstrncpy(dst, "&lt;", max_size - current_size);
current_size += 4;
break;
case '>':
dst = smartstrcat(dst, "&gt;", max_size - current_size);
if (current_size + 4 >= max_size)
break;
dst = smartstrncpy(dst, "&gt;", max_size - current_size);
current_size += 4;
break;
default:
@@ -119,18 +133,34 @@ void xmlencode(char *dst, const char *src, size_t max_size) {
}
char *parse_app_name(const char *uri) {
char *unknown = NULL;
if (uri == NULL) {
return "unknown";
unknown = (char*)calloc(strlen(unknown_str) + 1, sizeof(char));
if (unknown == NULL) {
return NULL;
}
strncpy(unknown, unknown_str, strlen(unknown_str) + 1);
return unknown;
}
char *slash = strrchr(uri, '/');
if (slash == NULL || slash == uri) {
return "unknown";
unknown = (char*)calloc(strlen(unknown_str) + 1, sizeof(char));
if (unknown == NULL) {
return NULL;
}
strncpy(unknown, unknown_str, strlen(unknown_str) + 1);
return unknown;
}
char *begin = slash;
while ((begin != uri) && (*--begin != '/'))
;
begin++; // skip the slash
char *result = (char *) calloc(1, slash - begin+1);
if (*begin == '/') {
begin++; // skip the slash
}
char *result = (char *) calloc(slash - begin+1, sizeof(char));
if (result == NULL) {
return NULL;
}
strncpy(result, begin, slash - begin);
result[slash-begin]='\0';
return result;
@@ -151,6 +181,9 @@ char *parse_param(char *query_string, char *param_name) {
end++;
int result_size = end - start;
char *result = malloc(result_size + 1);
if (result == NULL) {
return NULL;
}
result[0] = '\0';
strncpy(result, start, result_size);
result[result_size] = '\0';
@@ -165,20 +198,46 @@ DIALData *parse_params(char * query_string) {
query_string++; // skip leading question mark
}
DIALData *result = NULL;
int err = 0;
char *query_string_dup = strdup(query_string);
char * name_value = strtok(query_string_dup, "&");
while (name_value != NULL) {
DIALData *tmp = (DIALData *) malloc(sizeof(DIALData));
if (tmp == NULL) {
err = 1;
break;
}
size_t name_value_length = strlen(name_value);
tmp->key = (char *) malloc(name_value_length);
tmp->value = (char *) malloc(name_value_length);
sscanf(name_value, "%[^=]=%s", tmp->key, tmp->value);
tmp->key = (char *) calloc(name_value_length + 1, sizeof(char));
if (tmp->key == NULL) {
free(tmp); tmp = NULL;
err = 1;
break;
}
tmp->value = (char *) calloc(name_value_length + 1, sizeof(char));
if (tmp->value == NULL) {
free(tmp->key); tmp->key = NULL;
free(tmp); tmp = NULL;
err = 1;
break;
}
int match = sscanf(name_value, "%[^=]=%s", tmp->key, tmp->value);
if (match != 2) {
free(tmp->value); tmp->value = NULL;
free(tmp->key); tmp->key = NULL;
free(tmp); tmp = NULL;
err = 1;
break;
}
tmp->next = result;
result = tmp;
name_value = strtok(NULL, "&"); // read next token
}
free(query_string_dup);
if (err) {
free_dial_data(&result); result = NULL;
}
return result;
}
@@ -194,7 +253,7 @@ char from_hex(char ch) {
/* Converts an integer value to its hex character*/
char to_hex(char code) {
static char hex[] = "0123456789abcdef";
return hex[code & 15];
return hex[code & 15];
}