Fix memory leak on location rewrite in rev_proxy

This commit is contained in:
2022-08-16 21:03:50 +02:00
parent abe0e326cb
commit b6ba58d406
4 changed files with 31 additions and 33 deletions

View File

@ -498,9 +498,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
const char *content_type = http_get_header_field(&res.hdr, "Content-Type"); const char *content_type = http_get_header_field(&res.hdr, "Content-Type");
const char *content_length_f = http_get_header_field(&res.hdr, "Content-Length"); const char *content_length_f = http_get_header_field(&res.hdr, "Content-Length");
const char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding"); const char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
if (content_encoding == NULL && content_type != NULL && content_length_f != NULL && if (content_encoding == NULL && content_type != NULL && content_length_f != NULL && strncmp(content_type, "text/html", 9) == 0) {
strncmp(content_type, "text/html", 9) == 0)
{
long content_len = strtol(content_length_f, NULL, 10); long content_len = strtol(content_length_f, NULL, 10);
if (content_len <= sizeof(msg_content) - 1) { if (content_len <= sizeof(msg_content) - 1) {
ctx.status = res.status->code; ctx.status = res.status->code;

View File

@ -48,22 +48,25 @@ const char *http_field_get_value(const http_field *field) {
return NULL; return NULL;
} }
void http_free_field(http_field *f) {
if (f->type == HTTP_FIELD_NORMAL) {
f->normal.name[0] = 0;
f->normal.value[0] = 0;
} else if (f->type == HTTP_FIELD_EX_VALUE) {
f->ex_value.name[0] = 0;
free(f->ex_value.value);
f->ex_value.value = NULL;
} else if (f->type == HTTP_FIELD_EX_NAME) {
free(f->ex_name.name);
free(f->ex_name.value);
f->ex_name.name = NULL;
f->ex_name.value = NULL;
}
}
void http_free_hdr(http_hdr *hdr) { void http_free_hdr(http_hdr *hdr) {
for (int i = 0; i < hdr->field_num; i++) { for (int i = 0; i < hdr->field_num; i++) {
http_field *f = &hdr->fields[i]; http_free_field(&hdr->fields[i]);
if (f->type == HTTP_FIELD_NORMAL) {
f->normal.name[0] = 0;
f->normal.value[0] = 0;
} else if (f->type == HTTP_FIELD_EX_VALUE) {
f->ex_value.name[0] = 0;
free(f->ex_value.value);
f->ex_value.value = NULL;
} else if (f->type == HTTP_FIELD_EX_NAME) {
free(f->ex_name.name);
free(f->ex_name.value);
f->ex_name.name = NULL;
f->ex_name.value = NULL;
}
} }
hdr->field_num = 0; hdr->field_num = 0;
hdr->last_field_num = -1; hdr->last_field_num = -1;
@ -326,6 +329,7 @@ void http_remove_header_field(http_hdr *hdr, const char *field_name, int mode) {
strcpy(field_name_2, http_field_get_name(&hdr->fields[i])); strcpy(field_name_2, http_field_get_name(&hdr->fields[i]));
http_to_camel_case(field_name_2, HTTP_LOWER); http_to_camel_case(field_name_2, HTTP_LOWER);
if (strcmp(field_name_1, field_name_2) == 0) { if (strcmp(field_name_1, field_name_2) == 0) {
http_free_field(&hdr->fields[i]);
memmove(&hdr->fields[i], &hdr->fields[i + 1], sizeof(hdr->fields[0]) * (hdr->field_num - i)); memmove(&hdr->fields[i], &hdr->fields[i + 1], sizeof(hdr->fields[0]) * (hdr->field_num - i));
hdr->field_num--; hdr->field_num--;
if (mode == HTTP_REMOVE_ALL) { if (mode == HTTP_REMOVE_ALL) {

View File

@ -130,6 +130,8 @@ const char *http_field_get_name(const http_field *field);
const char *http_field_get_value(const http_field *field); const char *http_field_get_value(const http_field *field);
void http_free_field(http_field *f);
void http_free_hdr(http_hdr *hdr); void http_free_hdr(http_hdr *hdr);
void http_free_req(http_req *req); void http_free_req(http_req *req);

View File

@ -29,8 +29,7 @@ int rev_proxy_preload() {
} }
int rev_proxy_request_header(http_req *req, int enc) { int rev_proxy_request_header(http_req *req, int enc) {
char buf1[256]; char buf1[256], buf2[256];
char buf2[256];
int p_len; int p_len;
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL); http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
http_add_header_field(&req->hdr, "Connection", "keep-alive"); http_add_header_field(&req->hdr, "Connection", "keep-alive");
@ -52,7 +51,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
const char *host = http_get_header_field(&req->hdr, "Host"); const char *host = http_get_header_field(&req->hdr, "Host");
const char *forwarded = http_get_header_field(&req->hdr, "Forwarded"); const char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
int client_ipv6 = strchr(client_addr_str, ':') != NULL; int client_ipv6 = strchr(client_addr_str, ':') != NULL;
int server_ipv6 = strchr(server_addr_str, ':') != NULL; int server_ipv6 = strchr(server_addr_str, ':') != NULL;
p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s", p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s",
server_ipv6 ? "\"[" : "", server_addr_str, server_ipv6 ? "]\"" : "", server_ipv6 ? "\"[" : "", server_addr_str, server_ipv6 ? "]\"" : "",
@ -62,6 +61,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
print(ERR_STR "Appended part of header field 'Forwarded' too long" CLR_STR); print(ERR_STR "Appended part of header field 'Forwarded' too long" CLR_STR);
return -1; return -1;
} }
if (forwarded == NULL) { if (forwarded == NULL) {
http_add_header_field(&req->hdr, "Forwarded", buf1); http_add_header_field(&req->hdr, "Forwarded", buf1);
} else { } else {
@ -129,8 +129,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
} }
int rev_proxy_response_header(http_req *req, http_res *res, host_config *conf) { int rev_proxy_response_header(http_req *req, http_res *res, host_config *conf) {
char buf1[256]; char buf1[256], buf2[256];
char buf2[256];
int p_len; int p_len;
const char *via = http_get_header_field(&res->hdr, "Via"); const char *via = http_get_header_field(&res->hdr, "Via");
@ -172,20 +171,19 @@ int rev_proxy_response_header(http_req *req, http_res *res, host_config *conf) {
if (0) { if (0) {
match: match:
strcpy(buf1, location + p_len - 1);
http_remove_header_field(&res->hdr, "Location", HTTP_REMOVE_ALL); http_remove_header_field(&res->hdr, "Location", HTTP_REMOVE_ALL);
http_add_header_field(&res->hdr, "Location", location + p_len - 1); http_add_header_field(&res->hdr, "Location", buf1);
} }
} }
return 0; return 0;
} }
int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client, int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client, http_status *custom_status, char *err_msg) {
http_status *custom_status, char *err_msg) {
char buffer[CHUNK_SIZE]; char buffer[CHUNK_SIZE];
long ret; long ret;
int tries = 0; int tries = 0, retry = 0;
int retry = 0;
if (rev_proxy.socket != 0 && strcmp(rev_proxy_host, conf->name) == 0 && sock_check(&rev_proxy) == 0) { if (rev_proxy.socket != 0 && strcmp(rev_proxy_host, conf->name) == 0 && sock_check(&rev_proxy) == 0) {
goto rev_proxy; goto rev_proxy;
@ -455,13 +453,9 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf
int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) { int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) {
// TODO handle websockets // TODO handle websockets
long ret = 0; char buffer[CHUNK_SIZE], comp_out[CHUNK_SIZE], buf[256], *ptr;
char buffer[CHUNK_SIZE]; long ret = 0, len, snd_len;
char comp_out[CHUNK_SIZE];
char buf[256];
long len, snd_len;
int finish_comp = 0; int finish_comp = 0;
char *ptr;
compress_ctx comp_ctx; compress_ctx comp_ctx;
if (flags & REV_PROXY_COMPRESS_BR) { if (flags & REV_PROXY_COMPRESS_BR) {