@cryptotaxi247 / netdata-1 / commits / 54e4c8d0d

Fix payload memory leak (#22492)

fix(aclk): free cloud_to_agent.payload on v2 cmd success path aclk_handle_cloud_cmd_message parsed the cmd JSON into a local struct aclk_request. The error path freed payload, msg_id and callback_topic, but the v2 success path returned without freeing the JSON-parsed payload field. msg_id and callback_topic are transferred into the query and released by aclk_query_free; the v2 handler derives the HTTP body from the raw frame and never consumes the parsed payload, so it was leaked whenever the cmd JSON included a "payload" key. Free cloud_to_agent.payload after the success branch and document the ownership invariant on struct aclk_request so future field additions extend both cleanup paths.

Stelios Fragkakis committed May 17, 2026 at 22:43 UTC 54e4c8d0db92537044ae77624971740ded38d800
1 file changed +12 -2
src/aclk/aclk_rx_msgs.c
+12 -2
@@ -17,6 +17,13 @@
17 struct aclk_request {
18 bool has_type;
19 bool is_http;
20 + // Heap-allocated string fields below are owned by the local instance in
21 + // aclk_handle_cloud_cmd_message. On the v2 success path, msg_id and
22 + // callback_topic are transferred into the query and released by
23 + // aclk_query_free; payload is not consumed by v2 (the HTTP body is
24 + // re-derived from the raw frame) and must be freed by the caller on both
25 + // success and error paths. Any new owned field added here must extend
26 + // both cleanup paths to preserve this invariant.
27 char *msg_id;
28 char *callback_topic;
29 char *payload;
@@ -205,8 +212,11 @@ int aclk_handle_cloud_cmd_message(char *payload)
212 }
213
214 if (likely(!aclk_handle_cloud_http_request_v2(&cloud_to_agent, payload))) {
208 - // aclk_handle_cloud_request takes ownership of the pointers
209 - // (to avoid copying) in case of success
215 + // aclk_handle_cloud_http_request_v2 takes ownership of msg_id and
216 + // callback_topic on success. The JSON-parsed payload field is not
217 + // consumed by v2 (the HTTP body comes from the raw frame), so free
218 + // it here to avoid leaking when the cmd JSON included a "payload" key.
219 + freez(cloud_to_agent.payload);
220 return 0;
221 }
222