From 637a0f7ed437277ec22ba7ac5df7841664f0bcab Mon Sep 17 00:00:00 2001 From: Nikita Nemkin Date: Tue, 4 Feb 2025 22:04:35 +0500 Subject: cmCacheManager: Prevent corruption from multiline help strings Corruption happens when a multiline help string starts with a newline. This causes an overflow in substr() and the whole, unescaped help string is written to the cache file. Multiline strings are escaped line by line. The fix is to start searching for line break points from position 1. A break point at zero, which triggers the overflow, could only produce a redundant empty line. Fixes: #9098 --- Source/cmCacheManager.cxx | 2 +- Tests/RunCMake/Configure/CacheVarHelpString.cmake | 21 +++++++++++++++++++++ Tests/RunCMake/Configure/RunCMakeTest.cmake | 6 ++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/Configure/CacheVarHelpString.cmake diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 4ce2b66..0a4ed4a 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -414,7 +414,7 @@ void cmCacheManager::OutputHelpString(std::ostream& fout, } std::string oneLine; std::string::size_type pos = 0; - for (std::string::size_type i = 0; i <= end; i++) { + for (std::string::size_type i = 1; i <= end; i++) { if ((i == end) || (helpString[i] == '\n') || ((i - pos >= 60) && (helpString[i] == ' '))) { fout << "//"; diff --git a/Tests/RunCMake/Configure/CacheVarHelpString.cmake b/Tests/RunCMake/Configure/CacheVarHelpString.cmake new file mode 100644 index 0000000..262e527 --- /dev/null +++ b/Tests/RunCMake/Configure/CacheVarHelpString.cmake @@ -0,0 +1,21 @@ +# Various newline possibilities + +set(help_strings + "\n" + "\n\n\n" + "\n \n" + "\nline1" + "line1\n" + "\nline1\n" + "line1\nline2\nline3" + "\nline1\nline2\nline3\n" + " +line line line line line line line line line line line line line line line line +line line line line line line line line line line line line line line line line +line line line line line line line line line line line line line line line line" +) + +foreach(help IN LISTS help_strings) + string(SHA1 name "${help}") + set("${name}" "" CACHE STRING "${help}" FORCE) +endforeach() diff --git a/Tests/RunCMake/Configure/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake index 9b686e4..57cf947 100644 --- a/Tests/RunCMake/Configure/RunCMakeTest.cmake +++ b/Tests/RunCMake/Configure/RunCMakeTest.cmake @@ -64,6 +64,12 @@ if(NOT RunCMake_GENERATOR MATCHES "^Ninja Multi-Config$") run_cmake(NoCMAKE_DEFAULT_CONFIGS) endif() +block() + run_cmake(CacheVarHelpString) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake(CacheVarHelpString) +endblock() + if(NOT CMAKE_HOST_WIN32) block() # Test a non-writable build directory. -- cgit v0.12