From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id kDBdLaGpBmaF4hoAWB0awg (envelope-from ) for ; Fri, 29 Mar 2024 07:44:33 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IL2aVMbr; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id B5AA51E0C0; Fri, 29 Mar 2024 07:44:33 -0400 (EDT) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id A29DE1E030 for ; Fri, 29 Mar 2024 07:44:31 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 40D2B3858D37 for ; Fri, 29 Mar 2024 11:44:31 +0000 (GMT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 025313858C36 for ; Fri, 29 Mar 2024 11:44:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 025313858C36 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 025313858C36 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711712645; cv=none; b=quFNNNdOyj/MuxuQ0i8ZD4j1gb7x3dgAPjrFmsIrCqf4wvNfeEWQ56Z3mfs/bSZ6YRWhSvZDkTB5vuGqkTULPDTNbwrKcLxAlaauA0z62JA51DFOuuwadyI8jymv7+IWMHRe2miDCOs/0QvdV6owDw2dfxlHfHKpDcnCM5tWm9o= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711712645; c=relaxed/simple; bh=O05KYAyiAA9TDGPDjBFvAl+HbznTvFTyHPxL4WjjskA=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=QJ3xAcaY+gqVMiYbGysoO8jJA1UHDApm2QtCrJFcD9R9m8ZLrc1ocFChqWwrd3Woy3o6W5WIT4CxKrbtYTftnajpUjx6sM50ldkXeA1q+GLAROkWCb8WvhvOLgU7aViX/Ey0YvBIewj+3TSnmPYhgx0UHuDR3RiQnOA9bDpp7MM= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1711712641; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9OFQf6c/NiIg3Fp+I3EYGzy1L+TBbcHj69SmfoVh9NI=; b=IL2aVMbrJIbDhINGdVOOiLpvN7dNas6l9A6DgR4ajF0lBSahIewnb5FXLqqo6Lk75QnIQd Q/70EKramXmF4cJk6+UU+psIjUPV03qSK49laa4Cvm9r2BbVFEHL38dXeVOGuRAZNQYZw8 Zz7I+24s7vNKiy9skPNUo6ArLg7dsWM= Received: from mail-lf1-f69.google.com (mail-lf1-f69.google.com [209.85.167.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-688-7jO6i-00OtKKZ8yNX9qtxw-1; Fri, 29 Mar 2024 07:42:43 -0400 X-MC-Unique: 7jO6i-00OtKKZ8yNX9qtxw-1 Received: by mail-lf1-f69.google.com with SMTP id 2adb3069b0e04-515c94f9ea8so1086182e87.1 for ; Fri, 29 Mar 2024 04:42:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711712561; x=1712317361; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9OFQf6c/NiIg3Fp+I3EYGzy1L+TBbcHj69SmfoVh9NI=; b=qM6GqhMewlIm4maiObmDaDazoxH/EQx+xJ2ozBoFLbkQWYWVYH+2W2vzxgijiLB60x Absi0qpjS5B0gLk+V3kWpj6iwCSIgrn9kWqwKibMojrwWYSTpMU8sxaXZxyg82dCEDx7 QIubR7S+1YikLjMmvuIkOeXO84kLrTHdSR8USEVwCwiSfQLLauV9cxCii9m2NlKSf9/5 xGFUlCC2fd/qghYG9qM/UAP1ESMECA4SHWQNtjoQ1YVGSxQentWpgLSzgVWcpmQgpU0d 8l2eCBfkWnZyO1gGCMx0Ws7gZHqAMMwIejLlIG07sr0I5zBFK34FH6G31f22LgWPyuoU azUw== X-Gm-Message-State: AOJu0YzJk5wECn3ONqVByjkeasG9hdwKLmEGFlZganV5n7v3mOhWa2Bl k3Y34tXhwD2XJ3JcZX898YlPb5uWgSClJ6BHszgMxWREdEXQhOPjLGICy15pXQnJxU0mDJielb3 NT6rcx5eDgBPhzEZOHnFDOhpBNuPEsraP+cOdvdVvMZpJst3OwLjLpGoXZypiwpnXNpsRQybDcO E6n+TIaVAxUf8TPY+35AvZMM/0pku6YqlVktWPIo20KTg= X-Received: by 2002:a05:6512:475:b0:515:cf44:904e with SMTP id x21-20020a056512047500b00515cf44904emr1308297lfd.46.1711712561551; Fri, 29 Mar 2024 04:42:41 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEaWjo66ZwxFlu5r+0GmtdRRfH8Q4c20lC/spZ1+ouKLHUjW00Z5y+8l8W78uC9WngPyiYYKw== X-Received: by 2002:a05:6512:475:b0:515:cf44:904e with SMTP id x21-20020a056512047500b00515cf44904emr1308285lfd.46.1711712561081; Fri, 29 Mar 2024 04:42:41 -0700 (PDT) Received: from localhost (185.223.159.143.dyn.plus.net. [143.159.223.185]) by smtp.gmail.com with ESMTPSA id ef15-20020a05640228cf00b0056c1380a972sm1911388edb.74.2024.03.29.04.42.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Mar 2024 04:42:40 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH 5/6] gdb: apply escaping to filenames in 'complete' results Date: Fri, 29 Mar 2024 11:42:31 +0000 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org 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 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