From 2f85ec0a37d1ad75956dd81016a8c7ab90ff845b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 12 Jan 2023 11:04:16 -0500 Subject: try_run: Avoid crash in keyword-dispatched signature when cross-compiling Since commit aa9220d3a0 (try_compile: Add keyword-dispatched signature, 2022-09-02, v3.25.0-rc1~178^2) the `DoNotRunExecutable` code path may be reached with no single source-file argument. Do not assume it exists. Fixes: #24295 --- Source/cmTryRunCommand.cxx | 14 ++++++++------ Tests/RunCMake/try_run/CrossCompile.cmake | 8 ++++++++ Tests/RunCMake/try_run/old_and_new_signature_tests.cmake | 2 ++ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 Tests/RunCMake/try_run/CrossCompile.cmake diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 1e81195..8d62cb1 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -40,7 +40,7 @@ public: std::string* runOutputStdOutContents, std::string* runOutputStdErrContents); void DoNotRunExecutable(const std::string& runArgs, - const std::string& srcFile, + cm::optional const& srcFile, std::string const& compileResultVariable, std::string* runOutputContents, std::string* runOutputStdOutContents, @@ -128,7 +128,7 @@ bool TryRunCommandImpl::TryRunCode(std::vector const& argv) if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") && !this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) { this->DoNotRunExecutable( - runArgs, *arguments.SourceDirectoryOrFile, + runArgs, arguments.SourceDirectoryOrFile, *arguments.CompileResultVariable, captureRunOutput ? &runOutputContents : nullptr, captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable @@ -238,7 +238,7 @@ void TryRunCommandImpl::RunExecutable(const std::string& runArgs, the executable would have produced. */ void TryRunCommandImpl::DoNotRunExecutable( - const std::string& runArgs, const std::string& srcFile, + const std::string& runArgs, cm::optional const& srcFile, std::string const& compileResultVariable, std::string* out, std::string* stdOut, std::string* stdErr) { @@ -421,9 +421,11 @@ void TryRunCommandImpl::DoNotRunExecutable( comment += "The "; comment += compileResultVariable; - comment += " variable holds the build result for this try_run().\n\n" - "Source file : "; - comment += srcFile + "\n"; + comment += " variable holds the build result for this try_run().\n\n"; + if (srcFile) { + comment += "Source file : "; + comment += *srcFile + "\n"; + } comment += "Executable : "; comment += copyDest + "\n"; comment += "Run arguments : "; diff --git a/Tests/RunCMake/try_run/CrossCompile.cmake b/Tests/RunCMake/try_run/CrossCompile.cmake new file mode 100644 index 0000000..4993768 --- /dev/null +++ b/Tests/RunCMake/try_run/CrossCompile.cmake @@ -0,0 +1,8 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +# Pretend we are cross-compiling to take that try_run code path. +set(CMAKE_CROSSCOMPILING 1) +set(RUN_RESULT 0) +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c) +unset(CMAKE_CROSSCOMPILING) diff --git a/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake b/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake index e1c1784..2b51eb2 100644 --- a/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake +++ b/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake @@ -11,6 +11,8 @@ run_cmake(BadLinkLibraries) run_cmake(BinDirEmpty) run_cmake(BinDirRelative) +run_cmake(CrossCompile) + run_cmake(WorkingDirArg) run_cmake(NoCompileOutputVariable) -- cgit v0.12 From 0191e8b512d4a2d2bdb9f65ea9edebced9dee372 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 12 Jan 2023 13:53:54 -0500 Subject: try_run: Do not require unrequested stdout/stderr when cross-compiling Since commit 048a02d5bb (ConfigureLog: Log try_compile and try_run checks, 2022-11-23) we always capture the stdout/stderr for logging. When cross-compiling, do not require `__TRYRUN_OUTPUT_STD{OUT,ERR}` variables to be populated just for the logging. --- Source/cmTryRunCommand.cxx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 86c9679..dcb52da 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -90,7 +90,8 @@ public: std::string const& compileResultVariable, std::string* runOutputContents, std::string* runOutputStdOutContents, - std::string* runOutputStdErrContents); + std::string* runOutputStdErrContents, + bool stdOutErrRequired); bool NoCache; std::string RunResultVariable; @@ -185,12 +186,17 @@ bool TryRunCommandImpl::TryRunCode(std::vector const& argv) std::string runOutputStdErrContents; if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") && !this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) { + // We only require the stdout/stderr cache entries if the project + // actually asked for the values, not just for logging. + bool const stdOutErrRequired = (arguments.RunOutputStdOutVariable || + arguments.RunOutputStdErrVariable); this->DoNotRunExecutable( runArgs, *arguments.SourceDirectoryOrFile, *arguments.CompileResultVariable, captureRunOutput ? &runOutputContents : nullptr, captureRunOutputStdOutErr ? &runOutputStdOutContents : nullptr, - captureRunOutputStdOutErr ? &runOutputStdErrContents : nullptr); + captureRunOutputStdOutErr ? &runOutputStdErrContents : nullptr, + stdOutErrRequired); } else { this->RunExecutable( runArgs, arguments.RunWorkingDirectory, @@ -311,7 +317,7 @@ void TryRunCommandImpl::RunExecutable(const std::string& runArgs, void TryRunCommandImpl::DoNotRunExecutable( const std::string& runArgs, const std::string& srcFile, std::string const& compileResultVariable, std::string* out, - std::string* stdOut, std::string* stdErr) + std::string* stdOut, std::string* stdErr, bool stdOutErrRequired) { // copy the executable out of the CMakeFiles/ directory, so it is not // removed at the end of try_run() and the user can run it manually @@ -357,7 +363,7 @@ void TryRunCommandImpl::DoNotRunExecutable( } // is the output from the executable used ? - if (stdOut || stdErr) { + if (stdOutErrRequired) { if (!this->Makefile->GetDefinition(internalRunOutputStdOutName)) { // if the variables doesn't exist, create it with a helpful error text // and mark it as advanced -- cgit v0.12