git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: free and errno, was Re: [PATCH] apply: replace mksnpath() with a mkpathdup() call

From
René Scharfe <l.s.r@web.de>
Date
Apr 5, 2024, 10:52 UTC
Message-ID
<14c99998-cc4a-4581-aab3-607d7fac7edb@web.de>
In-Reply-To
<20240404225313.GA2512966@coredump.intra.peff.net>
Am 05.04.24 um 00:53 schrieb Jeff King:
Show 31 quoted lines
> On Thu, Apr 04, 2024 at 11:08:38PM +0200, René Scharfe wrote:
>
>> Support paths longer than PATH_MAX in create_one_file() (which is not a
>> hard limit e.g. on Linux) by calling mkpathdup() instead of mksnpath().
>> Remove the latter, as it becomes unused by this change.  Resist the
>> temptation of using the more convenient mkpath() to avoid introducing a
>> dependency on a static variable deep inside the apply machinery.
>>
>> Suggested-by: Jeff King <peff@peff.net>
>> Signed-off-by: René Scharfe <l.s.r@web.de>
>
> Heh, so obviously I had the same patch stewing. But one thing that gave
> me pause is: do we need to worry about preserving errno across free()
> boundaries?
>
> Traditionally touching errno was something free() was allowed to do, and
> there were definitely cases where glibc would do so (mostly due to
> munmap). But recent versions of POSIX clarify that it should not touch
> errno, and glibc as of 2.33 does not (which dates to 2021).
>
> This issue from 2015 talks about "the next version of POSIX" making that
> change:
>
>   https://sourceware.org/bugzilla/show_bug.cgi?id=17924
>
> but it looks to me from:
>
>   https://www.austingroupbugs.net/view.php?id=385
>
> that the change wasn't accepted there until 2020 (and AFAICT that hasn't
> resulted in a new published spec yet).

Horrible. OS implementation details peeking through an API that has no return value and no defined errors is outright Lovecraftian.

> Now it would be pretty darn useful to not have to worry about preserving
> errno. It's subtle code that's hard to remember is needed, and sometimes
> hard to get right depending on the rest of the flow control.
Yes.
Show 37 quoted lines
> Years like "2020" and "2021" are too recent for us to say "oh, that's
> ancient history, we don't have to care anymore". But I wonder if we can
> be a little cavalier here for two reasons:
>
>   - it's rare; for the most part free() isn't going to touch errno.
>     Failures from munmap() are pretty rare, and small allocations like
>     this are probably done with sbrk() anyway. Of course that's just
>     talking about glibc, and there are other platforms. But it still
>     seems like it should be a rarity for any free() implementation to
>     fail or to want to touch errno.
>
>   - the stakes are usually pretty low; the outcome in most cases would
>     be a misleading error message as we clobber errno. But note that it
>     does sometimes affect control flow (this patch is an example; we are
>     checking for EEXIST to break out of the loop).
>
> So would it be that unreasonable to assume the modern, desired behavior,
> and mostly shrug our shoulders for other platforms? We could even
> provide:
>
>   #ifdef FREE_CLOBBERS_ERRNO
>   void git_free(void *ptr)
>   {
>         int saved_errno = errno;
>         free(ptr);
>         errno = saved_errno;
>   }
>   #define free(ptr) git_free(ptr)
>   #endif
>
> if we really wanted to be careful, though it's hard to know which
> platforms even need it (and again, it's so rare to come up in practice
> that I'd suspect people could go for a long time before realizing their
> platform was a problem). I guess the flip side is that we could use the
> function above by default, and disable it selectively (the advantage of
> disabling it being that it's slightly more efficient; maybe that's not
> even measurable?).

I think performing this ritual automatically every time on all platforms (i.e. to use git_free() unconditionally) to provide sane errno values around free(3) calls is better than having to worry about attacks from the deep. But then again I'm easily scared and still a bit in shock, so perhaps I'm overreacting.

René
Previous: Junio C HamanoNext: Jeff King
Message 5 of 15 in “apply: replace mksnpath() with a mkpathdup() call”
  1. apply: replace mksnpath() with a mkpathdup() callRené Scharfe, Apr 4, 2024
  2. Junio C HamanoApr 4, 2024
  3. free and errno, was Re: [PATCH] apply: replace mksnpath() with a mkpathdup() callJeff King, Apr 4, 2024
  4. Junio C HamanoApr 4, 2024
  5. René ScharfeApr 5, 2024
  6. Jeff KingApr 5, 2024
  7. Jeff KingApr 5, 2024
  8. René ScharfeApr 6, 2024
  9. Jeff KingApr 7, 2024
  10. René ScharfeApr 14, 2024
  11. Jeff KingApr 24, 2024
  12. 1/2 apply: avoid fixed-size buffer in create_one_file()René Scharfe, Apr 5, 2024
  13. 2/2 path: remove mksnpath()René Scharfe, Apr 5, 2024
  14. Jeff KingApr 5, 2024
  15. Junio C HamanoApr 5, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.