From nobody Wed Jul 02 10:23:03 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bXGF41bdrz60DCC; Wed, 02 Jul 2025 10:23:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bXGF362tWz3KdB; Wed, 02 Jul 2025 10:23:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1751451783; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Kb4g0S4eQvUzvGC3zItcsMzq9gPmC4EpCm4h9ZHVgyA=; b=jF/Kx1CTGf924ooQLLs585DGqxEUoHHlbLQPrRBWx4nGBhk4vX7siYgSv3M6WeIikeOPr1 F1iYUI1eHnbrR0zUHpUyudrzvkp4FK/q4BS4zisQB5eJGCYIsf4RM37SjJp1Mn6QThUh0B dkbMjcg7vvX0TgXzCT0z7T9RZpqf4YNKep+/KJ38iDsvtWobeAVKBqO64GZ9TPtNL/yylU QUjOGDVQ06Nzt8SwiW0nGsz4omnqdhysokYBhwzwjNtkwF9lrvk04Kuo46gxvYHcynAda9 T+y/kXpB5fyNw9E/WlGZ2awTFqHpGLgBvQ/H8zfIEapAyMtkiuzgc7ONS1ZZfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1751451783; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Kb4g0S4eQvUzvGC3zItcsMzq9gPmC4EpCm4h9ZHVgyA=; b=WNeUcvWwSwH6LPYpPaWZbNfP0XBj2p//AKxNHN64YI8fiTpz3rS+mS/++RR+ma6R61FHkF eYZAY/Ulh4D1JultcYTKUxHqxULK3kEobS+1TYvrL2iPD6jGTb0NsH3aizCY5XGhG5u9VU jHu41PVNpcKHm0AgPcLkZlTtif1adppCnIHlzExc/CH3+89uo9CsPf7r54MPxCQ7scjZRU hGKyR/uHyy+v8LfsUx5nMT97AvgJ6P/hS7hhX5RRuJARcuJ4dQ6SWZ9YlaLU2aMZ3jR4m9 BPPuzKZMIIzNADoA6tiIqL9chbyDn4Zrjgh8WQ7Ame3lCYM2xnf8A/TCjUTNzw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1751451783; a=rsa-sha256; cv=none; b=q7upgo1jWuZpjuHA5aDXxld95RrkRpa3Q/NVOgFlti6+6cc3ac7tb8afTmGnVsbs7/VgB7 +VplUWV/6X8MBCKb22A1rFZbBBeVpLdUzKhociHmgrN4+jBGBZn16N3+obQByehvtQeMG7 0P00FXB+/zLDAhC/+tGQmG9sT/C6fWuim68qLy7nuOrOTRHlVM+jpuGF1q4ZDAvPa76DsN wpxyQ7LoeWnfk42r+7w9xwhsa8/9FmwAYjXT8JCqhKaRCFYW6wKw1UoiKHTkeIhFI0Fcp7 aCLlhRCuj0Fa+jnGd7Pw5XeNaur8Kt0DrK/KYC0eXOt9YNkTATtscKqZ/TeMDw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bXGF35L2qz1HF; Wed, 02 Jul 2025 10:23:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 562AN3bo050165; Wed, 2 Jul 2025 10:23:03 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 562AN3rQ050162; Wed, 2 Jul 2025 10:23:03 GMT (envelope-from git) Date: Wed, 2 Jul 2025 10:23:03 GMT Message-Id: <202507021023.562AN3rQ050162@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 8d02b7190d3b - main - fts: Add test cases for unreadable directories. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 8d02b7190d3b926118fafc6a70a80676c349e186 Auto-Submitted: auto-generated The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=8d02b7190d3b926118fafc6a70a80676c349e186 commit 8d02b7190d3b926118fafc6a70a80676c349e186 Author: Dag-Erling Smørgrav AuthorDate: 2025-07-02 10:22:16 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-07-02 10:22:29 +0000 fts: Add test cases for unreadable directories. Sponsored by: Klara, Inc. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D51098 --- lib/libc/tests/gen/Makefile | 9 ++++ lib/libc/tests/gen/fts_misc_test.c | 78 ++++++++++++++++++++++++++++++++ lib/libc/tests/gen/fts_options_test.c | 84 +++++------------------------------ lib/libc/tests/gen/fts_test.h | 81 +++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 72 deletions(-) diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile index b7df4b1d037b..a967ad5ddf91 100644 --- a/lib/libc/tests/gen/Makefile +++ b/lib/libc/tests/gen/Makefile @@ -10,6 +10,7 @@ ATF_TESTS_C+= fpclassify2_test .if ${COMPILER_FEATURES:Mblocks} ATF_TESTS_C+= fts_blocks_test .endif +ATF_TESTS_C+= fts_misc_test ATF_TESTS_C+= fts_options_test ATF_TESTS_C+= ftw_test ATF_TESTS_C+= getentropy_test @@ -104,6 +105,14 @@ TEST_METADATA.setdomainname_test+= is_exclusive=true TESTS_SUBDIRS= execve TESTS_SUBDIRS+= posix_spawn +# Tests that require address sanitizer +.if ${COMPILER_FEATURES:Masan} +.for t in scandir_test realpath2_test +CFLAGS.${t}.c+= -fsanitize=address +LDFLAGS.${t}+= -fsanitize=address +.endfor +.endif + # Tests that require blocks support .for t in fts_blocks_test glob_blocks_test scandir_blocks_test CFLAGS.${t}.c+= -fblocks diff --git a/lib/libc/tests/gen/fts_misc_test.c b/lib/libc/tests/gen/fts_misc_test.c new file mode 100644 index 000000000000..91640078f63c --- /dev/null +++ b/lib/libc/tests/gen/fts_misc_test.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "fts_test.h" + +ATF_TC(fts_unrdir); +ATF_TC_HEAD(fts_unrdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "unreadable directories"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(fts_unrdir, tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/unr", 0100)); + ATF_REQUIRE_EQ(0, mkdir("dir/unx", 0400)); + fts_test(tc, &(struct fts_testcase){ + (char *[]){ "dir", NULL }, + FTS_PHYSICAL, + (struct fts_expect[]){ + { FTS_D, "dir", "dir" }, + { FTS_D, "unr", "unr" }, + { FTS_DNR, "unr", "unr" }, + { FTS_D, "unx", "unx" }, + { FTS_DP, "unx", "unx" }, + { FTS_DP, "dir", "dir" }, + { 0 } + }, + }); +} + +ATF_TC(fts_unrdir_nochdir); +ATF_TC_HEAD(fts_unrdir_nochdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "unreadable directories (nochdir)"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(fts_unrdir_nochdir, tc) +{ + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE_EQ(0, mkdir("dir/unr", 0100)); + ATF_REQUIRE_EQ(0, mkdir("dir/unx", 0400)); + fts_test(tc, &(struct fts_testcase){ + (char *[]){ "dir", NULL }, + FTS_PHYSICAL | FTS_NOCHDIR, + (struct fts_expect[]){ + { FTS_D, "dir", "dir" }, + { FTS_D, "unr", "dir/unr" }, + { FTS_DNR, "unr", "dir/unr" }, + { FTS_D, "unx", "dir/unx" }, + { FTS_DP, "unx", "dir/unx" }, + { FTS_DP, "dir", "dir" }, + { 0 } + }, + }); +} + +ATF_TP_ADD_TCS(tp) +{ + fts_check_debug(); + ATF_TP_ADD_TC(tp, fts_unrdir); + ATF_TP_ADD_TC(tp, fts_unrdir_nochdir); + return (atf_no_error()); +} diff --git a/lib/libc/tests/gen/fts_options_test.c b/lib/libc/tests/gen/fts_options_test.c index c80474b70ac7..fc3015138a49 100644 --- a/lib/libc/tests/gen/fts_options_test.c +++ b/lib/libc/tests/gen/fts_options_test.c @@ -15,17 +15,7 @@ #include -struct fts_expect { - int fts_info; - const char *fts_name; - const char *fts_accpath; -}; - -struct fts_testcase { - char **paths; - int fts_options; - struct fts_expect *fts_expect; -}; +#include "fts_test.h" static char *all_paths[] = { "dir", @@ -37,20 +27,12 @@ static char *all_paths[] = { NULL }; -/* shorter name for dead links */ -#define FTS_DL FTS_SLNONE - -/* are we being debugged? */ -static bool debug; - /* * Prepare the files and directories we will be inspecting. */ static void fts_options_prepare(const struct atf_tc *tc) { - debug = !getenv("__RUNNING_INSIDE_ATF_RUN") && - isatty(STDERR_FILENO); ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); ATF_REQUIRE_EQ(0, close(creat("file", 0644))); ATF_REQUIRE_EQ(0, close(creat("dir/file", 0644))); @@ -60,49 +42,6 @@ fts_options_prepare(const struct atf_tc *tc) ATF_REQUIRE_EQ(0, symlink("noent", "dead")); } -/* - * Lexical order for reproducability. - */ -static int -fts_options_compar(const FTSENT * const *a, const FTSENT * const *b) -{ - return (strcmp((*a)->fts_name, (*b)->fts_name)); -} - -/* - * Run FTS with the specified paths and options and verify that it - * produces the expected result in the correct order. - */ -static void -fts_options_test(const struct atf_tc *tc, const struct fts_testcase *fts_tc) -{ - FTS *fts; - FTSENT *ftse; - const struct fts_expect *expect = fts_tc->fts_expect; - long level = 0; - - fts = fts_open(fts_tc->paths, fts_tc->fts_options, fts_options_compar); - ATF_REQUIRE_MSG(fts != NULL, "fts_open(): %m"); - while ((ftse = fts_read(fts)) != NULL && expect->fts_name != NULL) { - if (expect->fts_info == FTS_DP) - level--; - if (debug) { - fprintf(stderr, "%2ld %2d %s\n", level, - ftse->fts_info, ftse->fts_name); - } - ATF_CHECK_STREQ(expect->fts_name, ftse->fts_name); - ATF_CHECK_STREQ(expect->fts_accpath, ftse->fts_accpath); - ATF_CHECK_INTEQ(expect->fts_info, ftse->fts_info); - ATF_CHECK_INTEQ(level, ftse->fts_level); - if (expect->fts_info == FTS_D) - level++; - expect++; - } - ATF_CHECK_EQ(NULL, ftse); - ATF_CHECK_EQ(NULL, expect->fts_name); - ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m"); -} - ATF_TC(fts_options_logical); ATF_TC_HEAD(fts_options_logical, tc) { @@ -111,7 +50,7 @@ ATF_TC_HEAD(fts_options_logical, tc) ATF_TC_BODY(fts_options_logical, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_LOGICAL, (struct fts_expect[]){ @@ -162,7 +101,7 @@ ATF_TC_BODY(fts_options_logical_nostat, tc) */ atf_tc_expect_fail("FTS_LOGICAL nullifies FTS_NOSTAT"); fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_LOGICAL | FTS_NOSTAT, (struct fts_expect[]){ @@ -203,7 +142,7 @@ ATF_TC_HEAD(fts_options_logical_seedot, tc) ATF_TC_BODY(fts_options_logical_seedot, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_LOGICAL | FTS_SEEDOT, (struct fts_expect[]){ @@ -252,7 +191,7 @@ ATF_TC_HEAD(fts_options_physical, tc) ATF_TC_BODY(fts_options_physical, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL, (struct fts_expect[]){ @@ -278,7 +217,7 @@ ATF_TC_HEAD(fts_options_physical_nochdir, tc) ATF_TC_BODY(fts_options_physical_nochdir, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL | FTS_NOCHDIR, (struct fts_expect[]){ @@ -304,7 +243,7 @@ ATF_TC_HEAD(fts_options_physical_comfollow, tc) ATF_TC_BODY(fts_options_physical_comfollow, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL | FTS_COMFOLLOW, (struct fts_expect[]){ @@ -333,7 +272,7 @@ ATF_TC_HEAD(fts_options_physical_comfollowdir, tc) ATF_TC_BODY(fts_options_physical_comfollowdir, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL | FTS_COMFOLLOWDIR, (struct fts_expect[]){ @@ -362,7 +301,7 @@ ATF_TC_HEAD(fts_options_physical_nostat, tc) ATF_TC_BODY(fts_options_physical_nostat, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL | FTS_NOSTAT, (struct fts_expect[]){ @@ -388,7 +327,7 @@ ATF_TC_HEAD(fts_options_physical_nostat_type, tc) ATF_TC_BODY(fts_options_physical_nostat_type, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL | FTS_NOSTAT_TYPE, (struct fts_expect[]){ @@ -414,7 +353,7 @@ ATF_TC_HEAD(fts_options_physical_seedot, tc) ATF_TC_BODY(fts_options_physical_seedot, tc) { fts_options_prepare(tc); - fts_options_test(tc, &(struct fts_testcase){ + fts_test(tc, &(struct fts_testcase){ all_paths, FTS_PHYSICAL | FTS_SEEDOT, (struct fts_expect[]){ @@ -440,6 +379,7 @@ ATF_TC_BODY(fts_options_physical_seedot, tc) ATF_TP_ADD_TCS(tp) { + fts_check_debug(); ATF_TP_ADD_TC(tp, fts_options_logical); ATF_TP_ADD_TC(tp, fts_options_logical_nostat); ATF_TP_ADD_TC(tp, fts_options_logical_seedot); diff --git a/lib/libc/tests/gen/fts_test.h b/lib/libc/tests/gen/fts_test.h new file mode 100644 index 000000000000..b3f15050f265 --- /dev/null +++ b/lib/libc/tests/gen/fts_test.h @@ -0,0 +1,81 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef FTS_TEST_H_INCLUDED +#define FTS_TEST_H_INCLUDED + +struct fts_expect { + int fts_info; + const char *fts_name; + const char *fts_accpath; +}; + +struct fts_testcase { + char **paths; + int fts_options; + struct fts_expect *fts_expect; +}; + +/* shorter name for dead links */ +#define FTS_DL FTS_SLNONE + +/* are we being debugged? */ +static bool fts_test_debug; + +/* + * Set debug flag if appropriate. + */ +static void +fts_check_debug(void) +{ + fts_test_debug = !getenv("__RUNNING_INSIDE_ATF_RUN") && + isatty(STDERR_FILENO); +} + +/* + * Lexical order for reproducability. + */ +static int +fts_lexical_compar(const FTSENT * const *a, const FTSENT * const *b) +{ + return (strcmp((*a)->fts_name, (*b)->fts_name)); +} + +/* + * Run FTS with the specified paths and options and verify that it + * produces the expected result in the correct order. + */ +static void +fts_test(const struct atf_tc *tc, const struct fts_testcase *fts_tc) +{ + FTS *fts; + FTSENT *ftse; + const struct fts_expect *expect = fts_tc->fts_expect; + long level = 0; + + fts = fts_open(fts_tc->paths, fts_tc->fts_options, fts_lexical_compar); + ATF_REQUIRE_MSG(fts != NULL, "fts_open(): %m"); + while ((ftse = fts_read(fts)) != NULL && expect->fts_name != NULL) { + if (expect->fts_info == FTS_DP || expect->fts_info == FTS_DNR) + level--; + if (fts_test_debug) { + fprintf(stderr, "%2ld %2d %s\n", level, + ftse->fts_info, ftse->fts_name); + } + ATF_CHECK_STREQ(expect->fts_name, ftse->fts_name); + ATF_CHECK_STREQ(expect->fts_accpath, ftse->fts_accpath); + ATF_CHECK_INTEQ(expect->fts_info, ftse->fts_info); + ATF_CHECK_INTEQ(level, ftse->fts_level); + if (expect->fts_info == FTS_D) + level++; + expect++; + } + ATF_CHECK_EQ(NULL, ftse); + ATF_CHECK_EQ(NULL, expect->fts_name); + ATF_REQUIRE_EQ_MSG(0, fts_close(fts), "fts_close(): %m"); +} + +#endif /* FTS_TEST_H_INCLUDED */