public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCH 5/6] gdb: apply escaping to filenames in 'complete' results
Date: Fri, 29 Mar 2024 11:42:31 +0000	[thread overview]
Message-ID: <d7e83a30a256ad0c3790e044c4e9189f43d2a88d.1711712401.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1711712401.git.aburgess@redhat.com>

Building on the mechanism added in the previous commit(s), this commit
applies escaping to filenames in the 'complete' command output.
Consider a file: /tmp/xxx/aa"bb -- that is a filename that contains a
double quote, currently the 'complete' command output looks like this:

  (gdb) complete file /tmp/xxx/a
  file /tmp/xxx/aa"bb

Notice that the double quote in the output is not escaped.  If we
passed this same output back to GDB then the double quote will be
treated as the start of a string.

After this commit then the output looks like this:

  (gdb) complete file /tmp/xxx/a
  file /tmp/xxx/aa\"bb

The double quote is now escaped.  If we feed this output back to GDB
then GDB will treat this as a single filename that contains a double
quote, exactly what we want.

To achieve this I've done a little refactoring, splitting out the core
of gdb_completer_file_name_quote, and then added a new call from the
filename_match_formatter function.

There are updates to the tests to cover this new functionality.
---
 gdb/completer.c                               | 35 ++++++--
 .../gdb.base/filename-completion.exp          | 89 +++++++++++--------
 2 files changed, 80 insertions(+), 44 deletions(-)

diff --git a/gdb/completer.c b/gdb/completer.c
index 785fb09b4d7..710c8c206cb 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -305,24 +305,24 @@ gdb_completer_file_name_dequote (char *filename, int quote_char)
   return strdup (tmp.c_str ());
 }
 
-/* Apply character escaping to the file name in TEXT.  QUOTE_PTR points to
-   the quote character surrounding TEXT, or points to the null-character if
-   there are no quotes around TEXT.  MATCH_TYPE will be one of the readline
-   constants SINGLE_MATCH or MULTI_MATCH depending on if there is one or
-   many completions.  */
+/* Apply character escaping to the filename in TEXT and return a newly
+   allocated buffer containing the possibly updated filename.
+
+   QUOTE_CHAR is the quote character surrounding TEXT, or the
+   null-character if there are no quotes around TEXT.  */
 
 static char *
-gdb_completer_file_name_quote (char *text, int match_type, char *quote_ptr)
+gdb_completer_file_name_quote_1 (const char *text, char quote_char)
 {
   std::string str;
 
-  if (*quote_ptr == '\'')
+  if (quote_char == '\'')
     {
       /* There is no backslash escaping permitted within a single quoted
 	 string, so in this case we can just return the input sting.  */
       str = text;
     }
-  else if (*quote_ptr == '"')
+  else if (quote_char == '"')
     {
       /* Add escaping for a double quoted filename.  */
       for (const char *input = text;
@@ -351,6 +351,18 @@ gdb_completer_file_name_quote (char *text, int match_type, char *quote_ptr)
   return strdup (str.c_str ());
 }
 
+/* Apply character escaping to the filename in TEXT.  QUOTE_PTR points to
+   the quote character surrounding TEXT, or points to the null-character if
+   there are no quotes around TEXT.  MATCH_TYPE will be one of the readline
+   constants SINGLE_MATCH or MULTI_MATCH depending on if there is one or
+   many completions.  */
+
+static char *
+gdb_completer_file_name_quote (char *text, int match_type, char *quote_ptr)
+{
+  return gdb_completer_file_name_quote_1 (text, *quote_ptr);
+}
+
 /* The function is used to update the completion word MATCH before
    displaying it to the user in the 'complete' command output, this
    particular function is only used when MATCH has been supplied by the
@@ -370,7 +382,12 @@ filename_match_formatter (const char *match, char quote_char)
   struct stat finfo;
   const bool isdir = (stat (expanded.c_str (), &finfo) == 0
 		      && S_ISDIR (finfo.st_mode));
-  std::string result (match);
+
+  gdb::unique_xmalloc_ptr<char> quoted_match
+    (gdb_completer_file_name_quote_1 (match, quote_char));
+
+  std::string result (quoted_match.get ());
+
   if (isdir)
     result += "/";
   else
diff --git a/gdb/testsuite/gdb.base/filename-completion.exp b/gdb/testsuite/gdb.base/filename-completion.exp
index d7c99e1340d..f8a48269528 100644
--- a/gdb/testsuite/gdb.base/filename-completion.exp
+++ b/gdb/testsuite/gdb.base/filename-completion.exp
@@ -70,10 +70,22 @@ proc test_gdb_complete_filename_multiple {
 	    $add_completed_line $completion_list $max_completions $testname
     }
 
-    if { $start_quote_char eq "" && $end_quote_char ne "" } {
+    if { $start_quote_char eq "" } {
 	set updated_completion_list {}
 
 	foreach entry $completion_list {
+	    # If ENTRY is quoted with double quotes, then any double
+	    # quotes within the entry need to be escaped.
+	    if { $end_quote_char eq "\"" } {
+		regsub -all "\"" $entry "\\\"" entry
+	    }
+
+	    if { $end_quote_char eq "" } {
+		regsub -all " " $entry "\\ " entry
+		regsub -all "\"" $entry "\\\"" entry
+		regsub -all "'" $entry "\\'" entry
+	    }
+
 	    if {[string range $entry end end] ne "/"} {
 		set entry $entry$end_quote_char
 	    }
@@ -128,47 +140,54 @@ proc run_tests { root } {
 	    } "" "${qc}" false \
 	    "expand mixed directory and file names"
 
-	# GDB does not currently escape word break characters
-	# (e.g. white space) correctly in unquoted filenames.
 	if { $qc ne "" } {
 	    set sp " "
-
-	    test_gdb_complete_filename_multiple "file ${qc}${root}/aaa/" \
-		"a" "a${sp}" {
-		    "aa bb"
-		    "aa cc"
-		} "" "${qc}" false \
-		"expand filenames containing spaces"
-
-	    test_gdb_complete_filename_multiple "file ${qc}${root}/bb1/" \
-		"a" "a" {
-		    "aa\"bb"
-		    "aa'bb"
-		} "" "${qc}" false \
-		"expand filenames containing quotes"
 	} else {
 	    set sp "\\ "
+	}
 
-	    test_gdb_complete_tab_multiple "file ${qc}${root}/aaa/a" \
-		"a${sp}" {
-		    "aa bb"
-		    "aa cc"
-		} false \
-		"expand filenames containing spaces"
-
-	    test_gdb_complete_tab_multiple "file ${qc}${root}/bb1/a" \
-		"a" {
-		    "aa\"bb"
-		    "aa'bb"
-		} false \
-		"expand filenames containing quotes"
-
-	    test_gdb_complete_tab_unique "file ${qc}${root}/bb1/aa\\\"" \
-		"file ${qc}${root}/bb1/aa\\\\\"bb${qc}" " " \
+	if { $qc eq "'" } {
+	    set dq "\""
+	    set dq_re "\""
+	} else {
+	    set dq "\\\""
+	    set dq_re "\\\\\""
+	}
+
+	test_gdb_complete_filename_multiple "file ${qc}${root}/aaa/" \
+	    "a" "a${sp}" {
+		"aa bb"
+		"aa cc"
+	    } "" "${qc}" false \
+	    "expand filenames containing spaces"
+
+	test_gdb_complete_filename_multiple "file ${qc}${root}/bb1/" \
+	    "a" "a" {
+		"aa\"bb"
+		"aa'bb"
+	    } "" "${qc}" false \
+	    "expand filenames containing quotes"
+
+	test_gdb_complete_tab_unique "file ${qc}${root}/bb1/aa${dq}" \
+	    "file ${qc}${root}/bb1/aa${dq_re}bb${qc}" " " \
 	    "expand unique filename containing double quotes"
 
-	    test_gdb_complete_tab_unique "file ${qc}${root}/bb1/aa\\'" \
-		"file ${qc}${root}/bb1/aa\\\\'bb${qc}" " " \
+	# It is not possible to include a single quote character
+	# within a single quoted string.  However, GDB does not do
+	# anything smart if a user tries to do this.  Avoid testing
+	# this case.  Maybe in the future we'll figure a way to avoid
+	# this situation.
+	if { $qc ne "'" } {
+	    if { $qc eq "" } {
+		set sq "\\'"
+		set sq_re "\\\\'"
+	    } else {
+		set sq "'"
+		set sq_re "'"
+	    }
+
+	    test_gdb_complete_tab_unique "file ${qc}${root}/bb1/aa${sq}" \
+		"file ${qc}${root}/bb1/aa${sq_re}bb${qc}" " " \
 		"expand unique filename containing single quote"
 	}
     }
-- 
2.25.4


  parent reply	other threads:[~2024-03-29 11:44 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-29 11:42 [PATCH 0/6] Further filename completion improvements Andrew Burgess
2024-03-29 11:42 ` [PATCH 1/6] gdb: improve escaping when completing filenames Andrew Burgess
2024-03-30 23:48   ` Lancelot SIX
2024-03-29 11:42 ` [PATCH 2/6] gdb: move display of completion results into completion_result class Andrew Burgess
2024-03-29 12:14   ` Eli Zaretskii
2024-03-30 23:30     ` Lancelot SIX
2024-03-31  5:49       ` Eli Zaretskii
2024-04-12 17:24         ` Andrew Burgess
2024-04-12 18:42           ` Eli Zaretskii
2024-04-12 22:20             ` Andrew Burgess
2024-04-13  6:36               ` Eli Zaretskii
2024-04-13  9:09                 ` Andrew Burgess
2024-04-13  9:46                   ` Eli Zaretskii
2024-04-12 17:31       ` Andrew Burgess
2024-03-29 11:42 ` [PATCH 3/6] gdb: simplify completion_result::print_matches Andrew Burgess
2024-03-30 23:48   ` Lancelot SIX
2024-03-29 11:42 ` [PATCH 4/6] gdb: add match formatter mechanism for 'complete' command output Andrew Burgess
2024-03-30 23:49   ` Lancelot SIX
2024-03-31  5:55     ` Eli Zaretskii
2024-04-12 17:42       ` Andrew Burgess
2024-04-12 18:44         ` Eli Zaretskii
2024-04-12 22:29           ` Andrew Burgess
2024-04-13  6:39             ` Eli Zaretskii
2024-03-29 11:42 ` Andrew Burgess [this message]
2024-03-29 11:42 ` [PATCH 6/6] gdb: improve gdb_rl_find_completion_word for quoted words Andrew Burgess
2024-04-20  9:10 ` [PATCHv2 0/8] Further filename completion improvements Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 1/8] gdb/doc: document how filename arguments are formatted Andrew Burgess
2024-04-20  9:44     ` Eli Zaretskii
2024-04-27 10:01       ` Andrew Burgess
2024-04-27 10:06         ` Eli Zaretskii
2024-04-29  9:10           ` Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 2/8] gdb: split apart two different types of filename completion Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 3/8] gdb: improve escaping when completing filenames Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 4/8] gdb: move display of completion results into completion_result class Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 5/8] gdb: simplify completion_result::print_matches Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 6/8] gdb: add match formatter mechanism for 'complete' command output Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 7/8] gdb: apply escaping to filenames in 'complete' results Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 8/8] gdb: improve gdb_rl_find_completion_word for quoted words Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d7e83a30a256ad0c3790e044c4e9189f43d2a88d.1711712401.git.aburgess@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).