git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] add -p: avoid use of undefined $key when ReadKey -> EOF

From
Junio C Hamano <gitster@pobox.com>
Date
Nov 28, 2021, 19:44 UTC
Message-ID
<xmqq8rx85ala.fsf@gitster.g>
In-Reply-To
<20211128174903.5623-1-carenas@gmail.com>
Carlo Marcelo Arenas Belón  <carenas@gmail.com> writes:
Show 9 quoted lines
> b5cc003253 (add -i: ignore terminal escape sequences, 2011-05-17)
> add an additional check to the original code to better handle keys
> for escape sequences, but failed to account for the possibility
> the first ReadKey call returned undef (ex: stdin closes) and that
> was being handled fine by the original code in ca6ac7f135 (add -p:
> prompt for single characters, 2009-02-05)
>
> Add a test for undefined and encapsulate the loop and the original
> print that relied on it within it.

I wondered where a change to t/ directory was, but we are not talking about that kind of test ;-) OK.

Show 36 quoted lines
> After this, the following command (in a suitable repository state)
> wouldn't print any error:
>
>   $ git -c interactive.singleKey add -p </dev/null
>
> Signed-off-by: Carlo Marcelo Arenas Belón <carenas@gmail.com>
> ---
>  git-add--interactive.perl | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/git-add--interactive.perl b/git-add--interactive.perl
> index bc3a1e8eff..95887fd8e5 100755
> --- a/git-add--interactive.perl
> +++ b/git-add--interactive.perl
> @@ -1175,15 +1175,17 @@ sub prompt_single_character {
>  		ReadMode 'cbreak';
>  		my $key = ReadKey 0;
>  		ReadMode 'restore';
> -		if ($use_termcap and $key eq "\e") {
> -			while (!defined $term_escapes{$key}) {
> -				my $next = ReadKey 0.5;
> -				last if (!defined $next);
> -				$key .= $next;
> +		if (defined $key) {
> +			if ($use_termcap and $key eq "\e") {
> +				while (!defined $term_escapes{$key}) {
> +					my $next = ReadKey 0.5;
> +					last if (!defined $next);
> +					$key .= $next;
> +				}
> +				$key =~ s/\e/^[/;
>  			}
> -			$key =~ s/\e/^[/;
> +			print "$key";
>  		}
> -		print "$key" if defined $key;

This was from the very original and was a strong clue that $key could be undef; well spotted.

>  		print "\n";
>  		return $key;
>  	} else {

Essentially, the code added by b5cc0032 (add -i: ignore terminal escape sequences, 2011-05-17) wanted to say

    The original code
    - called ReadKey and took its output in $key, 
    - echoed it if it was defined (otherwise $key wasn't echoed),
    - emitted a line feed,
    - and returned $key.
    We deal with the case where a single keystroke of some keys is
    delivered to us as an escape sequence of multiple "key"s from
    ReadKey, and the way we do so is to replace that single ReadKey
    with the new code that accumulates these multiple "key"s in
    $key.

I am undecided, but the minimum patch below seems to makes the above intention in the updated code clearer.

diff --git i/git-add--interactive.perl w/git-add--interactive.perl
index bc3a1e8eff..c459c675e7 100755
--- i/git-add--interactive.perl
+++ w/git-add--interactive.perl
@@ -1175,7 +1175,7 @@ sub prompt_single_character {
 		ReadMode 'cbreak';
 		my $key = ReadKey 0;
 		ReadMode 'restore';
-		if ($use_termcap and $key eq "\e") {
+		if (defined $key && $use_termcap and $key eq "\e") {
 			while (!defined $term_escapes{$key}) {
 				my $next = ReadKey 0.5;
 				last if (!defined $next);
Previous: Carlo Marcelo Arenas BelónNext: Carlo Arenas
Message 2 of 4 in “add -p: avoid use of undefined $key when ReadKey -> EOF”
  1. add -p: avoid use of undefined $key when ReadKey -> EOFCarlo Marcelo Arenas Belón, Nov 28, 2021
  2. Junio C HamanoNov 28, 2021
  3. Carlo ArenasNov 28, 2021
  4. Junio C HamanoNov 28, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.