diff options
Diffstat (limited to 'lib/libc/tests/gen/realpath2_test.c')
| -rw-r--r-- | lib/libc/tests/gen/realpath2_test.c | 106 | 
1 files changed, 94 insertions, 12 deletions
| diff --git a/lib/libc/tests/gen/realpath2_test.c b/lib/libc/tests/gen/realpath2_test.c index f89dd99cbb72..431df8721ae0 100644 --- a/lib/libc/tests/gen/realpath2_test.c +++ b/lib/libc/tests/gen/realpath2_test.c @@ -1,6 +1,7 @@  /*   * Copyright (c) 2017 Jan Kokemüller   * All rights reserved. + * Copyright (c) 2025 Klara, Inc.   *   * Redistribution and use in source and binary forms, with or without   * modification, are permitted provided that the following conditions @@ -25,6 +26,8 @@   */  #include <sys/param.h> +#include <sys/stat.h> +  #include <errno.h>  #include <fcntl.h>  #include <stdio.h> @@ -34,6 +37,31 @@  #include <atf-c.h> +ATF_TC(realpath_null); +ATF_TC_HEAD(realpath_null, tc) +{ +	atf_tc_set_md_var(tc, "descr", "Test null input"); +} +ATF_TC_BODY(realpath_null, tc) +{ +	ATF_REQUIRE_ERRNO(EINVAL, realpath(NULL, NULL) == NULL); +} + +ATF_TC(realpath_empty); +ATF_TC_HEAD(realpath_empty, tc) +{ +	atf_tc_set_md_var(tc, "descr", "Test empty input"); +} +ATF_TC_BODY(realpath_empty, tc) +{ +	char resb[PATH_MAX] = ""; + +	ATF_REQUIRE_EQ(0, mkdir("foo", 0755)); +	ATF_REQUIRE_EQ(0, chdir("foo")); +	ATF_REQUIRE_ERRNO(ENOENT, realpath("", resb) == NULL); +	ATF_REQUIRE_STREQ("", resb); +} +  ATF_TC(realpath_buffer_overflow);  ATF_TC_HEAD(realpath_buffer_overflow, tc)  { @@ -44,16 +72,11 @@ ATF_TC_HEAD(realpath_buffer_overflow, tc)  ATF_TC_BODY(realpath_buffer_overflow, tc)  { -	char path[MAXPATHLEN] = { 0 }; -	char resb[MAXPATHLEN] = { 0 }; -	size_t i; +	char path[PATH_MAX] = ""; +	char resb[PATH_MAX] = ""; -	path[0] = 'a'; +	memset(path, 'a', sizeof(path) - 1);  	path[1] = '/'; -	for (i = 2; i < sizeof(path) - 1; ++i) { -		path[i] = 'a'; -	} -  	ATF_REQUIRE(realpath(path, resb) == NULL);  } @@ -66,9 +89,9 @@ ATF_TC_HEAD(realpath_empty_symlink, tc)  ATF_TC_BODY(realpath_empty_symlink, tc)  { -	char path[MAXPATHLEN] = { 0 }; -	char slnk[MAXPATHLEN] = { 0 }; -	char resb[MAXPATHLEN] = { 0 }; +	char path[PATH_MAX] = ""; +	char slnk[PATH_MAX] = ""; +	char resb[PATH_MAX] = "";  	int fd;  	(void)strlcat(slnk, "empty_symlink", sizeof(slnk)); @@ -89,11 +112,70 @@ ATF_TC_BODY(realpath_empty_symlink, tc)  	ATF_REQUIRE(unlink(slnk) == 0);  } -ATF_TP_ADD_TCS(tp) +ATF_TC(realpath_partial); +ATF_TC_HEAD(realpath_partial, tc) +{ +	atf_tc_set_md_var(tc, "descr", +	    "Test that failure leaves a partial result"); +	atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} + +ATF_TC_BODY(realpath_partial, tc)  { +	char resb[PATH_MAX] = ""; +	size_t len; + +	/* scenario 1: missing directory */ +	ATF_REQUIRE_EQ(0, mkdir("foo", 0755)); +	ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL); +	len = strnlen(resb, sizeof(resb)); +	ATF_REQUIRE(len > 8 && len < sizeof(resb)); +	ATF_REQUIRE_STREQ("/foo/bar", resb + len - 8); + +	/* scenario 2: dead link 1 */ +	ATF_REQUIRE_EQ(0, symlink("nix", "foo/bar")); +	ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL); +	len = strnlen(resb, sizeof(resb)); +	ATF_REQUIRE(len > 8 && len < sizeof(resb)); +	ATF_REQUIRE_STREQ("/foo/nix", resb + len - 8); + +	/* scenario 3: missing file */ +	ATF_REQUIRE_EQ(0, unlink("foo/bar")); +	ATF_REQUIRE_EQ(0, mkdir("foo/bar", 0755)); +	ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL); +	len = strnlen(resb, sizeof(resb)); +	ATF_REQUIRE(len > 12 && len < sizeof(resb)); +	ATF_REQUIRE_STREQ("/foo/bar/baz", resb + len - 12); + +	/* scenario 4: dead link 2 */ +	ATF_REQUIRE_EQ(0, symlink("nix", "foo/bar/baz")); +	ATF_REQUIRE_ERRNO(ENOENT, realpath("foo/bar/baz", resb) == NULL); +	len = strnlen(resb, sizeof(resb)); +	ATF_REQUIRE(len > 12 && len < sizeof(resb)); +	ATF_REQUIRE_STREQ("/foo/bar/nix", resb + len - 12); + +	/* scenario 5: unreadable directory */ +	ATF_REQUIRE_EQ(0, chmod("foo", 000)); +	ATF_REQUIRE_ERRNO(EACCES, realpath("foo/bar/baz", resb) == NULL); +	len = strnlen(resb, sizeof(resb)); +	ATF_REQUIRE(len > 4 && len < sizeof(resb)); +	ATF_REQUIRE_STREQ("/foo", resb + len - 4); + +	/* scenario 6: not a directory */ +	ATF_REQUIRE_EQ(0, close(creat("bar", 0644))); +	ATF_REQUIRE_ERRNO(ENOTDIR, realpath("bar/baz", resb) == NULL); +	len = strnlen(resb, sizeof(resb)); +	ATF_REQUIRE(len > 4 && len < sizeof(resb)); +	ATF_REQUIRE_STREQ("/bar", resb + len - 4); +} +ATF_TP_ADD_TCS(tp) +{ +	ATF_TP_ADD_TC(tp, realpath_null); +	ATF_TP_ADD_TC(tp, realpath_empty);  	ATF_TP_ADD_TC(tp, realpath_buffer_overflow);  	ATF_TP_ADD_TC(tp, realpath_empty_symlink); +	ATF_TP_ADD_TC(tp, realpath_partial);  	return atf_no_error();  } | 
