diff --git a/kernel/driver.cc b/kernel/driver.cc index 2a4ad1295..fefc62234 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -165,6 +165,7 @@ int main(int argc, char **argv) cxxopts::value>(), "") ("D,define", "set the specified Verilog define to if supplied via command \"read -define\"", cxxopts::value>(), "[=]") + ("enable-exec", "enable the 'exec' command, which runs arbitrary shell commands") ("S,synth", "shortcut for calling the \"synth\" command, a default script for transforming " \ "the Verilog input to a gate-level netlist. For example: " \ "yosys -o output.blif -S input.v " \ @@ -261,6 +262,7 @@ int main(int argc, char **argv) passes_commands.push_back("synth"); run_shell = false; } + if (result.count("enable-exec")) yosys_enable_exec = true; if (result.count("C")) run_tcl_shell = true; if (result.count("g")) log_force_debug++; if (result.count("m")) plugin_filenames = result["m"].as>(); diff --git a/kernel/register.cc b/kernel/register.cc index db42de008..2f7125582 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -218,6 +218,8 @@ void Pass::call(RTLIL::Design *design, std::string command) return; if (tok[0] == '!') { + if (!yosys_enable_exec) + log_cmd_error("The shell escape ('!') is disabled. Run Yosys with --enable-exec to enable it.\n"); #if defined(YOSYS_ENABLE_SPAWN) cmd_buf = command.substr(command.find('!') + 1); while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' || diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 167052340..6926a34cf 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -84,6 +84,7 @@ YOSYS_NAMESPACE_BEGIN Autoidx autoidx(1); int yosys_xtrace = 0; bool yosys_write_versions = true; +bool yosys_enable_exec = false; const char* yosys_maybe_version() { if (yosys_write_versions) return yosys_version_str; diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 9e19814bd..b6cde9453 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -296,6 +296,7 @@ private: extern Autoidx autoidx; extern int yosys_xtrace; extern bool yosys_write_versions; +extern bool yosys_enable_exec; const std::string *create_id_prefix(std::string_view file, int line, std::string_view func); RTLIL::IdString new_id_suffix(std::string_view file, int line, std::string_view func, std::string_view suffix); diff --git a/passes/cmds/exec.cc b/passes/cmds/exec.cc index f7a5bf8f7..4ed72ebcb 100644 --- a/passes/cmds/exec.cc +++ b/passes/cmds/exec.cc @@ -49,7 +49,8 @@ struct ExecPass : public Pass { log("\n"); log(" exec [options] -- [command]\n"); log("\n"); - log("Execute a command in the operating system shell. All supplied arguments are\n"); + log("Execute a command in the operating system shell. Enabled only\n"); + log("when Yosys is run with --enable-exec. All supplied arguments are\n"); log("concatenated and passed as a command to popen(3). Whitespace is not guaranteed\n"); log("to be preserved, even if quoted. stdin and stderr are not connected, while\n"); log("stdout is logged unless the \"-q\" option is specified.\n"); @@ -78,6 +79,9 @@ struct ExecPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) override { + if (!yosys_enable_exec) + log_cmd_error("The 'exec' command is disabled. Run Yosys with --enable-exec to enable it.\n"); + std::string cmd = ""; char buf[1024] = {}; std::string linebuf = ""; diff --git a/tests/gen_tests_makefile.py b/tests/gen_tests_makefile.py index 13bb806c9..a7251b5a4 100644 --- a/tests/gen_tests_makefile.py +++ b/tests/gen_tests_makefile.py @@ -26,12 +26,14 @@ def generate_target(name, command, deps = None): print(f"\t@$(call run_test,{target}, $({target}_cmd))") def generate_ys_test(ys_file, yosys_args="", commands=""): + yosys_args = f"--enable-exec {yosys_args}".strip() cmd = f'$(YOSYS) -l {ys_file}.err {yosys_args} {ys_file} && mv {ys_file}.err {ys_file}.log' if commands: cmd += f"; \\\n{commands}" generate_target(ys_file, cmd) def generate_tcl_test(tcl_file, yosys_args="", commands=""): + yosys_args = f"--enable-exec {yosys_args}".strip() cmd = f'$(YOSYS) -l {tcl_file}.err {yosys_args} {tcl_file} && mv {tcl_file}.err {tcl_file}.log' if commands: cmd += f"; \\\n{commands}"