]> sourceware.org Git - systemtap.git/commitdiff
PR11195: Prevent all nested argument substitution
authorJosh Stone <jistone@redhat.com>
Tue, 19 Jan 2010 23:36:35 +0000 (15:36 -0800)
committerJosh Stone <jistone@redhat.com>
Wed, 20 Jan 2010 01:01:35 +0000 (17:01 -0800)
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.

parse.cxx
parse.h
testsuite/parseko/preprocess16.stp [new file with mode: 0755]

index edb192751f5e5e2272df817e3e3a191fedf2fc8b..2688d6db3b44ef9cca29439730dcecfb0ca1fb24 100644 (file)
--- 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 5587586ec564d95e3c9264fd0fd5cf7708330b3f..0ff8664c0069b2be4a88c08afc3f14a46f8460dd 100644 (file)
--- 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 (executable)
index 0000000..364bad6
--- /dev/null
@@ -0,0 +1,4 @@
+#! /bin/sh
+
+# recursive after the first token (PR11195)
+stap -p1 -e 'probe begin {$1}' 'x $1'
This page took 0.17441 seconds and 5 git commands to generate.