From 8898f8ae1ffe724a149da242f7497c850f787e33 Mon Sep 17 00:00:00 2001 From: Enzo Evers Date: Mon, 23 Dec 2024 10:11:19 +0100 Subject: [PATCH] dev: ensure that RecursiveRmdir only handles directories as input --- CoDeLib/FileUtils/src/FileUtils.c | 11 ++++ CoDeLib/Test/src/TestFileUtils.c | 59 +++++++++++++++++++ CoDeLib/include/CoDeLib/FileUtils/FileUtils.h | 3 +- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/CoDeLib/FileUtils/src/FileUtils.c b/CoDeLib/FileUtils/src/FileUtils.c index 056ee27a..bf6ec560 100644 --- a/CoDeLib/FileUtils/src/FileUtils.c +++ b/CoDeLib/FileUtils/src/FileUtils.c @@ -133,6 +133,17 @@ bool RecursiveRmdir(const char *const pDirname) { return false; } + const size_t dirnameLength = + strnlen(pDirname, MAX_PATH_LENGTH_WTH_TERMINATOR); + if (dirnameLength == 0 || dirnameLength >= MAX_PATH_LENGTH_WTH_TERMINATOR) { + return false; + } + + const char lastChar = pDirname[dirnameLength - 1]; + if (lastChar != '/' && lastChar != '\\') { + return false; + } + const int maxOpenFiles = 64; const int flags = FTW_DEPTH | FTW_PHYS; int status = nftw(pDirname, _HandleFtwCallback_Remove, maxOpenFiles, flags); diff --git a/CoDeLib/Test/src/TestFileUtils.c b/CoDeLib/Test/src/TestFileUtils.c index c689f421..f1b0431b 100644 --- a/CoDeLib/Test/src/TestFileUtils.c +++ b/CoDeLib/Test/src/TestFileUtils.c @@ -470,6 +470,49 @@ TEST(TestFileUtils, test_RecursiveRmdir_ReturnsFalseIfDirnameIsNull) { TEST_ASSERT_FALSE(success); } +TEST(TestFileUtils, test_RecursiveRmdir_ReturnsFalseIfDirnameIsEmpty) { + bool success = RecursiveRmdir(""); + TEST_ASSERT_FALSE(success); +} + +TEST(TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfDirnameIsLargerThanMaxPath) { + char localBuffer[MAX_PATH_LENGTH_WTH_TERMINATOR + 1]; + memset(localBuffer, 'a', MAX_PATH_LENGTH_WTH_TERMINATOR); + localBuffer[MAX_PATH_LENGTH_WTH_TERMINATOR] = '\0'; + + bool success = RecursiveRmdir(localBuffer); + TEST_ASSERT_FALSE(success); +} + +TEST( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfRelativePathDoesNotEndInSlash_WindowsStyle) { + bool success = RecursiveRmdir(".\\NonExisting\\other"); + TEST_ASSERT_FALSE(success); +} + +TEST( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfRelativePathDoesNotEndInSlash_PosixStyle) { + bool success = RecursiveRmdir("./NonExisting/other"); + TEST_ASSERT_FALSE(success); +} + +TEST( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfAbsolutePathDoesNotEndInSlash_WindowsStyle) { + bool success = RecursiveRmdir("C:\\NonExisting\\other"); + TEST_ASSERT_FALSE(success); +} + +TEST( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfAbsolutePathDoesNotEndInSlash_PosixStyle) { + bool success = RecursiveRmdir("/NonExisting/other"); + TEST_ASSERT_FALSE(success); +} + TEST(TestFileUtils, test_RecursiveRmdir_CanDeleteAbsolutePath) { RAII_STRING tmpPath = RaiiStringCreateFromCString(g_pFullPathToBenchmarkTestFiles); @@ -723,6 +766,22 @@ TEST_GROUP_RUNNER(TestFileUtils) { // RecursiveRmdir(...) RUN_TEST_CASE(TestFileUtils, test_RecursiveRmdir_ReturnsFalseIfDirnameIsNull); + RUN_TEST_CASE(TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfDirnameIsEmpty); + RUN_TEST_CASE(TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfDirnameIsLargerThanMaxPath); + RUN_TEST_CASE( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfRelativePathDoesNotEndInSlash_WindowsStyle); + RUN_TEST_CASE( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfRelativePathDoesNotEndInSlash_PosixStyle); + RUN_TEST_CASE( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfAbsolutePathDoesNotEndInSlash_WindowsStyle); + RUN_TEST_CASE( + TestFileUtils, + test_RecursiveRmdir_ReturnsFalseIfAbsolutePathDoesNotEndInSlash_PosixStyle); RUN_TEST_CASE(TestFileUtils, test_RecursiveRmdir_CanDeleteAbsolutePath); RUN_TEST_CASE(TestFileUtils, test_RecursiveRmdir_CanDeleteRecursiveAbsolutePath); diff --git a/CoDeLib/include/CoDeLib/FileUtils/FileUtils.h b/CoDeLib/include/CoDeLib/FileUtils/FileUtils.h index df1ebb2b..76cb915b 100644 --- a/CoDeLib/include/CoDeLib/FileUtils/FileUtils.h +++ b/CoDeLib/include/CoDeLib/FileUtils/FileUtils.h @@ -18,7 +18,8 @@ bool RecursiveMkdir(const char *const pDirname); /*! @brief Recursively deletes a directory and all files. If the directory does not exist, nothing happens. -@param pDirname The directory to delete. The directory needs to end in '/'. +@param pDirname The directory to delete. The directory needs to end in '/' or +'\\' ('\' escaped). @return true if the directory was deleted or did not exist, false otherwise. */ bool RecursiveRmdir(const char *const pDirname);