mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-11 04:42:16 +01:00
install: Simplify path construction.
There's no need to copy the path twice to split it into base and dir. We simply call `basename()` first, then handle the two trivial cases in which it isn't safe to call `dirname()`. While here, add an early check that the destination is not an empty string. This would always fail eventually, so it may as well fail right away. Also add a test case for this shortcut. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D44743
This commit is contained in:
parent
e5035d0857
commit
17dc7017d7
@ -25,6 +25,13 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
atf_test_case copy_to_empty
|
||||||
|
copy_to_empty_body() {
|
||||||
|
printf 'test\n123\r456\r\n789\0z' >testf
|
||||||
|
atf_check -s not-exit:0 -e match:"empty string" \
|
||||||
|
install testf ""
|
||||||
|
}
|
||||||
|
|
||||||
copy_to_nonexistent_with_opts() {
|
copy_to_nonexistent_with_opts() {
|
||||||
printf 'test\n123\r456\r\n789\0z' >testf
|
printf 'test\n123\r456\r\n789\0z' >testf
|
||||||
atf_check install "$@" testf copyf
|
atf_check install "$@" testf copyf
|
||||||
@ -497,6 +504,7 @@ set_optional_exec_body()
|
|||||||
}
|
}
|
||||||
|
|
||||||
atf_init_test_cases() {
|
atf_init_test_cases() {
|
||||||
|
atf_add_test_case copy_to_empty
|
||||||
atf_add_test_case copy_to_nonexistent
|
atf_add_test_case copy_to_nonexistent
|
||||||
atf_add_test_case copy_to_nonexistent_safe
|
atf_add_test_case copy_to_nonexistent_safe
|
||||||
atf_add_test_case copy_to_nonexistent_comparing
|
atf_add_test_case copy_to_nonexistent_comparing
|
||||||
|
@ -657,8 +657,10 @@ static void
|
|||||||
makelink(const char *from_name, const char *to_name,
|
makelink(const char *from_name, const char *to_name,
|
||||||
const struct stat *target_sb)
|
const struct stat *target_sb)
|
||||||
{
|
{
|
||||||
char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
|
char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN];
|
||||||
struct stat to_sb;
|
char *to_name_copy, *d, *ld, *ls, *s;
|
||||||
|
const char *base, *dir;
|
||||||
|
struct stat to_sb;
|
||||||
|
|
||||||
/* Try hard links first. */
|
/* Try hard links first. */
|
||||||
if (dolink & (LN_HARD|LN_MIXED)) {
|
if (dolink & (LN_HARD|LN_MIXED)) {
|
||||||
@ -719,8 +721,6 @@ makelink(const char *from_name, const char *to_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dolink & LN_RELATIVE) {
|
if (dolink & LN_RELATIVE) {
|
||||||
char *to_name_copy, *cp, *d, *ld, *ls, *s;
|
|
||||||
|
|
||||||
if (*from_name != '/') {
|
if (*from_name != '/') {
|
||||||
/* this is already a relative link */
|
/* this is already a relative link */
|
||||||
do_symlink(from_name, to_name, target_sb);
|
do_symlink(from_name, to_name, target_sb);
|
||||||
@ -740,17 +740,23 @@ makelink(const char *from_name, const char *to_name,
|
|||||||
to_name_copy = strdup(to_name);
|
to_name_copy = strdup(to_name);
|
||||||
if (to_name_copy == NULL)
|
if (to_name_copy == NULL)
|
||||||
err(EX_OSERR, "%s: strdup", to_name);
|
err(EX_OSERR, "%s: strdup", to_name);
|
||||||
cp = dirname(to_name_copy);
|
base = basename(to_name_copy);
|
||||||
if (realpath(cp, dst) == NULL)
|
if (base == to_name_copy) {
|
||||||
err(EX_OSERR, "%s: realpath", cp);
|
/* destination is a file in cwd */
|
||||||
/* .. and add the last component. */
|
(void)strlcpy(dst, "./", sizeof(dst));
|
||||||
if (strcmp(dst, "/") != 0) {
|
} else if (base == to_name_copy + 1) {
|
||||||
if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst))
|
/* destination is a file in the root */
|
||||||
|
(void)strlcpy(dst, "/", sizeof(dst));
|
||||||
|
} else {
|
||||||
|
/* all other cases: safe to call dirname() */
|
||||||
|
dir = dirname(to_name_copy);
|
||||||
|
if (realpath(dir, dst) == NULL)
|
||||||
|
err(EX_OSERR, "%s: realpath", dir);
|
||||||
|
if (strcmp(dst, "/") != 0 &&
|
||||||
|
strlcat(dst, "/", sizeof(dst)) > sizeof(dst))
|
||||||
errx(1, "resolved pathname too long");
|
errx(1, "resolved pathname too long");
|
||||||
}
|
}
|
||||||
strcpy(to_name_copy, to_name);
|
if (strlcat(dst, base, sizeof(dst)) > sizeof(dst))
|
||||||
cp = basename(to_name_copy);
|
|
||||||
if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst))
|
|
||||||
errx(1, "resolved pathname too long");
|
errx(1, "resolved pathname too long");
|
||||||
free(to_name_copy);
|
free(to_name_copy);
|
||||||
|
|
||||||
@ -834,6 +840,8 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags)
|
|||||||
} else {
|
} else {
|
||||||
devnull = 1;
|
devnull = 1;
|
||||||
}
|
}
|
||||||
|
if (*to_name == '\0')
|
||||||
|
errx(EX_USAGE, "destination cannot be an empty string");
|
||||||
|
|
||||||
target = (lstat(to_name, &to_sb) == 0);
|
target = (lstat(to_name, &to_sb) == 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user