diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-01-02 15:48:59 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-01-02 15:48:59 +0100 |
commit | 4ddd662b3c206eb6737d78f8c51e687a33db7cfa (patch) | |
tree | 803e2dcf7eee26b979d09cd4710b5c7b9ec4202b | |
parent | aedaf285a0809cdf16f30fd07120b3f24954b6b4 (diff) |
Add faq entry about foo_max
-rw-r--r-- | faq/foo_max.mdwn | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/faq/foo_max.mdwn b/faq/foo_max.mdwn new file mode 100644 index 00000000..14015b9b --- /dev/null +++ b/faq/foo_max.mdwn @@ -0,0 +1,70 @@ +[[!meta copyright="Copyright © 2025 Free Software Foundation, Inc."]] + +[[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable +id="license" text="Permission is granted to copy, distribute and/or modify this +document under the terms of the GNU Free Documentation License, Version 1.2 or +any later version published by the Free Software Foundation; with no Invariant +Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license +is included in the section entitled [[GNU Free Documentation +License|/fdl]]."]]"""]] + +[[!tag faq/general]] + +[[!meta title="Why not just defining `PATH_MAX`, `MAXPATHLEN`, ... `FOO_MAX` and be done?"]] + +More technical details are described in [`PATH_MAX` Is Tricky](https://eklitzke.org/path-max-is-tricky) + +For porting guidelines, see [[hurd/porting/guidelines#PATH_MAX_tt_MAX_PATH_tt_MAXPATHL]] + +# Is it really standard not to define them? + +These macros are indeed optional in Posix, so not defining them remains standard-compliant. + +Their definition was actually not completely clear, Posix 1990 was ambiguous +about it including `\0` or not, it was made clear later on that it does include +it, but some software still add `+1`. Sometimes `PATH_MAX` is even understood as +the filename sections of paths, which is actually `NAME_MAX`, which *is* indeed +limited by filesystems constraints, but then it is filesystem-dependent, and +even depend on its revision, so to be rather queried at runtime with `pathconf`. + +# But it's really convenient! Isn't allocating dynamically much more complex? + +`FOO_MAX` constants are most often used as “reasonable size to allocate a +path”. On Linux it is typically 4096, which is not that reasonable (a whole +memory page, thus a TLB lookup) when manipulating a lot of paths. Allocating +dynamically would use much less memory. + +Most often interfaces can be made to properly allocate dynamically. Notably, +since Posix 2008 `realpath(path, NULL)` and `getcwd(NULL, 0)` allocate the path +dynamically. + +In general, using `FOO_MAX` in source code (with a large value) leads to code +that is not acually checking against overflows. `PATH_MAX` being 4096 is +actually "wrong" on Linux: + + $ printf '#include <limits.h>\nPATH_MAX' | cpp -P + $ d=0123456789; for i in `seq 1 1000`; do mkdir $d; cd $d 2>/dev/null; done + $ pwd | wc -c + +Using such paths lead to various broken software, we could for instance notice: + +* nautilus crashes because of unhandled signal 8, arithmetic exception +* tar can create an archive containing such paths, but cannot untar it +* filelight just ignores the path +* gdb refuses to work + +Using a large `PATH_MAX` value just *hides* these bugs under the +carpet. Attackers will happily try to exploit them. + +# Can't it just be defined to `PTRDIFF_MAX`? + +A lot of programs which blindly use `FOO_MAX` as allocation size would then just +at best either not compile or at worse compile but fail or segfault at execution. + +# These also imply ABI problems + +Exposing a hardcoded limitation like `FOO_MAX` also means hard-defining them +into binaries, making them part of the ABI, and then a hell to change. See for +instance Windows which has been stuck with `MAX_PATH` being 260. Some libraries +(e.g. libusb1) even expose them in their own ABI, thus making the increase a +very nasty flag-day. |