remove the [ and ] prompt expansions from prompt strings that are not used with readline; fix some redisplay issues when readline does not start in column 0; fix memory leak in unquoted $@ expansion; fix readline redisplay issue after SIGWINCH shrinks the terminal size; fix issue with mapfile that can cause crashes if a callback unsets the array mapfile is using

This commit is contained in:
Chet Ramey
2026-06-02 10:01:54 -04:00
parent 2d4ba0c618
commit 1e9f5e10b2
14 changed files with 123 additions and 36 deletions
+55
View File
@@ -12938,3 +12938,58 @@ subst.c
after they return by adding an unwind-protect function
uw_restore_verbose()
Report and patch from Grisha Levit <grishalevit@gmail.com>
5/18
----
doc/bash.1,doc/bashref.texi
- note that PS0 and PS4 are not fed to readline, so they shouldn't
contain the \[ and \] prompt escapes
parse.y
- decode_prompt_string: if we're decoding a prompt string (is_prompt == 1),
ignore \[ and \] unless the prompt is PS1 or PS2.
Report from Egmont Koblinger <egmont@gmail.com>
5/19
----
lib/readline/display.c
- rl_redisplay: when deciding whether or not to reprint the prompt from
column 0 because the cursor is before the last invisible character,
use local_prompt_len to compute index into the buffer in a multibyte
locale, since _rl_last_c_pos is a screen position. This still doesn't
fix the eventual redisplay breakage if readline starts with the
cursor somewhere other than column 0
Fixes issue reported by Lennart Ackermans <lennart@ackermans.ch>
5/20
----
builtins/getopt.c
examples/loadables/seq.c
lib/sh/mbschr.c,lib/sh/utf8.c
pathexp.c
examples/loadables/seq.c
- fixes for `const' and gcc 15
Report and patch from Grisha Levit <grishalevit@gmail.com>
5/21
----
subst.c
- string_list_dollar_atstar: fix memory leak by calling dispose_words(l2)
after the call to word_list_split(l2)
Report from Grisha Levit <grishalevit@gmail.com>
5/22
----
lib/readline/display.c
- _rl_redisplay_after_sigwinch: call _rl_reset_prompt every time, so
the local_prompt_invis_chars array gets updated along with the
local_prompt_newlines array
Report and fix from Félix Bouynot <felix.bouynot@setenforce.one>
5/25
----
builtins/mapfile.def
- mapfile: the callback can leave the variable in an inconsistent
state, or even unset it, so we use bind_array_variable to look it
up again every time through the loop
Report and patch from Philippe Grégoire <git@pgregoire.xyz>
+3 -2
View File
@@ -1,6 +1,6 @@
/* getopt.c - getopt for Bash. Used by the getopt builtin. */
/* Copyright (C) 1993-2009,2022 Free Software Foundation, Inc.
/* Copyright (C) 1993-2009,2022,2026 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -113,7 +113,8 @@ int sh_badopt = 0;
int
sh_getopt (int argc, char *const *argv, const char *optstring)
{
char c, *temp;
char c;
const char *temp;
sh_optarg = 0;
+8 -5
View File
@@ -153,9 +153,7 @@ mapfile (int fd, long line_count_goal, long origin, long nskip, long callback_qu
line_length = 0;
unbuffered_read = 0;
/* The following check should be done before reading any lines. Doing it
here allows us to call bind_array_element instead of bind_array_variable
and skip the variable lookup on every call. */
/* The following check should be done before reading any lines. */
entry = builtin_find_indexed_array (array_name, flags & MAPF_CLEARARRAY);
if (entry == 0)
return EXECUTION_FAILURE;
@@ -201,8 +199,13 @@ mapfile (int fd, long line_count_goal, long origin, long nskip, long callback_qu
run_callback (callback, array_index, line);
}
/* XXX - bad things can happen if the callback modifies ENTRY, e.g.,
unsetting it or changing it to a non-indexed-array type. */
/* Bad things can happen if the callback modifies ENTRY, e.g.,
unsetting it or changing it to a non-indexed-array type, so we
look it up again every time we need to assign something */
entry = bind_array_variable (array_name, array_index, line, 0);
if (entry == 0 || ASSIGN_DISALLOWED (entry, 0))
return EXECUTION_FAILURE;
bind_array_element (entry, array_index, line, 0);
/* Have we exceeded # of lines to store? */
+11 -5
View File
@@ -5,7 +5,7 @@
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
.\" Last Change: Wed May 6 16:08:33 EDT 2026
.\" Last Change: Mon May 18 11:35:35 EDT 2026
.\"
.\" For bash_builtins, strip all but "SHELL BUILTIN COMMANDS" section
.\" For rbash, strip all but "RESTRICTED SHELL" section
@@ -22,7 +22,7 @@
.ds zX \" empty
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2026 May 6" "GNU Bash 5.3"
.TH BASH 1 "2026 May 18" "GNU Bash 5.3"
.\"
.ie \n(.g \{\
.ds ' \(aq
@@ -4328,7 +4328,8 @@ is invalid,
.B bash
prints a message to standard error indicating failure,
does not perform the substitution,
and does not execute the command associated with the expansion.
and does not
continue to execute the command in which the error occurs.
.SS Process Substitution
\fIProcess substitution\fP allows a process's input or output to be
referred to using a filename.
@@ -4336,7 +4337,9 @@ It takes the form of
\fB<(\fP\fIlist\^\fP\fB)\fP
or
\fB>(\fP\fIlist\^\fP\fB)\fP.
The process \fIlist\fP is run asynchronously, and its input or output
The process \fIlist\fP,
as long as it is not a null command without redirections,
is run asynchronously, and its input or output
appears as a filename.
This filename is
passed as an argument to the current command as the result of the
@@ -6628,9 +6631,12 @@ A backslash.
.B \e[
Begin a sequence of non-printing characters, which could be used to
embed a terminal control sequence into the prompt.
This escape is only useful when the prompt will be supplied to
\fBreadline\fP, so it shouldn't be used in \fBPS0\fP or \fBPS4\fP.
.TP
.B \e]
End a sequence of non-printing characters.
End a sequence of non-printing characters begun with
.BR \e[ .
.PD
.RE
.PP
+9 -3
View File
@@ -2997,7 +2997,8 @@ The evaluation is performed according to the rules listed below
If the expression is invalid, Bash prints a message indicating
failure to the standard error,
does not perform the substitution,
and does not execute the command associated with the expansion.
and does not
continue to execute the command in which the error occurs.
@node Process Substitution
@subsection Process Substitution
@@ -3015,7 +3016,9 @@ or
>(@var{list})
@end example
@noindent
The process @var{list} is run asynchronously, and its input or output
The process @var{list},
as long as it is not a null command without redirections,
is run asynchronously, and its input or output
appears as a filename.
This filename is
passed as an argument to the current command as the result of the
@@ -9154,8 +9157,11 @@ A backslash.
Begin a sequence of non-printing characters.
This could be used to
embed a terminal control sequence into the prompt.
This escape is only useful when the prompt will be supplied to
Readline, so it shouldn't be used in @env{PS0} or @env{PS4}.
@item \]
End a sequence of non-printing characters.
End a sequence of non-printing characters begun with @samp{\[}
@end table
The command number and the history number are usually different:
+2 -2
View File
@@ -2,10 +2,10 @@
Copyright (C) 1988-2026 Free Software Foundation, Inc.
@end ignore
@set LASTCHANGE Wed May 6 16:08:14 EDT 2026
@set LASTCHANGE Mon May 18 11:35:01 EDT 2026
@set EDITION 5.3
@set VERSION 5.3
@set UPDATED 6 May 2026
@set UPDATED 18 May 2026
@set UPDATED-MONTH May 2026
+2
View File
@@ -615,6 +615,8 @@ char *cut_doc[] = {
"processes to successive elements of ARRAY, beginning at 0. The",
"strings cut assigns to ARRAY are identical to the strings it would",
"write to the standard output if -a were not supplied.",
"",
"-s stops printing of lines not containing delimiters. -n is ignored.",
(char *)NULL
};
+2 -2
View File
@@ -1,5 +1,5 @@
/* seq - print sequence of numbers to standard output.
Copyright (C) 2018-2022 Free Software Foundation, Inc.
Copyright (C) 2018-2026 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -171,7 +171,7 @@ static int
getprec (const char *numbuf)
{
int p;
char *dp;
const char *dp;
if (dp = strchr (numbuf, decimal_point))
dp++; /* skip over decimal point */
+5 -9
View File
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
This file is part of the GNU Readline Library (Readline), a library
for reading lines of text with interactive input and history editing.
@@ -1497,7 +1497,6 @@ rl_redisplay (void)
the characters from the current cursor position. But we
only need to reprint it if the cursor is before the last
invisible character in the prompt string. */
/* XXX - why not use local_prompt_len? */
nleft = prompt_visible_length + wrap_offset;
if (cursor_linenum == prompt_last_screen_line)
{
@@ -1509,11 +1508,7 @@ rl_redisplay (void)
on the current screen line begins in the buffer. It is a
buffer position, an index into curline
(local_prompt + pmt_offset) */
cursor_bufpos = pmt_offset;
if (mb_cur_max == 1 || rl_byte_oriented)
cursor_bufpos += _rl_last_c_pos;
else
cursor_bufpos += _rl_last_c_pos + curline_invchars;
cursor_bufpos = pmt_offset + local_prompt_len;
if (local_prompt && local_prompt_invis_chars[cursor_linenum] &&
_rl_last_c_pos > 0 &&
@@ -3525,8 +3520,9 @@ _rl_redisplay_after_sigwinch (void)
else
rl_crlf ();
if (_rl_screenwidth < prompt_visible_length)
_rl_reset_prompt (); /* update local_prompt_newlines array */
/* Let expand_prompt() update local_prompt_newlines and local_prompt_invis_chars
arrays */
_rl_reset_prompt ();
/* Redraw only the last line of a multi-line prompt. */
t = strrchr (rl_display_prompt, '\n');
+2 -2
View File
@@ -1,6 +1,6 @@
/* mbschr.c - strchr(3) that handles multibyte characters. */
/* Copyright (C) 2002 Free Software Foundation, Inc.
/* Copyright (C) 2002-2026 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -81,5 +81,5 @@ mbschr (const char *s, int c)
}
else
#endif
return (strchr (s, c));
return ((char *)strchr (s, c));
}
+2 -2
View File
@@ -1,6 +1,6 @@
/* utf8.c - UTF-8 character handling functions */
/* Copyright (C) 2018, 2022 Free Software Foundation, Inc.
/* Copyright (C) 2018, 2022, 2026 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -35,7 +35,7 @@ extern int locale_utf8locale;
char *
utf8_mbschr (const char *s, int c)
{
return strchr (s, c); /* for now */
return (char *)strchr (s, c); /* for now */
}
int
+1 -1
View File
@@ -6632,7 +6632,7 @@ decode_prompt_string (char *string, int is_prompt)
#if defined (READLINE)
case '[':
case ']':
if (no_line_editing)
if (no_line_editing || (is_prompt && decoding_prompt != ps1_prompt && decoding_prompt != ps2_prompt))
{
string++;
break;
+2 -2
View File
@@ -1,6 +1,6 @@
/* pathexp.c -- The shell interface to the globbing library. */
/* Copyright (C) 1995-2024 Free Software Foundation, Inc.
/* Copyright (C) 1995-2024,2026 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -525,7 +525,7 @@ static int
glob_name_is_acceptable (const char *name)
{
struct ign *p;
char *n;
const char *n;
int flags;
/* . and .. are never matched. We extend this to the terminal component of a
+19 -1
View File
@@ -3167,6 +3167,8 @@ string_list_dollar_atstar (WORD_LIST *list, int quoted, int flags)
don't want here. */
l = word_list_split (l2); /* pre-split, preserving empty arguments */
dispose_words (l2);
/* We want to turn words that are QUOTED_NULL with W_HASQUOTEDNULL set in
the word flags back into "" but leave every other $'\177' alone. */
for (l2 = l; l2; l2 = l2->next)
@@ -3183,7 +3185,6 @@ string_list_dollar_atstar (WORD_LIST *list, int quoted, int flags)
free (sep);
#endif
dispose_words (l2);
dispose_words (l);
return ret;
@@ -8905,6 +8906,23 @@ get_var_and_type (char *varname, char *value, array_eltstate_t *estatep, int quo
*valp = temp ? savestring (temp) : temp;
}
}
#if 0 /* TAG:bash-5.4 2026/05/11 YourLi@outlook.com */
/* For ksh93 compatibility, ${!ref} where ref is a non-special, nameref
variable, should expand to the value of ref, without resolving any
nameref chain. Previous versions treated an array variable without a
subscript the same as ref[0] (next clause). */
else if (shell_compatibility_level > 53 &&
want_indir && value && vtype == VT_VARIABLE &&
SPECIAL_VAR (varname, 1) == 0 &&
(v = find_variable_noref (varname + 1)) &&
nameref_p (v))
{
/* This is for compatibility with ksh93. */
vtype = VT_VARIABLE;
*varp = v;
*valp = savestring (value);
}
#endif
else if ((v = find_variable (vname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
{
vtype = VT_ARRAYMEMBER;