POSIX requires more than the original implementation, and this code
relied on the POSIX behavior. Rely on the intersection of POSIX and
the traditional 4.4BSD behavior. (realpath(3) originated in 4.4BSD.)
Signed-off-by: Greg Troxel <
g...@lexort.com>
---
lib/cmd/bup.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/lib/cmd/bup.c b/lib/cmd/bup.c
index 9cd1f388..43dcacb3 100644
--- a/lib/cmd/bup.c
+++ b/lib/cmd/bup.c
@@ -201,9 +201,18 @@ static char *find_in_path(const char * const name, const char * const path)
return result;
}
+/*
+ * This procedure uses realpath(3). While there is a POSIX
+ * specification that requires accepting a 2nd argument of NULL, the
+ * traditional 4.4BSD implementation (where realpath originated) does
+ * not have this requirement. Therefore, pass in a buffer, and expect
+ * that the return value points to the buffer (and thus, do not free
+ * it).
+ */
static char *find_exe_parent(const char * const argv_0)
{
char *candidate = NULL;
+ char resolvedname[MAXPATHLEN];
const char * const slash = strchr(argv_0, '/');
if (slash) {
candidate = strdup(argv_0);
@@ -215,24 +224,24 @@ static char *find_exe_parent(const char * const argv_0)
argv_0);
char *path_exe = find_in_path(argv_0, env_path);
if (path_exe) {
- char * abs_exe = realpath(path_exe, NULL);
+ char * abs_exe = realpath(path_exe, resolvedname);
if (!abs_exe)
die(2, "cannot resolve path (%s): %s\n",
strerror(errno), path_exe);
- free(path_exe);
- candidate = abs_exe;
+ assert(abs_exe == resolvedname);
+ candidate = strdup(resolvedname);
+ assert(candidate);
}
}
if (!candidate)
return NULL;
- char * const abs_exe = realpath(candidate, NULL);
+ char * const abs_exe = realpath(candidate, resolvedname);
if (!abs_exe)
die(2, "cannot resolve path (%s): %s\n", strerror(errno), candidate);
free(candidate);
char * const abs_parent = strdup(dirname(abs_exe));
assert(abs_parent);
- free(abs_exe);
return abs_parent;
}
--
2.36.1