This is terrible in both the "why is systemd doing this" and "it's just plain terrible software" sense.
This is terrible in both the "why is systemd doing this" and "it's just plain terrible software" sense.
That's only really an issue if someone ever turns this into a library and calls it from long-running code. As a command line utility the small amounts of memory that are leaked don't ammount to too much waste and everything gets reclaimed on exit.
This is Poetterings code after all, and he had his fingers in more than just command line utilities when it comes to systemd.
Writing this kind of software in C requires serious discipline and religious use of valgrind.
Being able to manage your allocation is a pretty good sign that a C programmer knows what he's doing. Relying on 'exit' to free your memory is backporting the web mentality to unix land, it just simply doesn't work that way. There is no different attitude when you write a long running daemon versus a utility program because for all you know your utility program code will be re-purposed to become part of a longer running daemon. So you write your code in as clean a manner as possible and balance your allocs/frees and make sure that you don't have any latent buffer overflows which you may not care about today because of the context your code executes in today because tomorrow that context of execution might change and then we're looking at yet another exploit.
A very fitting description of systemd as a whole.
> someone ... can't get memory leaks in a simple utility function right
because in a simple one-off utility it is right. Potterings didn't write these utilities to prove that he knew how to refcount.
At some point someone may come along and refactor this Docker import code into a library or something bigger.
The liberal use of completely unportable cleanup attributes shifts preventing memory leaks to the equally intractable problem of tracking stack allocated variable assignments, with an extra helping of double frees. I won't even comment on the show of horrors that is util:
http://cgit.freedesktop.org/systemd/systemd/tree/src/shared/...
I did just check again and realize that the single 'a' at the strndupa means it's using alloca, which is of course similarly unportable and has a whole slew of other problems, all of them intractable (did you pass that pointer to something that will use it later on? stack overflows?).
So hey, not a memory leak! Rejoice! It's just similarly broken.
Yeah, using alloca() (in any form, incl. VLA) isn't good style. At least it's bounded, since filename_is_valid() checks the length. But it uses FILENAME_MAX, which could be too large for the stack.
That's extremely unlikely.
This is definitely not pretty or good quality C code by any standard but let's not start spreading wrong information.
The stack overflowing because you use alloc for something of FILENAME_MAX length is just as likely as a malloc call running out of memory. After all, the heap grows 'up' and the stack grows 'down'. Other than that the mechanisms are roughly (very roughly, ok) identical.
The only time when you have to be extremely careful with alloca is when you use it in functions that might be called in a recursive manner. But then you're playing with fire anyway if you do not have hard upper bounds on the depth of your recursion.
Just because strdupa is not magical, does not mean it has its valid uses. In particular, the problem you allude to (knowing the scope of your memory) is something you would have to get right also if you use heap-allocated memory (unless you just leak everything of course, but I think we have established that that's not something we want to do).
Before jumping to conclusions, please verify what the code really does. C is a complex beast and what's "obvious" may not be such.
Relying on such niceties (as weird as it may seem, to a C programmer those are niceties) is what you gain if you are willing to trade them for portability (strndupa() is a GNU extension).
When the stack frame is unwound when the function returns the allocation is undone.
systemd is explicitly unportable (it uses glibc/gcc/linux-specific features liberally), this is not some sign of sloppy coding, but an explicit design decision as codified in the CODING_STYLE file.
Preventing memory leaks and tracking stack allocated variable assignment are not comparable at all. In the vast majority of cases the tracking of stack allocated variable assignments is entirely trivial. The problem with double freeing is also very hard to run into in practice. Getting a memory-leak when you don't use _cleanup_ is all too common on the other hand. Basically, as soon as there are more than one branch in your function you either have to use ugly goto's or remember to free on every branch, in practice either way you are just implementing the _cleanup_ macros manually all over the place (with all the bugs that implies).
Why don't you point to some code that would have been better without the use of the macros? It seems you think util.c is a god source of examples...