update readline-8.3 patch 4 to work better in single-byte locales; fix for kill to make sure all processes in a job's pipeline get signalled; readline fixes to use size_t instead of int; make sure closing a file descriptor that was used for a redirection invalidates any buffered input used by the `read' builtin

This commit is contained in:
Chet Ramey committed 2026-10-30 14:57:22 -04:00
1 parent 5e427bb15d
commit a4a9dbc1b6
19 files changed
+161 -54

No files matched your search

+59
View File
@@ -13465,3 +13465,62 @@ trap.c
them after the action completes. Make sure to handle the case where
the trap action runs break or continue.
From a report by Dimitrios Christou <dimitrios.christou@skillonnet.com>
10/23
-----
lib/readline/display.c
- rl_redisplay: update fix from 5/19 to use _rl_last_c_pos in a single
byte locale and local_prompt_len otherwise
From https://bugs.gentoo.org/984299 via Kerin Millar <kfm@plushkava.net>
10/24
-----
jobs.c
- kill_pid: if we are killing a process or job in a situation where
we can't use killpg(), make sure to set p to p->next even if we
skip over a job because we think it's already terminated so we go
through all of the processes in the job's pipeline
Report and fix from Edgar MAGDELAINE <edgarmagdelaine@hotmail.fr>
10/27
-----
lib/sh/zread.c
- zfileno: keep track of the file descriptor most recently used for
local buffering in zreadc/zreadcintr/zreadn (everything that uses
lbuf/lused/lind)
- zcheckfd: new function, return true if the file descriptor passed as
an argument is the same as zfileno and with presumably buffered
data
- zreset: new function, break code that resets lused/lind/etc into
separate function, change callers
- zpurge: new function, reset any buffered or pushed input and unset
zfileno
externs.h
- zcheckfd, zpurge: new extern declarations
lib/readline/histexpand.c
- postproc_subst_rhs: use size_t for i, j, new_size
Report from Osvaldo J. Filho <janeri@gmail.com>
lib/readline/bind.c,
lib/readline/complete.c
lib/readline/display.c,
lib/readline/histexpand.c,
lib/readline/isearch.c,
lib/readline/kill.c,
lib/readline/macro.c,
lib/readline/util.c,
lib/readline/rlprivate.h
- make sure places and variables that maintain buffer or struct sizes
or count struct or buffer elements are size_t
10/30
-----
redir.c
- do_redirection_internal: in contexts where a file descriptor that
was the target of a redirection will be closed, check whether
that file descriptor was the last one used to read buffered input
with zreadc/zreadcintr/zreadn and invalidate the buffered data
if so
Report from Edgar MAGDELAINE <edgarmagdelaine@hotmail.fr>
+2 -1
View File
@@ -1,4 +1,4 @@
/* getopt.c - getopt for Bash. Used by the getopt builtin. */
/* getopt.c - getopt for Bash. Used by the getopts builtin. */
/* Copyright (C) 1993-2009,2022,2026 Free Software Foundation, Inc.
@@ -252,6 +252,7 @@ sh_getopt_save_istate (void)
ret->gs_curopt = sh_curopt;
ret->gs_nextchar = nextchar; /* XXX */
ret->gs_charindex = sh_charindex;
ret->gs_vcontext = variable_context; /* informational only */
ret->gs_flags = 0; /* XXX for later use */
return ret;
+1
View File
@@ -68,6 +68,7 @@ typedef struct sh_getopt_state
int gs_curopt;
char *gs_nextchar;
int gs_charindex;
int gs_vcontext;
int gs_flags;
} sh_getopt_state_t;
+2
View File
@@ -572,6 +572,8 @@ extern ssize_t zreadn (int, char *, size_t);
extern int zungetc (int);
extern void zreset (void);
extern void zsyncfd (int);
extern int zcheckfd (int);
extern void zpurge (int);
/* declarations for functions defined in lib/sh/zwrite.c */
extern int zwrite (int, char *, size_t);
+8 -5
View File
@@ -3999,11 +3999,14 @@ kill_pid (pid_t pid, int sig, int group)
p = jobs[job]->pipe;
do
{
if (PALIVE (p) == 0)
continue; /* avoid pid recycling problem */
kill (p->pid, sig);
if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
kill (p->pid, SIGCONT);
/* Don't bother killing processes we think have already
terminated, in case the pid has already been reused. */
if (PALIVE (p))
{
kill (p->pid, sig);
if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
kill (p->pid, SIGCONT);
}
p = p->next;
}
while (p != jobs[job]->pipe);
+5 -4
View File
@@ -1,6 +1,6 @@
/* bind.c -- key binding and startup file support for the readline library. */
/* Copyright (C) 1987-2024 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.
@@ -1231,7 +1231,7 @@ const char *rl_readline_name = "other";
/* Stack of previous values of parsing_conditionalized_out. */
static unsigned char *if_stack = (unsigned char *)NULL;
static int if_stack_depth;
static size_t if_stack_depth;
static size_t if_stack_size;
/* Push _rl_parsing_conditionalized_out, and set parser state based
@@ -1444,7 +1444,7 @@ parser_if (char *args)
static int
parser_else (char *args)
{
register int i;
size_t i;
if (if_stack_depth == 0)
{
@@ -2463,7 +2463,8 @@ rl_get_keymap_name (Keymap map)
int
rl_set_keymap_name (const char *name, Keymap map)
{
int i, ni, mi;
int ni, mi;
size_t i;
/* First check whether or not we're trying to rename a builtin keymap */
mi = _rl_get_keymap_by_map (map);
+6 -4
View File
@@ -1,6 +1,6 @@
/* complete.c -- filename completion for readline. */
/* 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.
@@ -1006,7 +1006,8 @@ fnprint (const char *to_print, int prefix_bytes, const char *real_pathname)
static int
print_filename (char *to_print, char *full_pathname, int prefix_bytes)
{
int printed_len, extension_char, slen, tlen;
int printed_len, extension_char;
size_t slen, tlen;
char *s, c, *new_full_pathname, *dn;
extension_char = 0;
@@ -1329,7 +1330,8 @@ static char **
remove_duplicate_matches (char **matches)
{
char *lowest_common;
int i, j, newlen;
int i, j;
size_t newlen;
char dead_slot;
char **temp_array;
@@ -1473,7 +1475,7 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text)
}
else
{
match_list[0] = (char *)xmalloc (low + 1);
match_list[0] = (char *)xmalloc ((size_t)low + 1);
/* XXX - this might need changes in the presence of multibyte chars */
+13 -8
View File
@@ -225,7 +225,7 @@ static int last_lmargin;
/* A buffer for `modeline' messages. */
static char *msg_buf = 0;
static int msg_bufsiz = 0;
static size_t msg_bufsiz = 0;
/* Non-zero forces the redisplay even if we thought it was unnecessary. */
static int forced_display;
@@ -357,7 +357,8 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
{
char *r, *ret, *p, *igstart, *nprompt, *ms;
int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
int mlen, newlines, newlines_guess, bound, can_add_invis, lastinvis;
int mlen, newlines, bound, can_add_invis, lastinvis;
size_t newlines_guess;
int mb_cur_max;
/* We only expand the mode string for the last line of a multiline prompt
@@ -365,8 +366,10 @@ expand_prompt (char *pmt, int flags, int *lp, int *lip, int *niflp, int *vlp)
ms = (((pmt == rl_prompt) ^ (flags & PMT_MULTILINE)) && _rl_show_mode_in_prompt) ? prompt_modestr (&mlen) : 0;
if (ms)
{
l = strlen (pmt);
nprompt = (char *)xmalloc (l + mlen + 1);
size_t newlen;
newlen = strlen (pmt) + mlen + 1;
nprompt = (char *)xmalloc (newlen);
memcpy (nprompt, ms, mlen);
strcpy (nprompt + mlen, pmt);
}
@@ -1510,9 +1513,11 @@ rl_redisplay (void)
/* cursor_bufpos is where the portion of the prompt that appears
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 + local_prompt_len;
(local_prompt + pmt_offset in multibyte mode, single-byte
locales use _rl_last_c_pos) */
cursor_bufpos = pmt_offset +
(mb_cur_max == 1 || rl_byte_oriented) ? _rl_last_c_pos : local_prompt_len;
if (local_prompt && local_prompt_invis_chars[cursor_linenum] &&
_rl_last_c_pos > 0 &&
cursor_bufpos <= prompt_last_invisible)
@@ -3265,7 +3270,7 @@ rl_restore_prompt (void)
char *
_rl_make_prompt_for_search (int pchar)
{
int len;
size_t len;
char *pmt, *p;
rl_save_prompt ();
+1 -1
View File
@@ -1,6 +1,6 @@
/* funmap.c -- attach names to functions. */
/* Copyright (C) 1987-2024 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.
+12 -11
View File
@@ -1,6 +1,6 @@
/* histexpand.c -- history expansion. */
/* Copyright (C) 1989-2021,2023-2025 Free Software Foundation, Inc.
/* Copyright (C) 1989-2021,2023-2026 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
@@ -337,7 +337,7 @@ quote_breaks (char *s)
{
register char *p, *r;
char *ret;
int len = 3;
size_t len = 3;
for (p = s; p && *p; p++, len++)
{
@@ -378,7 +378,7 @@ hist_error(const char *s, int start, int current, int errtype)
{
char *temp;
const char *emsg;
int ll, elen;
size_t ll, elen;
ll = current - start;
@@ -436,7 +436,7 @@ hist_error(const char *s, int start, int current, int errtype)
static char *
get_subst_pattern (const char *str, int *iptr, int delimiter, int is_rhs, int *lenptr)
{
register int si, i, j, k;
size_t si, i, j, k;
char *s;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps;
@@ -492,7 +492,7 @@ static void
postproc_subst_rhs (void)
{
char *new;
int i, j, new_size;
size_t i, j, new_size;
new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
for (i = j = 0; i < subst_rhs_len; i++)
@@ -529,10 +529,10 @@ postproc_subst_rhs (void)
static int
history_expand_internal (const char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line)
{
int i, n, starting_index;
int i, starting_index;
int substitute_globally, subst_bywords, want_quotes, print_only;
char *event, *temp, *result, *tstr, *t, c, *word_spec;
size_t result_len;
size_t n, result_len;
#if defined (HANDLE_MULTIBYTE)
mbstate_t ps;
@@ -783,7 +783,7 @@ history_expand_internal (const char *string, int start, int qc, int *end_index_p
if (STREQN (temp+si, subst_lhs, subst_lhs_len))
{
int len = subst_rhs_len - subst_lhs_len + l_temp;
size_t len = subst_rhs_len - subst_lhs_len + l_temp;
new_event = (char *)xmalloc (1 + len);
strncpy (new_event, temp, si);
strncpy (new_event + si, subst_rhs, subst_rhs_len);
@@ -1170,7 +1170,8 @@ history_expand (const char *hstring, char **output)
}
else if (dquote == 0 && history_quotes_inhibit_expansion)
{
int quote, slen;
int quote;
size_t slen;
flag = (i > 0 && string[i - 1] == '$');
quote = i++;
@@ -1620,8 +1621,8 @@ get_word:
static char *
history_substring (const char *string, int start, int end)
{
register int len;
register char *result;
size_t len;
char *result;
len = end - start;
result = (char *)xmalloc (len + 1);
+1 -1
View File
@@ -1,6 +1,6 @@
/* histfile.c - functions to manipulate the history file. */
/* Copyright (C) 1989-2019,2023-2025 Free Software Foundation, Inc.
/* Copyright (C) 1989-2019,2023-2026 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
+2 -2
View File
@@ -6,7 +6,7 @@
/* */
/* **************************************************************** */
/* Copyright (C) 1987-2021,2023,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.
@@ -72,7 +72,7 @@ static void _rl_isearch_fini (_rl_search_cxt *);
/* Last search string and its length. */
static char *last_isearch_string;
static int last_isearch_string_len;
static size_t last_isearch_string_len;
static char * const default_isearch_terminators = "\033\012";
+3 -3
View File
@@ -1,6 +1,6 @@
/* kill.c -- kill ring management. */
/* Copyright (C) 1994-2025 Free Software Foundation, Inc.
/* Copyright (C) 1994-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.
@@ -91,7 +91,7 @@ static int
_rl_copy_to_kill_ring (char *text, int append)
{
char *old, *new;
int slot;
size_t slot;
/* First, find the slot to work with. */
if (_rl_last_command_was_kill == 0 || rl_kill_ring == 0)
@@ -111,7 +111,7 @@ _rl_copy_to_kill_ring (char *text, int append)
slot = rl_kill_ring_length;
if (slot == rl_max_kills)
{
register int i;
int i;
xfree (rl_kill_ring[0]);
for (i = 0; i < slot; i++)
rl_kill_ring[i] = rl_kill_ring[i + 1];
+3 -3
View File
@@ -1,6 +1,6 @@
/* macro.c -- keyboard macros for readline. */
/* Copyright (C) 1994-2009,2017 Free Software Foundation, Inc.
/* Copyright (C) 1994-2009,2017,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.
@@ -62,7 +62,7 @@
char *rl_executing_macro = (char *)NULL;
/* The offset in the above string to the next character to be read. */
static int executing_macro_index;
static size_t executing_macro_index;
/* The current macro string being built. Characters get stuffed
in here by add_macro_char (). */
@@ -72,7 +72,7 @@ static char *current_macro = (char *)NULL;
static size_t current_macro_size;
/* The index at which characters are being added to current_macro. */
static int current_macro_index;
static size_t current_macro_index;
/* A structure used to save nested macro strings.
It is a linked list of string/index for each saved macro. */
+3 -3
View File
@@ -1,7 +1,7 @@
/* rlprivate.h -- functions and variables global to the readline library,
but not intended for use by applications. */
/* Copyright (C) 1999-2025 Free Software Foundation, Inc.
/* Copyright (C) 1999-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.
@@ -75,8 +75,8 @@ typedef struct __rl_search_context
int sflags;
char *search_string;
int search_string_index;
int search_string_size;
size_t search_string_index;
size_t search_string_size;
char **lines;
char *allocated_line;
+1 -1
View File
@@ -717,7 +717,7 @@ _rl_insert_char (int count, int c)
register int i;
char *string;
#ifdef HANDLE_MULTIBYTE
int string_size;
size_t string_size;
char incoming[MB_LEN_MAX + 1];
int incoming_length = 0;
mbstate_t ps_back;
+3 -3
View File
@@ -147,7 +147,7 @@ rl_tty_status (int count, int key)
char *
rl_copy_text (int from, int to)
{
register int length;
size_t length;
char *copy;
/* Fix it if the caller is confused. */
@@ -180,9 +180,9 @@ rl_extend_line_buffer (int len)
int
rl_tilde_expand (int ignore, int key)
{
register int start, end;
int start, end;
char *homedir, *temp;
int len;
size_t len;
end = rl_point;
start = end - 1;
+23 -4
View File
@@ -200,6 +200,7 @@ zreadintr (int fd, char *buf, size_t len)
static char lbuf[ZBUFSIZ];
static size_t lind, lused;
static int zfileno = -1; /* fd associated with latest read into lbuf */
ssize_t
zreadc (int fd, char *cp)
@@ -223,6 +224,7 @@ zreadc (int fd, char *cp)
return nr;
}
lused = nr;
zfileno = fd;
}
if (cp)
*cp = lbuf[lind++];
@@ -253,6 +255,7 @@ zreadcintr (int fd, char *cp)
return nr;
}
lused = nr;
zfileno = fd;
}
if (cp)
*cp = lbuf[lind++];
@@ -285,6 +288,7 @@ zreadn (int fd, char *cp, size_t len)
return nr;
}
lused = nr;
zfileno = fd;
}
if (cp)
*cp = lbuf[lind++];
@@ -331,8 +335,23 @@ zsyncfd (int fd)
r = lseek (fd, -off, SEEK_CUR);
if (r != -1)
{
lused = lind = 0;
zpushind = zpopind = 0;
}
zreset ();
}
/* Return true if FD is the same as ZFILENO, the file descriptor associated
with the most recent call to one of the read functions above that populates
LBUF */
int
zcheckfd (int fd)
{
return (zfileno >= 0 && fd == zfileno);
}
/* Throw away buffered data associated with FD. The caller should have already
made sure that FD == ZFILENO by calling zcheckfd() */
void
zpurge (int fd)
{
zreset ();
zfileno = -1;
}
+13
View File
@@ -1051,6 +1051,10 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
if (ri == r_input_direction || ri == r_input_output)
duplicate_buffered_stream (fd, redirector);
if (ri == r_input_direction || ri == r_input_output)
if (zcheckfd (redirector))
zpurge (redirector);
/*
* If we're remembering, then this is the result of a while, for
* or until loop with a loop redirection, or a function/builtin
@@ -1221,6 +1225,10 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
if (ri == r_duplicating_input || ri == r_move_input)
duplicate_buffered_stream (redir_fd, redirector);
if (ri == r_duplicating_input || ri == r_move_input)
if (zcheckfd (redirector))
zpurge (redirector);
/* First duplicate the close-on-exec state of redirectee. dup2
leaves the flag unset on the new descriptor, which means it
stays open. Only set the close-on-exec bit for file descriptors
@@ -1257,6 +1265,8 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
#if defined (COPROCESS_SUPPORT)
coproc_fdchk (redir_fd); /* XXX - loses coproc fds */
#endif
if (zcheckfd (redir_fd))
zpurge (redir_fd);
}
}
break;
@@ -1291,6 +1301,9 @@ do_redirection_internal (REDIRECT *redirect, int flags, char **fnp)
check_bash_input (redirector);
r = close_buffered_fd (redirector);
if (zcheckfd (redirector))
zpurge (redirector);
if (r < 0 && (rflags & RX_INTERNAL) && (errno == EIO || errno == ENOSPC))
REDIRECTION_ERROR (r, errno, -1);
}