FileSets: Don't crash if a file's file set isn't found

File sets currently have issues with files containing semicolons;
particularly, names get mangled differently in different contexts. This
can result in failing to find a file's file set. Prior to dee8799d16
(FileSet management: Introduce dedicated classes for generation,
2026-02-16, v4.4.0-rc1~691^2), we guarded against this, but the
aforementioned commit introduced code that would try to use the found
fileset object without checking if it was valid. Add the missing checks
so that we do not crash trying to dereference a null pointer. Also,
refactor `cmGeneratorTarget::GetSourceFilePaths` to avoid unnecessary
work.

Fixes: #27924
This commit is contained in:
Matthew Woehlke
2026-07-08 12:30:17 -04:00
parent f0c892d572
commit d9b9b4cd27
3 changed files with 58 additions and 14 deletions
+12 -14
View File
@@ -266,26 +266,24 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
AddFileSetEntries(this, this->FileSets.get(), context, &fsDagChecker,
fileSetEntries);
auto processFileSetEntry = [this, &config](cmSourceFile* sf) {
auto const* fileSet = this->GetFileSetForSource(config, sf);
if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
cmGeneratorFileSet const* fileSet = this->GetFileSetForSource(config, sf);
if (fileSet && fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
}
#if !defined(CMAKE_BOOTSTRAP)
cmMakefile* mf = this->Target->GetMakefile();
auto const& path = sf->GetFullPath();
bool found = false;
for (auto const& sg : mf->GetSourceGroups()) {
if (sg->MatchChildrenFiles(path)) {
found = true;
break;
cmMakefile* mf = this->Target->GetMakefile();
std::string const& path = sf->GetFullPath();
bool found = false;
for (auto const& sg : mf->GetSourceGroups()) {
if (sg->MatchChildrenFiles(path)) {
found = true;
break;
}
}
}
if (!found) {
if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
if (!found) {
mf->GetOrCreateSourceGroup("Header Files")->AddGroupFile(path);
}
}
#endif
}
};
bool contextDependentFileSets =
processSources(this, config, fileSetEntries, files, uniqueSrcs,
@@ -0,0 +1,45 @@
enable_language(C)
add_library(lib1 STATIC empty.c)
set_property(
SOURCE ${CMAKE_CURRENT_BINARY_DIR}/h\\;1.h
PROPERTY GENERATED TRUE
)
set_property(
SOURCE ${CMAKE_CURRENT_BINARY_DIR}/h\\;2.h
PROPERTY GENERATED TRUE
)
set_property(
SOURCE ${CMAKE_CURRENT_BINARY_DIR}/h\\;3.h
PROPERTY GENERATED TRUE
)
target_sources(lib1
PRIVATE FILE_SET HEADERS
BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR}
FILES ${CMAKE_CURRENT_BINARY_DIR}/h\\\\\\\\;1.h
)
set_property(TARGET lib1 APPEND PROPERTY HEADER_SET
${CMAKE_CURRENT_BINARY_DIR}/h\\\\\\\\;2.h
${CMAKE_CURRENT_BINARY_DIR}/h\\\\\\\\;3.h
)
# Ensure we get the expected number of escapes when reading back the file set
# files.
get_property(headers TARGET lib1 PROPERTY HEADER_SET)
if (NOT headers MATCHES "h\\\\\\\\\\\\;1[.]h")
message(STATUS "headers: '${headers}'")
message(SEND_ERROR "'h;1.h' has wrong level of escaping")
endif()
if (NOT headers MATCHES "h\\\\\\\\\\\\;2[.]h")
message(STATUS "headers: '${headers}'")
message(SEND_ERROR "'h;2.h' has wrong level of escaping")
endif()
if (NOT headers MATCHES "h\\\\\\\\\\\\;3[.]h$")
message(STATUS "headers: '${headers}'")
message(SEND_ERROR "'h;3.h' has wrong level of escaping")
endif()
@@ -45,6 +45,7 @@ run_cmake(FileSetBadName)
run_cmake(FileSetWrongSyntax)
run_cmake(FileSetDirect)
run_cmake(FileSetDuplicateSource)
run_cmake(FileSetSemicolon)
if(APPLE)
run_cmake(FileSetFramework1)
run_cmake(FileSetFramework2)