summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvoisin2026-04-01 20:37:02 +0200
committerjvoisin2026-04-01 20:37:02 +0200
commit60c096eb0433f7573c768a2c8523abd3c11e0720 (patch)
treec9ff95ee202cabad323855cb6a9dc72c1778e060
parentb35761a1a8378e068fead72f828f2400a20682a8 (diff)
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.
-rw-r--r--include/stdlib.h6
-rw-r--r--tests/Makefile2
-rw-r--r--tests/test_realpath.c11
-rw-r--r--tests/test_realpath_null.c11
4 files changed, 27 insertions, 3 deletions
diff --git a/include/stdlib.h b/include/stdlib.h
index 0336d56..c95bb55 100644
--- 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
43_FORTIFY_FN(realpath) char *realpath(const char *__p, char *__r) 43_FORTIFY_FN(realpath) char *realpath(const char *__p, char *__r)
44{ 44{
45#ifndef PATH_MAX 45#ifndef PATH_MAX
46#error PATH_MAX unset. A fortified realpath will not work. 46/* see man realpath(3) */
47#else 47#define PATH_MAX 4096
48#endif
48 if (__r && PATH_MAX > __bos(__r, 2)) { 49 if (__r && PATH_MAX > __bos(__r, 2)) {
49 char __buf[PATH_MAX], *__ret; 50 char __buf[PATH_MAX], *__ret;
50 size_t __l; 51 size_t __l;
@@ -59,7 +60,6 @@ _FORTIFY_FN(realpath) char *realpath(const char *__p, char *__r)
59 return __r; 60 return __r;
60 } 61 }
61 return __orig_realpath(__p, __r); 62 return __orig_realpath(__p, __r);
62#endif
63} 63}
64#endif 64#endif
65 65
diff --git a/tests/Makefile b/tests/Makefile
index 81f7f6e..9c2dede 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -61,6 +61,8 @@ RUNTIME_TARGETS= \
61 test_read_static \ 61 test_read_static \
62 test_readlink_dynamic \ 62 test_readlink_dynamic \
63 test_readlink_static \ 63 test_readlink_static \
64 test_realpath_null \
65 test_realpath \
64 test_recv_dynamic \ 66 test_recv_dynamic \
65 test_recv_static \ 67 test_recv_static \
66 test_recvfrom_dynamic \ 68 test_recvfrom_dynamic \
diff --git a/tests/test_realpath.c b/tests/test_realpath.c
new file mode 100644
index 0000000..2a17708
--- /dev/null
+++ b/tests/test_realpath.c
@@ -0,0 +1,11 @@
1#include "common.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5
6int main(int argc, char** argv) {
7 char buf[PATH_MAX];
8 char* rpath = realpath("/root/../", buf);
9 printf("%s\n", rpath);
10 return 0;
11}
diff --git a/tests/test_realpath_null.c b/tests/test_realpath_null.c
new file mode 100644
index 0000000..b62cee8
--- /dev/null
+++ b/tests/test_realpath_null.c
@@ -0,0 +1,11 @@
1#include "common.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5
6int main(int argc, char** argv) {
7 char* rpath = realpath("/root/../", NULL);
8 printf("%s\n", rpath);
9 free(rpath);
10 return 0;
11}