From 42c54ff9d5e8733ec76f53b52ce2a7cbd6870763 Mon Sep 17 00:00:00 2001 From: Fred Wright <fw@fwright.net> Date: Thu, 7 Nov 2024 17:27:22 -0800 Subject: [PATCH] test_realpath: Add nonexistent path case. Although more thorough testing of various path cases would be useful, this one, which just tests a simple nonexistent relative path, is sufficient to demonstrate a bug in the 10.6 non-POSIX realpath(), which returns "success" via an unsafe pointer to an internal buffer. TESTED: Fails in known bad case without the fix; passes in all cases with the fix. --- test/test_realpath.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/test_realpath.c b/test/test_realpath.c index ec890dc..cf14745 100644 --- a/test/test_realpath.c +++ b/test/test_realpath.c @@ -37,6 +37,7 @@ typedef struct { strfunc_t realpath; } rpf_t; #include <assert.h> #include <libgen.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -44,6 +45,17 @@ typedef struct { strfunc_t realpath; } rpf_t; #include <sys/param.h> +/* + * Beginning in the 15.x SDK, including malloc.h doesn't work when + * _POSIX_C_SOURCE is defined, which we need for the "nonext" version. + * So we avoid the official include and declare malloc_size() directly. + * + * #include <malloc/malloc.h> + */ +extern size_t malloc_size(const void *ptr); + +#define NONEX_PATH "4981a2d5a4c7bea88154c434b4708045" + /* * Allow testing the legacy compatibility entry. * We use a simple argless macro and disable the fancier tests. @@ -85,6 +97,20 @@ main(int argc, char *argv[]) if (verbose) printf("realpath(path, NULL) supported.\n"); free((void*)q); + /* + * Test nonexistent path with no supplied buffer. + * In some cases (10.6 non-POSIX) this may "succeed" with a bad + * returned buffer address. We accept either failure or success + * with a valid buffer. + */ + q = realpath(NONEX_PATH, NULL); + assert((!q || malloc_size(q)) \ + && "realpath(_nonexpath, NULL) returned bad address"); + if (verbose) { + printf("realpath(nonex_path, NULL) %s.\n", q ? "succeeds" : "fails"); + } + if (q && malloc_size(q)) free((void*)q); + #ifndef TEST_MACPORTS_LEGACY_REALPATH /* Test with name (reference) only */ f = realpath; -- GitLab