fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers
Log | Files | Refs | README | LICENSE

commit 60c096eb0433f7573c768a2c8523abd3c11e0720
parent b35761a1a8378e068fead72f828f2400a20682a8
Author: jvoisin <julien.voisin@dustri.org>
Date:   Wed,  1 Apr 2026 20:37:02 +0200

Make do even if PATH_MAX isn't defined

As explained in `man realpath(3)`:

> The POSIX.1-2001 standard version of this function is broken by design,
> since it is impossible  to determine  a  suitable  size  for  the  output
> buffer, resolved_path.  According to POSIX.1-2001 a buffer of size PATH_MAX
> suffices, but PATH_MAX need not be a defined constant, and may have to  be
> obtained  using  pathconf(3).  And asking pathconf(3) does not really help,
> since, on the one hand POSIX warns that the result of pathconf(3) may be huge
> and unsuitable for mallocing memory, and on the other hand pathconf(3) may
> return -1 to  signify  that  PATH_MAX  is  not  bounded.   The  re‐ solved_path
> == NULL  feature,  not standardized in POSIX.1-2001, but standardized in
> POSIX.1-2008, allows this design problem to be avoided.

So we can either not compile, or be pragmatic, and define PATH_MAX to a sane
value, like 4096, which is the one used on Linux and some/most BSD.

This commit also adds two tests to ensure that things aren't catastrophically
broken by this change.

Diffstat:
Minclude/stdlib.h | 6+++---
Mtests/Makefile | 2++
Atests/test_realpath.c | 11+++++++++++
Atests/test_realpath_null.c | 11+++++++++++
4 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/include/stdlib.h b/include/stdlib.h @@ -43,8 +43,9 @@ __fortify_warning_if(__p == NULL, "'realpath' called with path set to `NULL`; di _FORTIFY_FN(realpath) char *realpath(const char *__p, char *__r) { #ifndef PATH_MAX -#error PATH_MAX unset. A fortified realpath will not work. -#else +/* see man realpath(3) */ +#define PATH_MAX 4096 +#endif if (__r && PATH_MAX > __bos(__r, 2)) { char __buf[PATH_MAX], *__ret; size_t __l; @@ -59,7 +60,6 @@ _FORTIFY_FN(realpath) char *realpath(const char *__p, char *__r) return __r; } return __orig_realpath(__p, __r); -#endif } #endif diff --git a/tests/Makefile b/tests/Makefile @@ -61,6 +61,8 @@ RUNTIME_TARGETS= \ test_read_static \ test_readlink_dynamic \ test_readlink_static \ + test_realpath_null \ + test_realpath \ test_recv_dynamic \ test_recv_static \ test_recvfrom_dynamic \ diff --git a/tests/test_realpath.c b/tests/test_realpath.c @@ -0,0 +1,11 @@ +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> + +int main(int argc, char** argv) { + char buf[PATH_MAX]; + char* rpath = realpath("/root/../", buf); + printf("%s\n", rpath); + return 0; +} diff --git a/tests/test_realpath_null.c b/tests/test_realpath_null.c @@ -0,0 +1,11 @@ +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> + +int main(int argc, char** argv) { + char* rpath = realpath("/root/../", NULL); + printf("%s\n", rpath); + free(rpath); + return 0; +}