summaryrefslogtreecommitdiffstats
path: root/parse.cxx
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2010-01-19 15:36:35 -0800
committerJosh Stone <jistone@redhat.com>2010-01-19 17:01:35 -0800
commit9300f661214a4f4dfac75878485867b30c7db389 (patch)
tree7d1408669fb7bd5fa648edbbd33707a7e8b094d0 /parse.cxx
parent596bbda30fd116c2d45c155ad347cc2d27186f3c (diff)
downloadsystemtap-steved-9300f661214a4f4dfac75878485867b30c7db389.tar.gz
systemtap-steved-9300f661214a4f4dfac75878485867b30c7db389.tar.xz
systemtap-steved-9300f661214a4f4dfac75878485867b30c7db389.zip
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.
Diffstat (limited to 'parse.cxx')
-rw-r--r--parse.cxx66
1 files changed, 36 insertions, 30 deletions
diff --git a/parse.cxx b/parse.cxx
index edb19275..2688d6db 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 == '_' ||