forked from pool/systemtap
183 lines
6.1 KiB
Diff
183 lines
6.1 KiB
Diff
|
From: Josh Stone <jistone@redhat.com>
|
||
|
Date: Tue Jan 19 15:36:35 2010 -0800
|
||
|
Git-Repo: git://sources.redhat.com/git/systemtap.git
|
||
|
Git-Commit: 9300f661214a4f4dfac75878485867b30c7db389
|
||
|
Signed-Off-By: Tony Jones <tonyj@suse.de>
|
||
|
|
||
|
tonyj: this fixes parse errors such as:
|
||
|
parse error: expected 'probe', 'global', 'function', or '%{'
|
||
|
saw: identifier '?robe' at
|
||
|
|
||
|
-------------------------------------------------
|
||
|
PR11195: Prevent all nested argument substitution
|
||
|
|
||
|
Our existing protection only made sure that the first token in a
|
||
|
substitution wasn't a nested substitution. That's not sufficient when
|
||
|
there could be multiple tokens involved. This patch makes sure that no
|
||
|
nested tokens are ever allowed to be argument substitutions.
|
||
|
|
||
|
This also adds a cursor_suspended_line/column and resets the main
|
||
|
cursor_line/column to the beginning of the substitution, so errors will
|
||
|
point a little closer to the right place.
|
||
|
|
||
|
diff --git a/parse.cxx b/parse.cxx
|
||
|
index edb1927..2688d6d 100644
|
||
|
--- a/parse.cxx
|
||
|
+++ b/parse.cxx
|
||
|
@@ -632,7 +632,8 @@ parser::peek_kw (std::string const & kw)
|
||
|
|
||
|
lexer::lexer (istream& input, const string& in, systemtap_session& s):
|
||
|
input_name (in), input_pointer (0), input_end (0),
|
||
|
- cursor_suspend_count(0), cursor_line (1), cursor_column (1),
|
||
|
+ cursor_suspend_count(0), cursor_suspend_line (1), cursor_suspend_column (1),
|
||
|
+ cursor_line (1), cursor_column (1),
|
||
|
session(s), current_file (0)
|
||
|
{
|
||
|
getline(input, input_contents, '\0');
|
||
|
@@ -693,9 +694,15 @@ lexer::input_get ()
|
||
|
++input_pointer;
|
||
|
|
||
|
if (cursor_suspend_count)
|
||
|
- // Track effect of input_put: preserve previous cursor/line_column
|
||
|
- // until all of its characters are consumed.
|
||
|
- cursor_suspend_count --;
|
||
|
+ {
|
||
|
+ // Track effect of input_put: preserve previous cursor/line_column
|
||
|
+ // until all of its characters are consumed.
|
||
|
+ if (--cursor_suspend_count == 0)
|
||
|
+ {
|
||
|
+ cursor_line = cursor_suspend_line;
|
||
|
+ cursor_column = cursor_suspend_column;
|
||
|
+ }
|
||
|
+ }
|
||
|
else
|
||
|
{
|
||
|
// update source cursor
|
||
|
@@ -714,12 +721,16 @@ lexer::input_get ()
|
||
|
|
||
|
|
||
|
void
|
||
|
-lexer::input_put (const string& chars)
|
||
|
+lexer::input_put (const string& chars, const token* t)
|
||
|
{
|
||
|
size_t pos = input_pointer - input_contents.data();
|
||
|
// clog << "[put:" << chars << " @" << pos << "]";
|
||
|
input_contents.insert (pos, chars);
|
||
|
cursor_suspend_count += chars.size();
|
||
|
+ cursor_suspend_line = cursor_line;
|
||
|
+ cursor_suspend_column = cursor_column;
|
||
|
+ cursor_line = t->location.line;
|
||
|
+ cursor_column = t->location.column;
|
||
|
input_pointer = input_contents.data() + pos;
|
||
|
input_end = input_contents.data() + input_contents.size();
|
||
|
}
|
||
|
@@ -731,19 +742,11 @@ lexer::scan (bool wildcard)
|
||
|
token* n = new token;
|
||
|
n->location.file = current_file;
|
||
|
|
||
|
- unsigned semiskipped_p = 0;
|
||
|
-
|
||
|
- skip:
|
||
|
+skip:
|
||
|
+ bool suspended = (cursor_suspend_count > 0);
|
||
|
n->location.line = cursor_line;
|
||
|
n->location.column = cursor_column;
|
||
|
|
||
|
- semiskip:
|
||
|
- if (semiskipped_p > 1)
|
||
|
- {
|
||
|
- input_get ();
|
||
|
- throw parse_error ("invalid nested substitution of command line arguments");
|
||
|
- }
|
||
|
-
|
||
|
int c = input_get();
|
||
|
// clog << "{" << (char)c << (char)c2 << "}";
|
||
|
if (c < 0)
|
||
|
@@ -762,38 +765,41 @@ lexer::scan (bool wildcard)
|
||
|
// characters; @1..@999 are quoted/escaped as strings.
|
||
|
// $# and @# expand to the number of arguments, similarly
|
||
|
// raw or quoted.
|
||
|
- if ((c == '$' || c == '@') &&
|
||
|
- (c2 == '#'))
|
||
|
+ if ((c == '$' || c == '@') && (c2 == '#'))
|
||
|
{
|
||
|
+ n->content.push_back (c);
|
||
|
+ n->content.push_back (c2);
|
||
|
input_get(); // swallow '#'
|
||
|
- stringstream converter;
|
||
|
- converter << session.args.size ();
|
||
|
- if (c == '$') input_put (converter.str());
|
||
|
- else input_put (lex_cast_qstring (converter.str()));
|
||
|
- semiskipped_p ++;
|
||
|
- goto semiskip;
|
||
|
+ if (suspended)
|
||
|
+ throw parse_error ("invalid nested substitution of command line arguments", n);
|
||
|
+ size_t num_args = session.args.size ();
|
||
|
+ input_put ((c == '$') ? lex_cast (num_args) : lex_cast_qstring (num_args), n);
|
||
|
+ n->content.clear();
|
||
|
+ goto skip;
|
||
|
}
|
||
|
- else if ((c == '$' || c == '@') &&
|
||
|
- (isdigit (c2)))
|
||
|
+ else if ((c == '$' || c == '@') && (isdigit (c2)))
|
||
|
{
|
||
|
+ n->content.push_back (c);
|
||
|
unsigned idx = 0;
|
||
|
do
|
||
|
{
|
||
|
input_get ();
|
||
|
idx = (idx * 10) + (c2 - '0');
|
||
|
+ n->content.push_back (c2);
|
||
|
c2 = input_peek ();
|
||
|
} while (c2 > 0 &&
|
||
|
isdigit (c2) &&
|
||
|
idx <= session.args.size()); // prevent overflow
|
||
|
+ if (suspended)
|
||
|
+ throw parse_error ("invalid nested substitution of command line arguments", n);
|
||
|
if (idx == 0 ||
|
||
|
idx-1 >= session.args.size())
|
||
|
throw parse_error ("command line argument index " + lex_cast(idx)
|
||
|
+ " out of range [1-" + lex_cast(session.args.size()) + "]", n);
|
||
|
- string arg = session.args[idx-1];
|
||
|
- if (c == '$') input_put (arg);
|
||
|
- else input_put (lex_cast_qstring (arg));
|
||
|
- semiskipped_p ++;
|
||
|
- goto semiskip;
|
||
|
+ const string& arg = session.args[idx-1];
|
||
|
+ input_put ((c == '$') ? arg : lex_cast_qstring (arg), n);
|
||
|
+ n->content.clear();
|
||
|
+ goto skip;
|
||
|
}
|
||
|
|
||
|
else if (isalpha (c) || c == '$' || c == '@' || c == '_' ||
|
||
|
diff --git a/parse.h b/parse.h
|
||
|
index 5587586..0ff8664 100644
|
||
|
--- a/parse.h
|
||
|
+++ b/parse.h
|
||
|
@@ -79,12 +79,14 @@ public:
|
||
|
private:
|
||
|
inline int input_get ();
|
||
|
inline int input_peek (unsigned n=0);
|
||
|
- void input_put (const std::string&);
|
||
|
+ void input_put (const std::string&, const token*);
|
||
|
std::string input_name;
|
||
|
std::string input_contents;
|
||
|
const char *input_pointer; // index into input_contents
|
||
|
const char *input_end;
|
||
|
unsigned cursor_suspend_count;
|
||
|
+ unsigned cursor_suspend_line;
|
||
|
+ unsigned cursor_suspend_column;
|
||
|
unsigned cursor_line;
|
||
|
unsigned cursor_column;
|
||
|
systemtap_session& session;
|
||
|
diff --git a/testsuite/parseko/preprocess16.stp b/testsuite/parseko/preprocess16.stp
|
||
|
new file mode 100755
|
||
|
index 0000000..364bad6
|
||
|
--- /dev/null
|
||
|
+++ b/testsuite/parseko/preprocess16.stp
|
||
|
@@ -0,0 +1,4 @@
|
||
|
+#! /bin/sh
|
||
|
+
|
||
|
+# recursive after the first token (PR11195)
|
||
|
+stap -p1 -e 'probe begin {$1}' 'x $1'
|