[Bug preprocessor/67046] [10/11/12/13 Regression] Segmentation fault when a preprocessor directive follows the argument to _Pragma

lhyatt at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Jan 13 22:36:00 GMT 2023


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67046

Lewis Hyatt <lhyatt at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lhyatt at gcc dot gnu.org

--- Comment #4 from Lewis Hyatt <lhyatt at gcc dot gnu.org> ---
By default, libcpp reuses token buffers whenever it begins a new line.
get__Pragma_string() in directives.cc doesn't account for this, and so the
string token it obtains is overwritten by the paren token if the paren token is
not on the same line. If the no-op directive is removed as in:

=======
_Pragma(
"message(\"msg\")"
)
=======

Then it ends up returning a "weird" string token with type set to
CPP_CLOSE_PAREN, but with still-valid string contents because the lexing of a
paren token does not touch the rest of the data. So by chance it all ends up
working. But interposing an empty directive there makes it not to work, the
string contents get cleared out and destringize_and_run() ends up seeing a
string token with length 0 which it does not expect and calls alloca() with -1.

The fix is just to use the existing keep_tokens mechanism to avoid invalidating
the token. I am testing this patch now and will follow up.

diff --git a/libcpp/directives.cc b/libcpp/directives.cc
index 9dc4363c65a..15de1826373 100644
--- a/libcpp/directives.cc
+++ b/libcpp/directives.cc
@@ -1840,7 +1840,7 @@ get_token_no_padding (cpp_reader *pfile)
 /* Check syntax is "(string-literal)".  Returns the string on success,
    or NULL on failure.  */
 static const cpp_token *
-get__Pragma_string (cpp_reader *pfile)
+get__Pragma_string_1 (cpp_reader *pfile)
 {
   const cpp_token *string;
   const cpp_token *paren;
@@ -1868,6 +1868,17 @@ get__Pragma_string (cpp_reader *pfile)
   return string;
 }

+/* Make sure we don't invalidate the string token, if the parenthesis
+   ended up on a different line.  */
+static const cpp_token *
+get__Pragma_string (cpp_reader *pfile)
+{
+  ++pfile->keep_tokens;
+  const auto result = get__Pragma_string_1 (pfile);
+  --pfile->keep_tokens;
+  return result;
+}
+
 /* Destringize IN into a temporary buffer, by removing the first \ of
    \" and \\ sequences, and process the result as a #pragma directive.  */
 static void


More information about the Gcc-bugs mailing list