cli: fix memory leak in volume status detail (#4292)#4675
cli: fix memory leak in volume status detail (#4292)#4675ThalesBarretto wants to merge 1 commit into
Conversation
60d6193 to
3690dca
Compare
37abfec to
b4b9d5a
Compare
cli_volume_status_t has seven pointer fields, but they have two
different ownership models:
Owned (heap-allocated, caller must free):
- brick — GF_MALLOC before the loop
- pid_str — gf_asprintf each iteration
- free, total — gf_uint64_2human_readable inside cli_get_detail_status
Borrowed (point into dict internals, released by dict_unref at out:):
- fs_name, mount_options, device, inode_size — dict_get_str
The status variable is declared once outside the loop with = {0}.
Each iteration overwrites the owned pointers with new allocations.
Before this fix, only pid_str was freed inside the loop body and
only brick was freed at the out: label. The other two owned
pointers (free, total) were simply overwritten each iteration — the
previous values were lost, leaking two strings per brick.
The fix adds three things:
1. GF_FREE for free and total inside the loop, matching what was
already done for pid_str.
2. GF_FREE for pid_str, free, and total at the out: label, covering
the two goto-out error paths mid-iteration (gf_asprintf failure
at line 7592 and cli_get_detail_status failure at line 7597)
where the current iteration's allocations have not been freed yet.
3. Explicit NULLing after each in-loop GF_FREE. On the normal path
the loop finishes, execution falls through cont: to out:, which
calls GF_FREE on the same pointers again. Without NULLing, that
would be a double-free. With it, GF_FREE(NULL) is a no-op.
Signed-off-by: Thales Antunes de Oliveira Barretto <thales.barretto.git@gmail.com>
b4b9d5a to
18e96ed
Compare
|
@sanjurakonde would you mind taking a look here, i think this one is pretty straightforward |
|
There is no need for:
Note that generating AI slop wastes electricity and the time of real human developers. |
Thanks for your interest in glusterfs, your contributions are welcome, feel free to propose a patch |
|
Thanks for the review. Let me address each point with code references. On point 2 —
They must be freed by the caller, unlike the four On point 3 — freeing On point 1 — the NULLing fixes a second, separate issue. After On point 4 — agreed, the CLI is short-lived and this is not a critical storage bug. It is a correctness fix for a reported issue (#4292) with an ASan trace. |
Ownership model
cli_volume_status_thas seven pointer fields with two different ownership models:Owned (heap-allocated, caller must free):
brick—GF_MALLOCbefore the looppid_str—gf_asprintfeach iterationfree,total—gf_uint64_2human_readableinsidecli_get_detail_statusBorrowed (point into dict internals, released by
dict_unrefatout:):fs_name,mount_options,device,inode_size— all fromdict_get_strThe bug
statusis declared once outside the loop with= {0}. Each iteration overwrites the owned pointers with new heap allocations. Before this fix, onlypid_strwas freed inside the loop body and onlybrickat theout:label. The other two owned fields (free,total) were overwritten each iteration — previous values lost, two strings leaked per brick. The reporter's ASan trace confirms 144 bytes in 4 allocations (2 calls × 2 bricks).What the fix does
freeandtotalfreed in the loop — matching what was already done forpid_str.pid_str,free,totalfreed atout:— covers the twogoto outerror paths mid-iteration (gf_asprintffailure andcli_get_detail_statusfailure) where the current iteration's allocations haven't been freed yet.Explicit NULLing after each in-loop
GF_FREE— on the normal path the loop finishes, execution falls throughcont:toout:, which callsGF_FREEon the same pointers. Without NULLing that's a double-free; with it,GF_FREE(NULL)is a no-op.Fixes: #4292