aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/build
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-06-08 12:25:21 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-06-08 16:50:24 +0300
commit10a4ed7c470d3fed8e2bb6b2089de68c61f9064b (patch)
tree88818d092adca845740ef905a1d2ef256091b8a7 /libbuild2/build
parent892c5c63cba987f3d74c47b730d600ab26f9c2e6 (diff)
Fix crashing when special builtin appears inside if condition or branch
Diffstat (limited to 'libbuild2/build')
-rw-r--r--libbuild2/build/script/parser.cxx24
-rw-r--r--libbuild2/build/script/parser.hxx10
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_;