diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2020-06-08 12:25:21 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2020-06-08 16:50:24 +0300 |
commit | 10a4ed7c470d3fed8e2bb6b2089de68c61f9064b (patch) | |
tree | 88818d092adca845740ef905a1d2ef256091b8a7 /libbuild2/build/script | |
parent | 892c5c63cba987f3d74c47b730d600ab26f9c2e6 (diff) |
Fix crashing when special builtin appears inside if condition or branch
Diffstat (limited to 'libbuild2/build/script')
-rw-r--r-- | libbuild2/build/script/parser.cxx | 24 | ||||
-rw-r--r-- | libbuild2/build/script/parser.hxx | 10 |
2 files changed, 33 insertions, 1 deletions
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_; |