1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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 actually 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.
|