From fec573408310139e1ffc42741fbe46b4f2947592 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 12 Nov 2020 17:27:28 -0500 Subject: [PATCH] jit: fix string escaping This patch fixes a bug in recording::string::make_debug_string in which '\t' and '\n' were "escaped" by simply prepending a '\', thus emitting '\' then '\n', rather than '\' then 'n'. It also removes a hack that determined if a string is to be escaped by checking for a leading '"', by instead adding a flag. gcc/jit/ChangeLog: * jit-recording.c (recording::context::new_string): Add "escaped" param and use it when creating the new recording::string instance. (recording::string::string): Add "escaped" param and use it to initialize m_escaped. (recording::string::make_debug_string): Replace check that first char is double-quote with use of m_escaped. Fix escaping of '\t' and '\n'. Set "escaped" on the result. * jit-recording.h (recording::context::new_string): Add "escaped" param. (recording::string::string): Add "escaped" param. (recording::string::m_escaped): New field. gcc/testsuite/ChangeLog: * jit.dg/test-debug-strings.c (create_code): Add tests of string literal escaping. --- gcc/jit/jit-recording.c | 39 ++++++++++++++++------- gcc/jit/jit-recording.h | 9 ++++-- gcc/testsuite/jit.dg/test-debug-strings.c | 20 ++++++++++++ 3 files changed, 55 insertions(+), 13 deletions(-) diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 3cbeba0f371..3a84c1fc5c0 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -724,12 +724,12 @@ recording::context::disassociate_from_playback () This creates a fresh copy of the given 0-terminated buffer. */ recording::string * -recording::context::new_string (const char *text) +recording::context::new_string (const char *text, bool escaped) { if (!text) return NULL; - recording::string *result = new string (this, text); + recording::string *result = new string (this, text, escaped); record (result); return result; } @@ -1954,8 +1954,9 @@ recording::memento::write_to_dump (dump &d) /* Constructor for gcc::jit::recording::string::string, allocating a copy of the given text using new char[]. */ -recording::string::string (context *ctxt, const char *text) - : memento (ctxt) +recording::string::string (context *ctxt, const char *text, bool escaped) +: memento (ctxt), + m_escaped (escaped) { m_len = strlen (text); m_buffer = new char[m_len + 1]; @@ -2005,9 +2006,9 @@ recording::string::from_printf (context *ctxt, const char *fmt, ...) recording::string * recording::string::make_debug_string () { - /* Hack to avoid infinite recursion into strings when logging all - mementos: don't re-escape strings: */ - if (m_buffer[0] == '"') + /* Avoid infinite recursion into strings when logging all mementos: + don't re-escape strings: */ + if (m_escaped) return this; /* Wrap in quotes and do escaping etc */ @@ -2024,15 +2025,31 @@ recording::string::make_debug_string () for (size_t i = 0; i < m_len ; i++) { char ch = m_buffer[i]; - if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"') - APPEND('\\'); - APPEND(ch); + switch (ch) + { + default: + APPEND(ch); + break; + case '\t': + APPEND('\\'); + APPEND('t'); + break; + case '\n': + APPEND('\\'); + APPEND('n'); + break; + case '\\': + case '"': + APPEND('\\'); + APPEND(ch); + break; + } } APPEND('"'); /* closing quote */ #undef APPEND tmp[len] = '\0'; /* nil termintator */ - string *result = m_ctxt->new_string (tmp); + string *result = m_ctxt->new_string (tmp, true); delete[] tmp; return result; diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index 30e37aff387..9a43a7bf33a 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -74,7 +74,7 @@ public: void disassociate_from_playback (); string * - new_string (const char *text); + new_string (const char *text, bool escaped = false); location * new_location (const char *filename, @@ -414,7 +414,7 @@ private: class string : public memento { public: - string (context *ctxt, const char *text); + string (context *ctxt, const char *text, bool escaped); ~string (); const char *c_str () { return m_buffer; } @@ -431,6 +431,11 @@ private: private: size_t m_len; char *m_buffer; + + /* Flag to track if this string is the result of string::make_debug_string, + to avoid infinite recursion when logging all mementos: don't re-escape + such strings. */ + bool m_escaped; }; class location : public memento diff --git a/gcc/testsuite/jit.dg/test-debug-strings.c b/gcc/testsuite/jit.dg/test-debug-strings.c index e515a176257..03ef3370d94 100644 --- a/gcc/testsuite/jit.dg/test-debug-strings.c +++ b/gcc/testsuite/jit.dg/test-debug-strings.c @@ -178,6 +178,26 @@ create_code (gcc_jit_context *ctxt, void *user_data) "((struct node *)ptr->next)->next"); } + /* Check string literal escaping. */ + { + CHECK_RVALUE_DEBUG_STRING + (gcc_jit_context_new_string_literal (ctxt, ""), + "\"\""); + CHECK_RVALUE_DEBUG_STRING + (gcc_jit_context_new_string_literal (ctxt, "foo"), + "\"foo\""); + CHECK_RVALUE_DEBUG_STRING + (gcc_jit_context_new_string_literal (ctxt, "\""), + "\"\\\"\""); + CHECK_RVALUE_DEBUG_STRING + (gcc_jit_context_new_string_literal (ctxt, "line 1\nline 2\n"), + "\"line 1\\nline 2\\n\""); + CHECK_RVALUE_DEBUG_STRING + (gcc_jit_context_new_string_literal (ctxt, "foo\tbar"), + "\"foo\\tbar\""); + } + +#undef CHECK_RVALUE_DEBUG_STRING #undef CHECK_LVALUE_DEBUG_STRING } -- 2.30.2