From 10a4ed7c470d3fed8e2bb6b2089de68c61f9064b Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 8 Jun 2020 12:25:21 +0300 Subject: Fix crashing when special builtin appears inside if condition or branch --- libbuild2/build/script/parser.cxx | 24 +++++++++++++++++++++++- libbuild2/build/script/parser.hxx | 10 ++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'libbuild2/build/script') diff --git a/libbuild2/build/script/parser.cxx b/libbuild2/build/script/parser.cxx index 747e56f..16dead1 100644 --- a/libbuild2/build/script/parser.cxx +++ b/libbuild2/build/script/parser.cxx @@ -202,6 +202,12 @@ namespace build2 case line_type::cmd_if: case line_type::cmd_ifn: next (t, tt); // Skip to start of command. + + if (lt == line_type::cmd_if || lt == line_type::cmd_ifn) + ++level_; + else if (lt == line_type::cmd_end) + --level_; + // Fall through. case line_type::cmd: { @@ -356,12 +362,26 @@ namespace build2 // builtin. Also review the non-script-local variables tracking while // executing a single line in lookup_variable(). // - if (pre_parse_ && first && tt == type::word) + if (pre_parse_ && tt == type::word) { const string& v (t.value); + // Verify that the special builtin is not called inside an improper + // context (flow control construct or complex expression). + // + auto verify = [first, &v, &l, this] () + { + if (level_ != 0) + fail (l) << "'" << v << "' call inside flow control construct"; + + if (!first) + fail (l) << "'" << v << "' call must be the only command"; + }; + if (v == "diag") { + verify (); + // Check for ambiguity. // if (diag_weight_ == 4) @@ -402,6 +422,8 @@ namespace build2 } else if (v == "depdb") { + verify (); + // Note that the rest of the line contains the builtin command // name, potentially followed by the arguments to be // hashed/saved. Thus, we parse it in the value lexer mode. diff --git a/libbuild2/build/script/parser.hxx b/libbuild2/build/script/parser.hxx index a652cf4..73bcd09 100644 --- a/libbuild2/build/script/parser.hxx +++ b/libbuild2/build/script/parser.hxx @@ -181,6 +181,16 @@ namespace build2 // line* save_line_; + // The if-else nesting level (and in the future for other flow + // control constructs). + // + // Maintained during pre-parsing and is incremented when the cmd_if or + // cmd_ifn lines are encountered, which in particular means that it is + // already incremented by the time the if-condition expression is + // pre-parsed. Decremented when the cmd_end line is encountered. + // + size_t level_ = 0; + // Execute state. // runner* runner_; -- cgit v1.1