From 8aee7fdb32a7099e3e4efdf1bf0a00732ee1c46b Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Thu, 22 Oct 2020 16:50:42 -0400 Subject: cmState: Prohibit override of flow control commands --- Source/cmCommands.cxx | 17 ++++++------ Source/cmFunctionCommand.cxx | 7 +++-- Source/cmLoadCommandCommand.cxx | 11 ++++---- Source/cmMacroCommand.cxx | 7 +++-- Source/cmState.cxx | 31 +++++++++++++++++++--- Source/cmState.h | 8 +++++- Tests/RunCMake/Syntax/Override.cmake | 6 +++++ Tests/RunCMake/Syntax/OverrideBreak-result.txt | 1 + Tests/RunCMake/Syntax/OverrideContinue-result.txt | 1 + Tests/RunCMake/Syntax/OverrideElse-result.txt | 1 + Tests/RunCMake/Syntax/OverrideElseIf-result.txt | 1 + .../RunCMake/Syntax/OverrideEndForeach-result.txt | 1 + .../RunCMake/Syntax/OverrideEndFunction-result.txt | 1 + Tests/RunCMake/Syntax/OverrideEndIf-result.txt | 1 + Tests/RunCMake/Syntax/OverrideEndMacro-result.txt | 1 + Tests/RunCMake/Syntax/OverrideEndWhile-result.txt | 1 + Tests/RunCMake/Syntax/OverrideForeach-result.txt | 1 + Tests/RunCMake/Syntax/OverrideFunction-result.txt | 1 + Tests/RunCMake/Syntax/OverrideIf-result.txt | 1 + Tests/RunCMake/Syntax/OverrideMacro-result.txt | 1 + Tests/RunCMake/Syntax/OverrideReturn-result.txt | 1 + Tests/RunCMake/Syntax/OverrideWhile-result.txt | 1 + Tests/RunCMake/Syntax/RunCMakeTest.cmake | 27 +++++++++++++++++++ 23 files changed, 108 insertions(+), 21 deletions(-) create mode 100644 Tests/RunCMake/Syntax/Override.cmake create mode 100644 Tests/RunCMake/Syntax/OverrideBreak-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideContinue-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideElse-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideElseIf-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideEndForeach-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideEndFunction-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideEndIf-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideEndMacro-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideEndWhile-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideForeach-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideFunction-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideIf-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideMacro-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideReturn-result.txt create mode 100644 Tests/RunCMake/Syntax/OverrideWhile-result.txt diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 37be542..9e5b783 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -119,12 +119,19 @@ void GetScriptingCommands(cmState* state) { - state->AddBuiltinCommand("break", cmBreakCommand); + state->AddFlowControlCommand("break", cmBreakCommand); + state->AddFlowControlCommand("continue", cmContinueCommand); + state->AddFlowControlCommand("foreach", cmForEachCommand); + state->AddFlowControlCommand("function", cmFunctionCommand); + state->AddFlowControlCommand("if", cmIfCommand); + state->AddFlowControlCommand("macro", cmMacroCommand); + state->AddFlowControlCommand("return", cmReturnCommand); + state->AddFlowControlCommand("while", cmWhileCommand); + state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired); state->AddBuiltinCommand("cmake_path", cmCMakePathCommand); state->AddBuiltinCommand("cmake_policy", cmCMakePolicyCommand); state->AddBuiltinCommand("configure_file", cmConfigureFileCommand); - state->AddBuiltinCommand("continue", cmContinueCommand); state->AddBuiltinCommand("exec_program", cmExecProgramCommand); state->AddBuiltinCommand("execute_process", cmExecuteProcessCommand); state->AddBuiltinCommand("file", cmFileCommand); @@ -133,26 +140,21 @@ void GetScriptingCommands(cmState* state) state->AddBuiltinCommand("find_package", cmFindPackage); state->AddBuiltinCommand("find_path", cmFindPath); state->AddBuiltinCommand("find_program", cmFindProgram); - state->AddBuiltinCommand("foreach", cmForEachCommand); - state->AddBuiltinCommand("function", cmFunctionCommand); state->AddBuiltinCommand("get_cmake_property", cmGetCMakePropertyCommand); state->AddBuiltinCommand("get_directory_property", cmGetDirectoryPropertyCommand); state->AddBuiltinCommand("get_filename_component", cmGetFilenameComponentCommand); state->AddBuiltinCommand("get_property", cmGetPropertyCommand); - state->AddBuiltinCommand("if", cmIfCommand); state->AddBuiltinCommand("include", cmIncludeCommand); state->AddBuiltinCommand("include_guard", cmIncludeGuardCommand); state->AddBuiltinCommand("list", cmListCommand); - state->AddBuiltinCommand("macro", cmMacroCommand); state->AddBuiltinCommand("make_directory", cmMakeDirectoryCommand); state->AddBuiltinCommand("mark_as_advanced", cmMarkAsAdvancedCommand); state->AddBuiltinCommand("math", cmMathCommand); state->AddBuiltinCommand("message", cmMessageCommand); state->AddBuiltinCommand("option", cmOptionCommand); state->AddBuiltinCommand("cmake_parse_arguments", cmParseArgumentsCommand); - state->AddBuiltinCommand("return", cmReturnCommand); state->AddBuiltinCommand("separate_arguments", cmSeparateArgumentsCommand); state->AddBuiltinCommand("set", cmSetCommand); state->AddBuiltinCommand("set_directory_properties", @@ -161,7 +163,6 @@ void GetScriptingCommands(cmState* state) state->AddBuiltinCommand("site_name", cmSiteNameCommand); state->AddBuiltinCommand("string", cmStringCommand); state->AddBuiltinCommand("unset", cmUnsetCommand); - state->AddBuiltinCommand("while", cmWhileCommand); state->AddUnexpectedCommand( "else", diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 71c82d6..1359009 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -163,8 +163,11 @@ bool cmFunctionFunctionBlocker::Replay( f.FilePath = this->GetStartingContext().FilePath; f.Line = this->GetStartingContext().Line; mf.RecordPolicies(f.Policies); - mf.GetState()->AddScriptedCommand(this->Args.front(), std::move(f)); - return true; + return mf.GetState()->AddScriptedCommand( + this->Args.front(), + BT(std::move(f), + mf.GetBacktrace().Push(this->GetStartingContext())), + mf); } } // anonymous namespace diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx index 5790e16..adebe02 100644 --- a/Source/cmLoadCommandCommand.cxx +++ b/Source/cmLoadCommandCommand.cxx @@ -24,6 +24,7 @@ #include "cmCommand.h" #include "cmDynamicLoader.h" #include "cmExecutionStatus.h" +#include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmState.h" @@ -36,8 +37,6 @@ # include /* for malloc/free on QNX */ #endif -class cmListFileBacktrace; - namespace { const char* LastName = nullptr; @@ -256,10 +255,12 @@ bool cmLoadCommandCommand(std::vector const& args, // if the symbol is found call it to set the name on the // function blocker if (initFunction) { - status.GetMakefile().GetState()->AddScriptedCommand( + return status.GetMakefile().GetState()->AddScriptedCommand( args[0], - cmLegacyCommandWrapper(cm::make_unique(initFunction))); - return true; + BT( + cmLegacyCommandWrapper(cm::make_unique(initFunction)), + status.GetMakefile().GetBacktrace()), + status.GetMakefile()); } status.SetError("Attempt to load command failed. " "No init function found."); diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 98f88c1..8c4b2a7 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -171,8 +171,11 @@ bool cmMacroFunctionBlocker::Replay(std::vector functions, f.Functions = std::move(functions); f.FilePath = this->GetStartingContext().FilePath; mf.RecordPolicies(f.Policies); - mf.GetState()->AddScriptedCommand(this->Args[0], std::move(f)); - return true; + return mf.GetState()->AddScriptedCommand( + this->Args[0], + BT(std::move(f), + mf.GetBacktrace().Push(this->GetStartingContext())), + mf); } } diff --git a/Source/cmState.cxx b/Source/cmState.cxx index d5ac9ae..77665f1 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -436,6 +436,19 @@ void cmState::AddBuiltinCommand(std::string const& name, }); } +void cmState::AddFlowControlCommand(std::string const& name, Command command) +{ + this->FlowControlCommands.insert(name); + this->AddBuiltinCommand(name, std::move(command)); +} + +void cmState::AddFlowControlCommand(std::string const& name, + BuiltinCommand command) +{ + this->FlowControlCommands.insert(name); + this->AddBuiltinCommand(name, command); +} + void cmState::AddDisallowedCommand(std::string const& name, BuiltinCommand command, cmPolicies::PolicyID policy, @@ -465,7 +478,7 @@ void cmState::AddDisallowedCommand(std::string const& name, void cmState::AddUnexpectedCommand(std::string const& name, const char* error) { - this->AddBuiltinCommand( + this->AddFlowControlCommand( name, [name, error](std::vector const&, cmExecutionStatus& status) -> bool { @@ -480,16 +493,28 @@ void cmState::AddUnexpectedCommand(std::string const& name, const char* error) }); } -void cmState::AddScriptedCommand(std::string const& name, Command command) +bool cmState::AddScriptedCommand(std::string const& name, BT command, + cmMakefile& mf) { std::string sName = cmSystemTools::LowerCase(name); + if (this->FlowControlCommands.count(sName)) { + mf.GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Built-in flow control command \"", sName, + "\" cannot be overridden."), + command.Backtrace); + cmSystemTools::SetFatalErrorOccured(); + return false; + } + // if the command already exists, give a new name to the old command. if (Command oldCmd = this->GetCommandByExactName(sName)) { this->ScriptedCommands["_" + sName] = oldCmd; } - this->ScriptedCommands[sName] = std::move(command); + this->ScriptedCommands[sName] = std::move(command.Value); + return true; } cmState::Command cmState::GetCommand(std::string const& name) const diff --git a/Source/cmState.h b/Source/cmState.h index 2aa57e0..0744f64 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "cmDefinitions.h" @@ -24,6 +25,7 @@ class cmCacheManager; class cmCommand; class cmGlobVerificationManager; +class cmMakefile; class cmStateSnapshot; class cmMessenger; class cmExecutionStatus; @@ -157,10 +159,13 @@ public: std::unique_ptr command); void AddBuiltinCommand(std::string const& name, Command command); void AddBuiltinCommand(std::string const& name, BuiltinCommand command); + void AddFlowControlCommand(std::string const& name, Command command); + void AddFlowControlCommand(std::string const& name, BuiltinCommand command); void AddDisallowedCommand(std::string const& name, BuiltinCommand command, cmPolicies::PolicyID policy, const char* message); void AddUnexpectedCommand(std::string const& name, const char* error); - void AddScriptedCommand(std::string const& name, Command command); + bool AddScriptedCommand(std::string const& name, BT command, + cmMakefile& mf); void RemoveBuiltinCommand(std::string const& name); void RemoveUserDefinedCommands(); std::vector GetCommandNames() const; @@ -223,6 +228,7 @@ private: std::vector EnabledLanguages; std::unordered_map BuiltinCommands; std::unordered_map ScriptedCommands; + std::unordered_set FlowControlCommands; cmPropertyMap GlobalProperties; std::unique_ptr CacheManager; std::unique_ptr GlobVerificationManager; diff --git a/Tests/RunCMake/Syntax/Override.cmake b/Tests/RunCMake/Syntax/Override.cmake new file mode 100644 index 0000000..af62db1 --- /dev/null +++ b/Tests/RunCMake/Syntax/Override.cmake @@ -0,0 +1,6 @@ +function(override) + function(${FUNCTION_NAME}) + endfunction() +endfunction() +override() +message(FATAL_ERROR "This shouldn't happen") diff --git a/Tests/RunCMake/Syntax/OverrideBreak-result.txt b/Tests/RunCMake/Syntax/OverrideBreak-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideBreak-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideContinue-result.txt b/Tests/RunCMake/Syntax/OverrideContinue-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideContinue-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideElse-result.txt b/Tests/RunCMake/Syntax/OverrideElse-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideElse-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideElseIf-result.txt b/Tests/RunCMake/Syntax/OverrideElseIf-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideElseIf-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideEndForeach-result.txt b/Tests/RunCMake/Syntax/OverrideEndForeach-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideEndForeach-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideEndFunction-result.txt b/Tests/RunCMake/Syntax/OverrideEndFunction-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideEndFunction-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideEndIf-result.txt b/Tests/RunCMake/Syntax/OverrideEndIf-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideEndIf-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideEndMacro-result.txt b/Tests/RunCMake/Syntax/OverrideEndMacro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideEndMacro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideEndWhile-result.txt b/Tests/RunCMake/Syntax/OverrideEndWhile-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideEndWhile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideForeach-result.txt b/Tests/RunCMake/Syntax/OverrideForeach-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideForeach-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideFunction-result.txt b/Tests/RunCMake/Syntax/OverrideFunction-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideFunction-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideIf-result.txt b/Tests/RunCMake/Syntax/OverrideIf-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideIf-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideMacro-result.txt b/Tests/RunCMake/Syntax/OverrideMacro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideMacro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideReturn-result.txt b/Tests/RunCMake/Syntax/OverrideReturn-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideReturn-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/OverrideWhile-result.txt b/Tests/RunCMake/Syntax/OverrideWhile-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/Syntax/OverrideWhile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/Syntax/RunCMakeTest.cmake b/Tests/RunCMake/Syntax/RunCMakeTest.cmake index 8d74dc1..3fc769d 100644 --- a/Tests/RunCMake/Syntax/RunCMakeTest.cmake +++ b/Tests/RunCMake/Syntax/RunCMakeTest.cmake @@ -122,3 +122,30 @@ run_cmake(FunctionUnmatched) run_cmake(FunctionUnmatchedForeach) run_cmake(MacroUnmatched) run_cmake(MacroUnmatchedForeach) + +function(run_override name) + string(TOLOWER "${name}" lname) + set(RunCMake_DEFAULT_stderr "^CMake Error at [^ +]*/Tests/RunCMake/Syntax/Override\\.cmake:[0-9]+ \\(function\\): + Built-in flow control command \"${lname}\" cannot be overridden\\. +Call Stack \\(most recent call first\\): + [^ +]*/Tests/RunCMake/Syntax/Override\\.cmake:[0-9]+ \\(override\\)$") + run_cmake_command(Override${name} "${CMAKE_COMMAND}" -DFUNCTION_NAME=${name} -P "${RunCMake_SOURCE_DIR}/Override.cmake") +endfunction() + +run_override(Break) +run_override(Continue) +run_override(Else) +run_override(ElseIf) +run_override(EndForeach) +run_override(EndFunction) +run_override(EndIf) +run_override(EndMacro) +run_override(EndWhile) +run_override(Foreach) +run_override(Function) +run_override(If) +run_override(Macro) +run_override(Return) +run_override(While) -- cgit v0.12