fix potential crash with invalid readline key binding command; fix crash caused by signal cleanup after using ^G to abort out of listing possible completions

This commit is contained in:
Chet Ramey committed 2026-11-06 12:00:10 -05:00
1 parent a4a9dbc1b6
commit f7043f647e
6 files changed
+63 -8

No files matched your search

+24
View File
@@ -13524,3 +13524,27 @@ redir.c
with zreadc/zreadcintr/zreadn and invalidate the buffered data
if so
Report from Edgar MAGDELAINE <edgarmagdelaine@hotmail.fr>
11/4
----
lib/readline/bind.c
- rl_generic_bind: make sure to cast prevkey to unsigned char because
we use it as an index into a keymap
Report and fix from Can Ozkan <can.ozkan@esat.kuleuven.be>
11/6
----
lib/readline/complete.c
- _rl_abort_completion: new function, fakes a signal to clean up the
saved match list state, then calls _rl_abort_internal
- get_y_or_n: if we read ^G or get a read error, return -1 and let
the caller handle it instead of calling _rl_abort_internal()
- _rl_internal_pager, display_matches: if get_y_or_n returns -1, call
_rl_abort_completion to clean up the completion state and longjmp
back to reading input
Report from Sergio Herreros <sergioherrerosp@gmail.com>
lib/readline/util.c,lib/readline/rlprivate.h
- _rl_abort_internal: now a void function with noreturn attribute;
changed callers to accommodate
+4
View File
@@ -87,4 +87,8 @@ extern void setup_history_ignore (const char *);
extern char *last_history_line (void);
#ifdef BASH_SYSLOG_HISTORY
extern void bash_syslog_history (const char *);
#endif
#endif /* _BASHHIST_H_ */
+6 -1
View File
@@ -410,7 +410,12 @@ rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
}
prevmap = map;
prevkey = keys[0];
prevkey = (unsigned char)keys[0];
if (prevkey >= KEYMAP_SIZE)
{
xfree (keys);
return -1;
}
/* Bind keys, making new keymaps as necessary. */
for (i = 0; i < keys_len; i++)
+25 -3
View File
@@ -129,6 +129,7 @@ static int path_isdir (const char *);
static char *rl_quote_filename (char *, int, char *);
static void _rl_complete_sigcleanup (int, void *);
static void _rl_abort_completion (void) __attribute__((noreturn));
static void set_completion_defaults (int);
static int get_y_or_n (int);
@@ -540,6 +541,19 @@ _rl_complete_sigcleanup (int sig, void *ptr)
}
}
static void
_rl_abort_completion ()
{
if (_rl_sigcleanup && _rl_sigcleanup == _rl_complete_sigcleanup)
{
_rl_sigcleanup (SIGINT, _rl_sigcleanarg);
_rl_sigcleanup = 0;
_rl_sigcleanarg = 0;
}
_rl_complete_display_matches_interrupt = 0;
_rl_abort_internal ();
}
/************************************/
/* */
/* Completion utility functions */
@@ -611,7 +625,7 @@ get_y_or_n (int for_pager)
if (c == 'n' || c == 'N' || c == RUBOUT)
return (0);
if (c == ABORT_CHAR || c < 0)
_rl_abort_internal ();
return -1;
if (for_pager && (c == NEWLINE || c == RETURN))
return (2);
if (for_pager && (c == 'q' || c == 'Q'))
@@ -643,6 +657,11 @@ _rl_internal_pager (int lines)
n = _rl_screenheight / 2;
return (lines > n) ? (lines - n) : -1;
}
else if (i < 0)
{
_rl_abort_completion ();
return 0;
}
else
return 0;
}
@@ -1812,14 +1831,17 @@ display_matches (char **matches)
rl_crlf ();
fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
fflush (rl_outstream);
if ((completion_y_or_n = get_y_or_n (0)) == 0)
if ((completion_y_or_n = get_y_or_n (0)) <= 0)
{
rl_crlf ();
rl_forced_update_display ();
rl_display_fixed = 1;
return;
if (completion_y_or_n < 0)
_rl_abort_completion ();
else
return;
}
}
+1 -1
View File
@@ -516,7 +516,7 @@ extern void _rl_audit_tty (char *);
extern int _rl_tropen (void);
extern int _rl_abort_internal (void);
extern void _rl_abort_internal (void) __attribute__((noreturn));
extern int _rl_null_function (int, int);
extern char *_rl_strindex (const char *, const char *);
extern int _rl_strcaseeqn (const char *, const char *, size_t, int);
+3 -3
View File
@@ -95,7 +95,7 @@ _rl_walphabetic (WCHAR_T wc)
#endif
/* How to abort things. */
int
void
_rl_abort_internal (void)
{
if (RL_ISSTATE (RL_STATE_TIMEOUT) == 0)
@@ -115,13 +115,13 @@ _rl_abort_internal (void)
_rl_command_to_execute = 0;
_rl_longjmp (_rl_top_level, 1);
return (0);
}
int
rl_abort (int count, int key)
{
return (_rl_abort_internal ());
_rl_abort_internal ();
return 0;
}
int