export: Fix use-after-free on multiple calls overwriting same FILE

CMake 3.16 and below allow multiple `export()` calls with the same output
file even without using `APPEND`.  The implementation worked by accident
by leaking memory.  Refactoring in commit 5444a8095d (cmGlobalGenerator:
modernize memrory managemenbt, 2019-12-29, v3.17.0-rc1~239^2) cleaned up
that memory leak and converted it to a use-after-free instead.

The problem is caused by using the `cmGlobalGenerator::BuildExportSets`
map to own `cmExportBuildFileGenerator` instances.  It can own only
one instance per output FILE name at a time, so repeating use of the
same file now frees the old `cmExportBuildFileGenerator` instance
and leaves the pointer in the `cmMakefile::ExportBuildFileGenerators`
vector dangling.  Move ownership of the instances into `cmMakefile`'s
vector since its entries are not replaced on a repeat output FILE.

In future work we should introduce a policy to error out on this case.
For now simply fix the use-after-free to restore CMake <= 3.16 behavior.

Fixes: #20469
This commit is contained in:
Brad King
2020-03-18 09:51:46 -04:00
parent 1ec72e0947
commit 8affe9aa33
8 changed files with 41 additions and 28 deletions
+6 -4
View File
@@ -945,10 +945,11 @@ public:
const std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>&
GetEvaluationFiles() const;
std::vector<cmExportBuildFileGenerator*> GetExportBuildFileGenerators()
const;
std::vector<std::unique_ptr<cmExportBuildFileGenerator>> const&
GetExportBuildFileGenerators() const;
void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(
std::unique_ptr<cmExportBuildFileGenerator> gen);
// Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
// searches
@@ -1053,7 +1054,8 @@ private:
mutable cmsys::RegularExpression cmNamedCurly;
std::vector<cmMakefile*> UnConfiguredDirectories;
std::vector<cmExportBuildFileGenerator*> ExportBuildFileGenerators;
std::vector<std::unique_ptr<cmExportBuildFileGenerator>>
ExportBuildFileGenerators;
std::vector<std::unique_ptr<cmGeneratorExpressionEvaluationFile>>
EvaluationFiles;