CPS: Fix crash on bad paths in .cps file

The logic to compute the CPS prefix by comparing the specified relative
path to the actual path contained a potential overflow if the specified
path is longer than the actual path.  Fix this by comparing the path
lengths first.

Fixes: #27631
This commit is contained in:
Matthew Woehlke
2026-02-23 12:40:55 -05:00
committed by Brad King
parent ee5414b0e6
commit 7d2b4df69a
10 changed files with 47 additions and 8 deletions

View File

@@ -137,8 +137,14 @@ bool CheckSchemaVersion(Json::Value const& data)
bool ComparePathSuffix(std::string const& path, std::string const& suffix)
{
std::string const& tail = path.substr(path.size() - suffix.size());
return cmSystemTools::ComparePath(tail, suffix);
std::string::size_type const ps = path.size();
std::string::size_type const ss = suffix.size();
if (ss > ps) {
return false;
}
return cmSystemTools::ComparePath(path.substr(ps - ss), suffix);
}
std::string DeterminePrefix(std::string const& filepath,

View File

@@ -1,11 +1,11 @@
CMake Error at BadPrefix\.cmake:[0-9]+ \(find_package\):
Could not find a configuration file for package "BadPrefix" that is
CMake Error at BadPrefix1\.cmake:[0-9]+ \(find_package\):
Could not find a configuration file for package "BadPrefix1" that is
compatible with requested version ""\.
The following configuration files were considered but not accepted:
(
[^
]*/Tests/RunCMake/find_package-CPS/cps/[Bb]ad[Pp]refix\.cps, version: unknown
]*/Tests/RunCMake/find_package-CPS/cps/[Bb]ad[Pp]refix1\.cps, version: unknown
The package description file could not be read\.)+
Call Stack \(most recent call first\):

View File

@@ -8,4 +8,4 @@ set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
###############################################################################
# Test reporting when trying to read a .cps whose absolute prefix cannot be
# determined.
find_package(BadPrefix REQUIRED)
find_package(BadPrefix1 REQUIRED)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,12 @@
CMake Error at BadPrefix2\.cmake:[0-9]+ \(find_package\):
Could not find a configuration file for package "BadPrefix2" that is
compatible with requested version ""\.
The following configuration files were considered but not accepted:
(
[^
]*/Tests/RunCMake/find_package-CPS/cps/[Bb]ad[Pp]refix2\.cps, version: unknown
The package description file could not be read\.)+
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 4.0)
include(Setup.cmake)
set(CMAKE_FIND_PACKAGE_SORT_ORDER NAME)
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
###############################################################################
# Test that trying to read a .cps whose claimed prefix is longer than its
# actual prefix doesn't crash CMake.
#
# https://gitlab.kitware.com/cmake/cmake/-/issues/27631
find_package(BadPrefix2 REQUIRED)

View File

@@ -34,7 +34,8 @@ run_cmake(InvalidCps1)
run_cmake(InvalidCps2)
run_cmake(InvalidCps3)
run_cmake(WrongName)
run_cmake(BadPrefix)
run_cmake(BadPrefix1)
run_cmake(BadPrefix2)
# Version-matching tests
run_cmake(ExactVersion)

View File

@@ -1,6 +1,6 @@
{
"cps_version": "0.13",
"name": "BadPrefix",
"name": "BadPrefix1",
"cps_path": "@prefix@/share/cps",
"components": {}
}

View File

@@ -0,0 +1,6 @@
{
"cps_version": "0.13",
"name": "BadPrefix2",
"cps_path": "@prefix@/if the specified prefix is longer than the actual prefix, it obviously doesn't match/however, the code to compare path tails just subtracted without checking/that could cause CMake to try to pass a negative number as a string offset/that would result in an indexing error that could lead to a seg-fault/since we don't know where the test is running, it's hard to ensure that this string is longer than the actual path/so let's just make it absurdly long and hope for the best/this should be okay on at least some instances, which will be enough to let us know if there's still a problem/cps",
"components": {}
}