From 6e84c0f9c5e4d7d98d2a352eec6bc19de0d75d28 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Tue, 17 Sep 2019 16:00:20 +0300 Subject: Fix crashing on testscript command redirect overrides --- .../test/script/parser+redirect.test.testscript | 86 ++++++++++++++++++++++ libbuild2/test/script/parser.cxx | 47 +++++++++++- libbuild2/test/script/parser.hxx | 3 +- 3 files changed, 132 insertions(+), 4 deletions(-) (limited to 'libbuild2/test/script') diff --git a/libbuild2/test/script/parser+redirect.test.testscript b/libbuild2/test/script/parser+redirect.test.testscript index a8691da..49fa89b 100644 --- a/libbuild2/test/script/parser+redirect.test.testscript +++ b/libbuild2/test/script/parser+redirect.test.testscript @@ -167,6 +167,92 @@ } } } + + : overriding + : + { + : literal + : + { + : with + : + { + : string + : + $* <>EOO + cmd >>EOF >bar + foo + EOF + EOI + cmd >bar + EOO + + : regex + : + $* <>EOO + cmd >>FOO >>~/BAR/ + foo + FOO + bar + BAR + EOI + cmd >>~/BAR/ + bar + BAR + EOO + + : self + : + $* <>EOO + cmd >>EOF >>EOF + foo + EOF + EOI + cmd >>EOF + foo + EOF + EOO + + : different-modifiers + : + $* <>EOE != 0 + cmd >>EOF >>/EOF + foo + EOF + EOI + testscript:1:14: error: different modifiers for shared here-document 'EOF' + EOE + } + } + + : shared + : + { + : after-sharing + : + $* <>EOO + cmd >>EOF 2>>EOF >bar + foo + EOF + EOI + cmd >bar 2>>EOF + foo + EOF + EOO + + : before-sharing + : + $* <>EOO + cmd >>EOF >bar 2>>EOF + foo + EOF + EOI + cmd >bar 2>>EOF + foo + EOF + EOO + } + } } : file diff --git a/libbuild2/test/script/parser.cxx b/libbuild2/test/script/parser.cxx index 8b8f705..bc06ce8 100644 --- a/libbuild2/test/script/parser.cxx +++ b/libbuild2/test/script/parser.cxx @@ -1657,7 +1657,7 @@ namespace build2 // Parse the redirect operator. // auto parse_redirect = - [&c, &expr, &p, &mod, this] (token& t, const location& l) + [&c, &expr, &p, &mod, &hd, this] (token& t, const location& l) { // Our semantics is the last redirect seen takes effect. // @@ -1774,6 +1774,8 @@ namespace build2 } redirect& r (fd == 0 ? c.in : fd == 1 ? c.out : c.err); + redirect_type overriden (r.type); + r = redirect (rt); // Don't move as still may be used for pending here-document end @@ -1848,6 +1850,37 @@ namespace build2 case redirect_type::here_doc_ref: assert (false); break; } + + // If we are overriding a here-document, then remove the reference + // to this command redirect from the corresponding here_doc object. + // + if (!pre_parse_ && + (overriden == redirect_type::here_doc_literal || + overriden == redirect_type::here_doc_regex)) + { + size_t e (expr.size () - 1); + size_t p (expr.back ().pipe.size ()); + int f (static_cast (fd)); + + for (here_doc& d: hd) + { + small_vector& rs (d.redirects); + + auto i (find_if (rs.begin (), rs.end (), + [e, p, f] (const here_redirect& r) + { + return r.expr == e && + r.pipe == p && + r.fd == f; + })); + + if (i != rs.end ()) + { + rs.erase (i); + break; + } + } + } }; // Set pending cleanup type. @@ -2483,9 +2516,11 @@ namespace build2 parsed_doc v ( parse_here_document (t, tt, h.end, h.modifiers, h.regex)); - if (!pre_parse_) + // If all the here-document redirects are overridden, then we just + // drop the fragment. + // + if (!pre_parse_ && !h.redirects.empty ()) { - assert (!h.redirects.empty ()); auto i (h.redirects.cbegin ()); command& c (p.first[i->expr].pipe[i->pipe]); @@ -2493,11 +2528,17 @@ namespace build2 if (v.re) { + assert (r.type == redirect_type::here_doc_regex); + r.regex = move (v.regex); r.regex.flags = move (h.regex_flags); } else + { + assert (r.type == redirect_type::here_doc_literal); + r.str = move (v.str); + } r.end = move (h.end); r.end_line = v.end_line; diff --git a/libbuild2/test/script/parser.hxx b/libbuild2/test/script/parser.hxx index e4d1f3a..4d3fa49 100644 --- a/libbuild2/test/script/parser.hxx +++ b/libbuild2/test/script/parser.hxx @@ -122,7 +122,8 @@ namespace build2 struct here_doc { // Redirects that share here_doc. Most of the time we will have no - // more than 2 (2 - for the roundtrip test cases). + // more than 2 (2 - for the roundtrip test cases). Doesn't refer + // overridden redirects and thus can be empty. // small_vector redirects; -- cgit v1.1