Skip to content

Fix mismatched free for cJSON-generated string in dynsec__config_save #3287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 11, 2025

Conversation

jesferman
Copy link
Contributor

@jesferman jesferman commented Jun 11, 2025

Summary

This PR changes the deallocation of the JSON string returned by cJSON_Print() from mosquitto_free() to cJSON_free(), fixing a memory‐tracking underflow caused by mixing allocators. This underflow makes the tracking subsystem thinks that it has a lot of GB reserved, and any subsequent call to mosquitto_malloc() returns "out of memory" which leaves the broker unusable after a few operations with the Dynamic Security Plugin. The only way of recovering it is restarting Mosquitto.

Background & Problem

In dynsec__config_save(), the code currently does:

json_str = cJSON_Print(tree);
/* … */
mosquitto_free(json_str);

However:

  • cJSON_Print() internally allocates with cJSON_malloc().
  • Freeing that memory with mosquitto_free() (instead of cJSON_free()) decrements Mosquitto’s own allocation counter (memory_mosq.c) for a pointer that was never allocated and counted by mosquitto_malloc(), causing the counter to underflow.
  • On the next mosquitto_malloc() this counter appears “too large,” causing subsequent allocations to spuriously fail with “out of memory,” rendering the broker unusable until restart.

How to reproduce

Set a memory_limit in mosquitto.conf

Using the dynamic security plugin perform a few operations of adding and/or removing users to/from ACL rules. The counter of the memory tracker will decrease with each operation until it underflows.


  • Have you signed the Eclipse Contributor Agreement, using the same email address as you used in your commits?
  • Do each of your commits have a "Signed-off-by" line, with the correct email address? Use "git commit -s" to generate this line for you.
  • If you are contributing a bugfix, is your work based off the fixes branch?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you successfully run make test with your changes locally?

The JSON string produced by cJSON_Print() is allocated with cJSON_malloc()
and must be freed with cJSON_free(), not mosquitto_free(). Using the wrong
allocator caused Mosquitto’s memory-tracking counter to underflow, leading
to spurious "out of memory" errors on subsequent allocations which
render the broker unusable.

This change replaces mosquitto_free(json_str) with cJSON_free(json_str)
in dynsec__config_save(), ensuring correct matching of allocators and
eliminating the underflow bug.

Signed-off-by: Jesús Fernández Manzano <[email protected]>
@ralight ralight merged commit e1ab390 into eclipse-mosquitto:fixes Jul 11, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants