From 07d6280864e16fb04098cb841d7887569a345506 Mon Sep 17 00:00:00 2001
From: Lorenz Stechauner <lorenz.stechauner@necronda.net>
Date: Thu, 12 Jan 2023 01:58:14 +0100
Subject: [PATCH] Fix list pointer bug in proxy

---
 src/lib/http.c               | 19 +++++++------------
 src/lib/http.h               |  4 ----
 src/lib/list.c               |  5 ++---
 src/lib/proxy.c              |  9 +++++----
 src/logger.c                 |  8 ++++++--
 src/worker/func.h            |  2 +-
 src/worker/proxy_handler.c   |  1 -
 src/worker/request_handler.c |  2 --
 src/worker/tcp_acceptor.c    |  2 ++
 9 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/src/lib/http.c b/src/lib/http.c
index abeef39..883f662 100644
--- a/src/lib/http.c
+++ b/src/lib/http.c
@@ -88,6 +88,7 @@ void http_free_res(http_res *res) {
 }
 
 int http_init_hdr(http_hdr *hdr) {
+    hdr->last_field_num = -1;
     hdr->fields = list_create(sizeof(http_field), HTTP_INIT_HEADER_FIELD_NUM);
     if (hdr->fields == NULL)
         return error_http(HTTP_ERROR_SYSCALL);
@@ -122,8 +123,11 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr,
     str_trim_lws(&pos1, &pos2);
     long len2 = pos2 - pos1;
 
+    char header_name[256];
+    sprintf(header_name, "%.*s", (int) len1, buf);
+
     int field_num = list_size(hdr->fields);
-    int found = http_get_header_field_num_len(hdr, buf, len1);
+    int found = http_get_header_field_num(hdr, header_name);
     if (!(flags & HTTP_MERGE_FIELDS) || found == -1) {
         if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0)
             return error_http(HTTP_ERROR_TOO_MANY_HEADER_FIELDS);
@@ -206,7 +210,6 @@ int http_receive_request(sock *client, http_req *req) {
     memset(req->method, 0, sizeof(req->method));
     memset(req->version, 0, sizeof(req->version));
     req->uri = NULL;
-    req->hdr.last_field_num = -1;
     http_init_hdr(&req->hdr);
 
     rcv_len = sock_recv(client, buf, CLIENT_MAX_HEADER_SIZE - 1, MSG_PEEK);
@@ -227,21 +230,13 @@ int http_receive_request(sock *client, http_req *req) {
 }
 
 const char *http_get_header_field(const http_hdr *hdr, const char *field_name) {
-    return http_get_header_field_len(hdr, field_name, strlen(field_name));
-}
-
-const char *http_get_header_field_len(const http_hdr *hdr, const char *field_name, unsigned long len) {
-    int num = http_get_header_field_num_len(hdr, field_name, len);
+    int num = http_get_header_field_num(hdr, field_name);
     return (num >= 0 && num < list_size(hdr->fields)) ? http_field_get_value(&hdr->fields[num]) : NULL;
 }
 
 int http_get_header_field_num(const http_hdr *hdr, const char *field_name) {
-    return http_get_header_field_num_len(hdr, field_name, strlen(field_name));
-}
-
-int http_get_header_field_num_len(const http_hdr *hdr, const char *field_name, unsigned long len) {
     for (int i = 0; i < list_size(hdr->fields); i++) {
-        if (strncasecmp(field_name, http_field_get_name(&hdr->fields[i]), len) == 0)
+        if (strcasecmp(field_name, http_field_get_name(&hdr->fields[i])) == 0)
             return i;
     }
 
diff --git a/src/lib/http.h b/src/lib/http.h
index 2d54357..813fbbb 100644
--- a/src/lib/http.h
+++ b/src/lib/http.h
@@ -156,12 +156,8 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr,
 
 const char *http_get_header_field(const http_hdr *hdr, const char *field_name);
 
-const char *http_get_header_field_len(const http_hdr *hdr, const char *field_name, unsigned long len);
-
 int http_get_header_field_num(const http_hdr *hdr, const char *field_name);
 
-int http_get_header_field_num_len(const http_hdr *hdr, const char *field_name, unsigned long len);
-
 int http_add_header_field(http_hdr *hdr, const char *field_name, const char *field_value);
 
 int http_add_header_field_len(http_hdr *hdr, const char *name, unsigned long name_len, const char *value, unsigned long value_len);
diff --git a/src/lib/list.c b/src/lib/list.c
index 0b3296c..b3b638e 100644
--- a/src/lib/list.c
+++ b/src/lib/list.c
@@ -113,7 +113,7 @@ void *list_remove(void *list_ptr, int n) {
     memset(array + list->size * list->elem_size, 0, list->elem_size);
 
     list->size--;
-    if (list->size < list->max_size / FACTOR / 2 && list->max_size / FACTOR >= list->init_size) {
+    if (list->size <= list->max_size / FACTOR * 3 / 4 && list->max_size / FACTOR >= list->init_size) {
         if ((list = list_resize(list, list->max_size / FACTOR)) == NULL) {
             return NULL;
         }
@@ -135,8 +135,7 @@ void *list_clear(void *list_ptr) {
     list_meta_t *list = meta(list_ptr);
     list->size = 0;
     memset(list_ptr, 0, list->max_size * list->elem_size);
-    list->max_size = list->init_size;
-    return data(list_resize(list, list->max_size));
+    return data(list_resize(list, list->init_size));
 }
 
 void list_free(void *list_ptr) {
diff --git a/src/lib/proxy.c b/src/lib/proxy.c
index a974f55..624bd72 100644
--- a/src/lib/proxy.c
+++ b/src/lib/proxy.c
@@ -163,20 +163,19 @@ int proxy_request_header(http_req *req, sock *sock) {
         http_add_header_field(&req->hdr, "Via", buf2);
     }
 
-    const char *host = http_get_header_field(&req->hdr, "Host");
-    const char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
     int client_ipv6 = strchr(sock->addr, ':') != NULL;
     int server_ipv6 = strchr(sock->s_addr, ':') != NULL;
 
     p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s",
                      server_ipv6 ? "\"[" : "", sock->s_addr, server_ipv6 ? "]\"" : "",
                      client_ipv6 ? "\"[" : "", sock->addr, client_ipv6 ? "]\"" : "",
-                     host, sock->enc ? "https" : "http");
+                     http_get_header_field(&req->hdr, "Host"), sock->enc ? "https" : "http");
     if (p_len < 0 || p_len >= sizeof(buf1)) {
         error("Appended part of header field 'Forwarded' too long");
         return -1;
     }
 
+    const char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
     if (forwarded == NULL) {
         http_add_header_field(&req->hdr, "Forwarded", buf1);
     } else {
@@ -199,9 +198,10 @@ int proxy_request_header(http_req *req, sock *sock) {
     }
 
     const char *xfh = http_get_header_field(&req->hdr, "X-Forwarded-Host");
+    forwarded = http_get_header_field(&req->hdr, "Forwarded");
     if (xfh == NULL) {
         if (forwarded == NULL) {
-            http_add_header_field(&req->hdr, "X-Forwarded-Host", host);
+            http_add_header_field(&req->hdr, "X-Forwarded-Host", http_get_header_field(&req->hdr, "Host"));
         } else {
             char *ptr = strchr(forwarded, ',');
             unsigned long len;
@@ -220,6 +220,7 @@ int proxy_request_header(http_req *req, sock *sock) {
     }
 
     const char *xfp = http_get_header_field(&req->hdr, "X-Forwarded-Proto");
+    forwarded = http_get_header_field(&req->hdr, "Forwarded");
     if (xfp == NULL) {
         if (forwarded == NULL) {
             http_add_header_field(&req->hdr, "X-Forwarded-Proto", sock->enc ? "https" : "http");
diff --git a/src/logger.c b/src/logger.c
index e0725ea..562c81b 100644
--- a/src/logger.c
+++ b/src/logger.c
@@ -165,14 +165,15 @@ static int logger_remaining(void) {
 void logger_set_name(const char *restrict format, ...) {
     va_list args;
 
+    void *ptr;
     if (key_name == -1) {
         // not initialized
         va_start(args, format);
         vsnprintf(global_name, sizeof(global_name), format, args);
+        ptr = global_name;
     } else {
         int ret;
-        void *ptr = pthread_getspecific(key_name);
-        if (!ptr) {
+        if ((ptr = pthread_getspecific(key_name)) == NULL) {
             ptr = malloc(LOG_NAME_LEN);
             if ((ret = pthread_setspecific(key_name, ptr)) != 0) {
                 errno = ret;
@@ -185,6 +186,9 @@ void logger_set_name(const char *restrict format, ...) {
         vsnprintf(ptr, LOG_NAME_LEN, format, args);
     }
 
+    // set thread name
+    pthread_setname_np(pthread_self(), global_name);
+
     // cleanup
     va_end(args);
 }
diff --git a/src/worker/func.h b/src/worker/func.h
index 6d0a23e..6ea0f68 100644
--- a/src/worker/func.h
+++ b/src/worker/func.h
@@ -23,7 +23,7 @@ typedef struct {
     char cc[3], host[256];
     char req_host[256], err_msg[256];
     char log_prefix[128];
-    char _c_addr[ADDRSTRLEN + 1], _s_addr[ADDRSTRLEN + 1];
+    char _c_addr[INET6_ADDRSTRLEN + 1], _s_addr[INET6_ADDRSTRLEN + 1];
     long cnx_s, cnx_e, req_s, res_ts, req_e;
     http_req req;
     http_res res;
diff --git a/src/worker/proxy_handler.c b/src/worker/proxy_handler.c
index a3d65d4..5984f10 100644
--- a/src/worker/proxy_handler.c
+++ b/src/worker/proxy_handler.c
@@ -14,7 +14,6 @@
 #include "../workers.h"
 
 #include <string.h>
-#include <errno.h>
 
 static int proxy_handler_1(client_ctx_t *ctx);
 static int proxy_handler_2(client_ctx_t *ctx);
diff --git a/src/worker/request_handler.c b/src/worker/request_handler.c
index 3fec749..1cc8581 100644
--- a/src/worker/request_handler.c
+++ b/src/worker/request_handler.c
@@ -62,10 +62,8 @@ static void init_ctx(client_ctx_t *ctx) {
     memset(&ctx->req, 0, sizeof(ctx->req));
     memset(&ctx->res, 0, sizeof(ctx->res));
 
-
     ctx->res.status = http_get_status(501);
     http_init_hdr(&ctx->res.hdr);
-    ctx->res.hdr.last_field_num = -1;
     sprintf(ctx->res.version, "1.1");
 
     ctx->status.status = 0;
diff --git a/src/worker/tcp_acceptor.c b/src/worker/tcp_acceptor.c
index 170fe6d..b9a6876 100644
--- a/src/worker/tcp_acceptor.c
+++ b/src/worker/tcp_acceptor.c
@@ -32,6 +32,8 @@ void tcp_acceptor_func(client_ctx_t *ctx) {
 static int tcp_acceptor(client_ctx_t *ctx) {
     struct sockaddr_in6 server_addr;
 
+    memset(ctx->_c_addr, 0, sizeof(ctx->_c_addr));
+    memset(ctx->_s_addr, 0, sizeof(ctx->_s_addr));
     inet_ntop(ctx->socket._addr.ipv6.sin6_family, &ctx->socket._addr.ipv6.sin6_addr, ctx->_c_addr, sizeof(ctx->_c_addr));
     if (strstarts(ctx->_c_addr, "::ffff:")) {
         ctx->socket.addr = ctx->_c_addr + 7;