This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] libcpp deferred pragma hack (PR c++/25294)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, Mark Mitchell <mark at codesourcery dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 29 Dec 2005 06:34:46 -0500
- Subject: [PATCH] libcpp deferred pragma hack (PR c++/25294)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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