Fix duplicate header leak in ACLK HTTPS client (#21084)
fix(aclk): free previous header values before overwrite Refs: netdata/netdata#21083
Costa Tsaousis committed
Oct 2, 2025 at 08:49 UTC
41d9554a022dc6ba69d6587a859425198c4430a7
1 file changed
+30
-10
src/aclk/https_client.c
+30
-10
@@ -147,15 +147,6 @@ static const char *http_req_type_to_str(http_req_type_t req) {
147
148
#define TRANSFER_ENCODING_CHUNKED (-2)
149
150
-void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state)
151
-{
152
- ctx->state = parse_state;
153
- ctx->content_length = -1;
154
- ctx->http_code = 0;
155
- ctx->headers = c_rhash_new(0);
156
- ctx->flags = HTTP_PARSE_FLAGS_DEFAULT;
157
-}
158
-
150
void http_parse_ctx_destroy(http_parse_ctx *ctx)
151
{
152
if(!ctx->headers)
@@ -175,6 +166,23 @@ void http_parse_ctx_destroy(http_parse_ctx *ctx)
166
ctx->headers = NULL;
167
}
168
169
+void http_parse_ctx_create(http_parse_ctx *ctx, enum http_parse_state parse_state)
170
+{
171
+ http_parse_ctx_destroy(ctx);
172
+
173
+ ctx->state = parse_state;
174
+ ctx->content_length = -1;
175
+ ctx->http_code = 0;
176
+ ctx->headers = c_rhash_new(0);
177
+ ctx->flags = HTTP_PARSE_FLAGS_DEFAULT;
178
+ ctx->chunked_content_state = CHUNKED_CONTENT_CHUNK_SIZE;
179
+ ctx->chunk_size = 0;
180
+ ctx->chunk_got = 0;
181
+ ctx->chunked_response_written = 0;
182
+ ctx->chunked_response_size = 0;
183
+ ctx->chunked_response = NULL;
184
+}
185
+
186
#define POLL_TO_MS 100
187
188
#define HTTP_LINE_TERM "\x0D\x0A"
@@ -214,6 +222,10 @@ static int process_http_hdr(http_parse_ctx *parse_ctx, const char *key, const ch
222
}
223
return 0;
224
}
225
+ void *prev_val = NULL;
226
+ if (!c_rhash_get_ptr_by_str(parse_ctx->headers, key, &prev_val))
227
+ freez(prev_val); // drop previous allocation before overwriting
228
+
229
char *val_cpy = strdupz(val);
230
c_rhash_insert_str_ptr(parse_ctx->headers, key, val_cpy);
231
return 0;
@@ -710,8 +722,12 @@ static https_client_resp_t handle_http_request(https_req_ctx_t *ctx) {
722
rc = read_parse_response(ctx);
723
if (rc != HTTPS_CLIENT_RESP_OK) {
724
netdata_log_error("ACLK: error reading or parsing response from server");
713
- if (ctx->parse_ctx.chunked_response)
725
+ if (ctx->parse_ctx.chunked_response) {
726
freez(ctx->parse_ctx.chunked_response);
727
+ ctx->parse_ctx.chunked_response = NULL;
728
+ ctx->parse_ctx.chunked_response_size = 0;
729
+ ctx->parse_ctx.chunked_response_written = 0;
730
+ }
731
}
732
733
err_exit:
@@ -887,6 +903,9 @@ https_client_resp_t https_request(https_req_t *request, https_req_response_t *re
903
if (ctx->parse_ctx.content_length == TRANSFER_ENCODING_CHUNKED) {
904
response->payload_size = ctx->parse_ctx.chunked_response_size;
905
response->payload = ctx->parse_ctx.chunked_response;
906
+ ctx->parse_ctx.chunked_response = NULL;
907
+ ctx->parse_ctx.chunked_response_size = 0;
908
+ ctx->parse_ctx.chunked_response_written = 0;
909
}
910
if (ctx->parse_ctx.content_length > 0) {
911
response->payload_size = ctx->parse_ctx.content_length;
@@ -918,6 +937,7 @@ exit_sock:
937
exit_buf_rx:
938
rbuf_free(ctx->buf_rx);
939
exit_req_ctx:
940
+ http_parse_ctx_destroy(&ctx->parse_ctx);
941
freez(ctx);
942
return rc;
943
}