From 9a9ce6637b390b7d3e58fe508fca731a6e84cf1d Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Aug 2026 09:57:40 -0400 Subject: [PATCH 1/2] file(GLOB): Teach CONFIGURE_DEPENDS to handle quotes in matched file names Otherwise a malicious file name can inject code into the verification script. Fixes: #28023 --- Source/cmGlobVerificationManager.cxx | 6 ++++-- .../file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt | 2 +- ...OB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt | 2 +- ...B-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt | 2 +- Tests/RunCMake/file/RunCMakeTest.cmake | 4 ++++ 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx index 73365d2d17..e9faa4d074 100644 --- a/Source/cmGlobVerificationManager.cxx +++ b/Source/cmGlobVerificationManager.cxx @@ -11,6 +11,7 @@ #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmMessenger.h" +#include "cmOutputConverter.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -64,8 +65,9 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path, verifyScriptFile << "\n"; verifyScriptFile << "set(OLD_GLOB\n"; - for (const std::string& file : v.Files) { - verifyScriptFile << " \"" << file << "\"\n"; + for (std::string const& file : v.Files) { + verifyScriptFile << " " << cmOutputConverter::EscapeForCMake(file) + << '\n'; } verifyScriptFile << " )\n"; diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt index 71ab721d71..379689483e 100644 --- a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt @@ -1 +1 @@ -.*b9fbdd8803c036dbe9f5ea6b74db4b9670c78a72 +.*(f7e3d5ebf4a6976f057a883301f2066b10bd4cd6|b9fbdd8803c036dbe9f5ea6b74db4b9670c78a72) diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt index ff90f9c1d1..b48c0f104e 100644 --- a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt @@ -1,2 +1,2 @@ .*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake -.*6bc141b40c0f851d20fa9a1fe5fbdae94acc5de0 +.*(293478329e0cb75b6b85e35dbe513b175f4c2311|6bc141b40c0f851d20fa9a1fe5fbdae94acc5de0) diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt index cf2a5afe67..ac6df2dab4 100644 --- a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt @@ -1,2 +1,2 @@ .*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake -.*0c3ceab9daa7914fde7410c34cae4049e140aa51 +.*(be528f629fe14e32494b2bba544361392e177d4c|0c3ceab9daa7914fde7410c34cae4049e140aa51) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 38ec2acd33..b93db833a3 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -144,6 +144,10 @@ else() file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test") + if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows|CYGWIN|MSYS") + # Test literal quotes in matched file names. + file(WRITE "${RunCMake_TEST_BINARY_DIR}/test/\".txt" "") + endif() set(tf_1 "${RunCMake_TEST_BINARY_DIR}/test/1.txt") file(WRITE "${tf_1}" "1") From 2c89c2a74c321cb617183bb45b089cf3a267b7e7 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 6 Aug 2026 09:57:40 -0400 Subject: [PATCH 2/2] file(GLOB): Teach CONFIGURE_DEPENDS to handle quotes in matched file names Otherwise a malicious file name can inject code into the verification script. Fixes: #28023 --- Source/cmGlobVerificationManager.cxx | 4 +++- .../file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt | 2 +- ...GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt | 2 +- ...LOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt | 2 +- Tests/RunCMake/file/RunCMakeTest.cmake | 4 ++++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx index 7798fc934e..2fe14c3219 100644 --- a/Source/cmGlobVerificationManager.cxx +++ b/Source/cmGlobVerificationManager.cxx @@ -11,6 +11,7 @@ #include "cmListFileCache.h" #include "cmMessageType.h" #include "cmMessenger.h" +#include "cmOutputConverter.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -63,7 +64,8 @@ bool cmGlobVerificationManager::SaveVerificationScript(std::string const& path, verifyScriptFile << "set(OLD_GLOB\n"; for (std::string const& file : v.Files) { - verifyScriptFile << " \"" << file << "\"\n"; + verifyScriptFile << " " << cmOutputConverter::EscapeForCMake(file) + << '\n'; } verifyScriptFile << " )\n"; diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt index 71ab721d71..379689483e 100644 --- a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt @@ -1 +1 @@ -.*b9fbdd8803c036dbe9f5ea6b74db4b9670c78a72 +.*(f7e3d5ebf4a6976f057a883301f2066b10bd4cd6|b9fbdd8803c036dbe9f5ea6b74db4b9670c78a72) diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt index ff90f9c1d1..b48c0f104e 100644 --- a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt @@ -1,2 +1,2 @@ .*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake -.*6bc141b40c0f851d20fa9a1fe5fbdae94acc5de0 +.*(293478329e0cb75b6b85e35dbe513b175f4c2311|6bc141b40c0f851d20fa9a1fe5fbdae94acc5de0) diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt index cf2a5afe67..ac6df2dab4 100644 --- a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt @@ -1,2 +1,2 @@ .*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake -.*0c3ceab9daa7914fde7410c34cae4049e140aa51 +.*(be528f629fe14e32494b2bba544361392e177d4c|0c3ceab9daa7914fde7410c34cae4049e140aa51) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 38ec2acd33..b93db833a3 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -144,6 +144,10 @@ else() file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test") + if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows|CYGWIN|MSYS") + # Test literal quotes in matched file names. + file(WRITE "${RunCMake_TEST_BINARY_DIR}/test/\".txt" "") + endif() set(tf_1 "${RunCMake_TEST_BINARY_DIR}/test/1.txt") file(WRITE "${tf_1}" "1")