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] libcpp deferred pragma hack (PR c++/25294)


Hi!

This is fixed for real on the gomp-20050608-branch (and
redhat/gcc-4_1-branch), but I'm not sure if we want to change the pragma
handling this late in the 4.1 release cycle, so this patch is just a hack
that implements what Mark suggested in the bugzilla.  In addition to
fixing the multi-line C block comment at the end of pragma line it also
fixes crashes when literal '\0' character is present on the pragma line
(then ustrchr returns NULL and this GCC attempts to allocate almost 4GB
pragma saved string and if that succeeds, crashes while memcpying it).

Ok for 4.1?  Ok to commit the testcases alone to gomp-20050608-branch
(they already pass there), so that when the pragma fixes from gomp branch
are merged to the trunk, this will get fixed there?

2005-12-29  Jakub Jelinek  <jakub@redhat.com>

	PR c++/25294
	* directives.c (do_pragma): If pragma line ends with multi-line
	block comment, end the saved deferred pragma string before that
	comment.  Handle embedded '\0' chars on the pragma line.

	* gcc.dg/pragma-pack-3.c: New test.
	* g++.dg/parse/pragma3.C: New test.

--- libcpp/directives.c.jj	2005-10-28 23:38:53.000000000 +0200
+++ libcpp/directives.c	2005-12-29 12:01:50.000000000 +0100
@@ -1280,15 +1280,59 @@ do_pragma (cpp_reader *pfile)
 	  /* Squirrel away the pragma text.  Pragmas are
 	     newline-terminated. */
 	  const uchar *line_end;
-	  uchar *s;
+	  uchar *s, c, cc;
 	  cpp_string body;
 	  cpp_token *ptok;
 
-	  line_end = ustrchr (line_start, '\n');
+	  for (line_end = line_start; (c = *line_end) != '\n'; line_end++)
+	    if (c == '"' || c == '\'')
+	      {
+		/* Skip over string literal.  */
+		do
+		  {
+		    cc = *++line_end;
+		    if (cc == '\\' && line_end[1] != '\n')
+		      line_end++;
+		    else if (cc == '\n')
+		      {
+			line_end--;
+			break;
+		      }
+		  }
+		while (cc != c);
+	      }
+	    else if (c == '/')
+	      {
+		if (line_end[1] == '*')
+		  {
+		    /* Skip over C block comment, unless it is multi-line.
+		       When encountering multi-line block comment, terminate
+		       the pragma token right before that block comment.  */
+		    const uchar *le = line_end + 2;
+		    while (*le != '\n')
+		      if (*le++ == '*' && *le == '/')
+			{
+			  line_end = le;
+			  break;
+			}
+		    if (line_end < le)
+		      break;
+		  }
+		else if (line_end[1] == '/'
+			 && (CPP_OPTION (pfile, cplusplus_comments)
+			     || cpp_in_system_header (pfile)))
+		  {
+		    line_end += 2;
+		    while (*line_end != '\n')
+		      line_end++;
+		    break;
+		  }
+	      }
 
 	  body.len = (line_end - line_start) + 1;
 	  s = _cpp_unaligned_alloc (pfile, body.len + 1);
-	  memcpy (s, line_start, body.len);
+	  memcpy (s, line_start, body.len - 1);
+	  s[body.len - 1] = '\n';
 	  s[body.len] = '\0';
 	  body.text = s;
 
--- gcc/testsuite/gcc.dg/pragma-pack-3.c.jj	2005-12-29 11:42:33.000000000 +0100
+++ gcc/testsuite/gcc.dg/pragma-pack-3.c	2005-12-29 12:04:19.000000000 +0100
@@ -0,0 +1,27 @@
+/* PR c++/25294 */
+/* { dg-options "-std=gnu99" } */
+/* { dg-do run } */
+
+extern void abort (void);
+
+struct S
+{
+  char a[3];
+#pragma pack(1) /* A block comment
+		   that ends on the next line.  */
+  struct T
+  {
+    char b;
+    int c;
+  } d;
+#pragma pack /*/ */ () // C++ comment
+  int e;
+} s;
+
+int
+main ()
+{
+  if (sizeof (int) == 4 && sizeof (s) != 12)
+    abort ();
+  return 0;
+}
--- gcc/testsuite/g++.dg/parse/pragma3.C.jj	2005-12-29 11:40:12.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/pragma3.C	2005-12-29 11:44:53.000000000 +0100
@@ -0,0 +1,26 @@
+// PR c++/25294
+// { dg-do run }
+
+extern "C" void abort (void);
+
+struct S
+{
+  char a[3];
+#pragma pack(1) /* A block comment
+		   that ends on the next line.  */
+  struct T
+  {
+    char b;
+    int c;
+  } d;
+#pragma pack /*/ */ () // C++ comment
+  int e;
+} s;
+
+int
+main ()
+{
+  if (sizeof (int) == 4 && sizeof (s) != 12)
+    abort ();
+  return 0;
+}

	Jakub


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