This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: PR preprocessor/29966


This patch fixes PR preprocessor/29966.

If you valgrind cpp on the test case included in the PR, you'll see
that some invalid writes; and in some cases this can cause an ICE.

The problem occurs because _cpp_create_definition saves and restores
cur_token; but create_iso_definition calls _cpp_lex_token, which may
(and in the bug, does) require allocating a new tokenrun.  In this
situation _cpp_create_definition restores cur_token to an invalid
value.

I chose to fix this by changing lex_expansion_token to save and
restore cur_token.  This seemed like a good approach because it moves
the save/restore logic to the narrowest scope possible.  (Another
possible approach would be to change create_iso_definition to use
_cpp_lex_direct instead of _cpp_lex_token.)

I added an assertion to _cpp_lex_token to check what I think is an
assumption it makes, namely that cur_token lies at a valid position
within the current token run.

I'm not sure what to do about the test case here.  It will trigger the
new assertion but the test case is dependent on the size of various
buffers in cpp -- so maybe it isn't a reliable-enough regression test.
Also, the test case is rather large and hard to reduce, and I was
wondering if we would need a copyright assignment in order to check it
in.

Bootstrapped & regression tested on x86 FC6.  I verified that it fixes
the bug using valgrind.

Ok?

Tom

:ADDPATCH preprocessor:

2006-12-29  Tom Tromey  <tromey@redhat.com>

	PR preprocessor/29966:
	* macro.c (lex_expansion_token): Save and restore cpp_reader's
	cur_token.
	(_cpp_create_definition): Don't restore cur_token here.
	* lex.c (_cpp_lex_token): Added assertion.

Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c	(revision 120244)
+++ libcpp/macro.c	(working copy)
@@ -1,6 +1,7 @@
 /* Part of CPP library.  (Macro and #define handling.)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -1398,10 +1408,12 @@
 static cpp_token *
 lex_expansion_token (cpp_reader *pfile, cpp_macro *macro)
 {
-  cpp_token *token;
+  cpp_token *token, *saved_cur_token;
 
+  saved_cur_token = pfile->cur_token;
   pfile->cur_token = alloc_expansion_token (pfile, macro);
   token = _cpp_lex_direct (pfile);
+  pfile->cur_token = saved_cur_token;
 
   /* Is this a parameter?  */
   if (token->type == CPP_NAME
@@ -1590,18 +1602,12 @@
     ok = _cpp_create_trad_definition (pfile, macro);
   else
     {
-      cpp_token *saved_cur_token = pfile->cur_token;
-
       ok = create_iso_definition (pfile, macro);
 
-      /* Restore lexer position because of games lex_expansion_token()
-	 plays lexing the macro.  We set the type for SEEN_EOL() in
-	 directives.c.
+      /* We set the type for SEEN_EOL() in directives.c.
 
 	 Longer term we should lex the whole line before coming here,
 	 and just copy the expansion.  */
-      saved_cur_token[-1].type = pfile->cur_token[-1].type;
-      pfile->cur_token = saved_cur_token;
 
       /* Stop the lexer accepting __VA_ARGS__.  */
       pfile->state.va_args_ok = 0;
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c	(revision 120244)
+++ libcpp/lex.c	(working copy)
@@ -754,6 +754,11 @@
 	  pfile->cur_run = next_tokenrun (pfile->cur_run);
 	  pfile->cur_token = pfile->cur_run->base;
 	}
+      /* We assume that the current token is somewhere in the current
+	 run.  */
+      if (pfile->cur_token < pfile->cur_run->base
+	  || pfile->cur_token >= pfile->cur_run->limit)
+	abort ();
 
       if (pfile->lookaheads)
 	{


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]