From a23c863e755dd862cb9e723f7d85578346e450a5 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 9 Jul 2025 16:33:00 -0400 Subject: [PATCH] fix for crash when executing PROMPT_COMMAND; fix for readline crash when rl_save_prompt is not followed by rl_set_prompt; fix for bash C-xg key binding listing completions; fix for precision overflow issue in printf; fix for readline non-multibyte builds --- CWRU/CWRU.chlog | 49 ++++++++++++++++++++++++++++++++++++ array.h | 2 +- bashline.c | 2 +- builtins/printf.def | 2 +- configure | 20 +++++++-------- configure.ac | 2 +- eval.c | 8 +++--- input.h | 2 +- lib/readline/display.c | 2 +- lib/readline/doc/rltech.texi | 5 +++- lib/readline/mbutil.c | 4 ++- parse.y | 8 +++--- pcomplete.c | 4 --- 13 files changed, 81 insertions(+), 29 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 3f25c008..fc1002cf 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -11295,3 +11295,52 @@ parse.y --- tests/printf7.sub,tests/exec3.sub - changes to compensate for some system differences (macos/Linux/BSD) + + 7/6 + --- +parse.y,input.h + - execute_variable_command: takes an additional FLAGS argument; right + now only takes one value. If FLAGS != 0, we save and restore the + parser state + +eval.c,array.h + - execute_array_command: takes an additional flags argument to pass to + execute_variable_command for each array element + - execute_prompt_command: call execute_array_command or execute_variable_command + with 0 as the appropriate flags argument, since we don't need to + save and restore the parser state at the point we're calling this + Fixes bug reported by Carl Johnson + +lib/readline/display.c + - WRAP_OFFSET: make sure local_prompt_invis_chars is non-null before + dereferencing it + Fixes bug reported by Tobias Powalowski + + 7/7 + --- +lib/readline/mbutil.c + - Make sure _rl_mb_strcaseeqn and _rl_mb_charcasecmp are protected by + HAVE_MULTIBYTE + Report from Bernd Kuhls + +lib/readline/doc/rltech.texi + - rl_complete_internal: document that the `?' specifier will insert a + single completion if the last completion failed, and that `|' will + display possible completions unconditionally. + +bashline.c + - bash_glob_list_expansions: use `|' to force listing possible + completions even in the presence of a single completion after previous + completion failure + Based on report from A4-Tacks + +lib/readline/mbutil.c + - _rl_utf8_mblen: accept 4-byte UTF-8 characters beginning with 0xF4 + Report from Collin Funk + + 7/8 + --- +builtins/printf.def + - printstr: only adjust precision if the decoded precision is >= 0, + since decodeint returns -1 on overflow/failure + diff --git a/array.h b/array.h index 47712e88..169584a5 100644 --- a/array.h +++ b/array.h @@ -177,6 +177,6 @@ extern arrayind_t element_back (ARRAY *, arrayind_t); #define ALL_ELEMENT_SUB(c) ((c) == '@' || (c) == '*') /* In eval.c, but uses ARRAY * */ -extern int execute_array_command (ARRAY *, void *); +extern int execute_array_command (ARRAY *, void *, int); #endif /* _ARRAY_H_ */ diff --git a/bashline.c b/bashline.c index c6039844..776fe64b 100644 --- a/bashline.c +++ b/bashline.c @@ -4090,7 +4090,7 @@ bash_glob_expand_word (int count, int key) static int bash_glob_list_expansions (int count, int key) { - return bash_glob_completion_internal ('?'); + return bash_glob_completion_internal ('|'); } static int diff --git a/builtins/printf.def b/builtins/printf.def index 142c5bdf..3c4335c4 100644 --- a/builtins/printf.def +++ b/builtins/printf.def @@ -914,7 +914,7 @@ printstr (char *fmt, char *string, size_t len, int fieldwidth, int precision) pr = decodeint (&fmt, 1, -1); /* pr < precision means we adjusted precision in printf_builtin for the quoted string length (%Q), so we use the adjusted value */ -#if 0 /*TAG:bash-5.4 20250702 */ +#if 1 /*TAG:bash-5.4 20250702 */ if (pr >= 0 && pr < precision) #else if (pr < precision) diff --git a/configure b/configure index f71ebc5d..a7aa8ba5 100755 --- a/configure +++ b/configure @@ -1,7 +1,7 @@ #! /bin/sh # From configure.ac for Bash 5.3, version 5.080. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for bash 5.3-rc2. +# Generated by GNU Autoconf 2.72 for bash 5.3-maint. # # Report bugs to . # @@ -605,8 +605,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bash' PACKAGE_TARNAME='bash' -PACKAGE_VERSION='5.3-rc2' -PACKAGE_STRING='bash 5.3-rc2' +PACKAGE_VERSION='5.3-maint' +PACKAGE_STRING='bash 5.3-maint' PACKAGE_BUGREPORT='bug-bash@gnu.org' PACKAGE_URL='' @@ -1468,7 +1468,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures bash 5.3-rc2 to adapt to many kinds of systems. +'configure' configures bash 5.3-maint to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1534,7 +1534,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bash 5.3-rc2:";; + short | recursive ) echo "Configuration of bash 5.3-maint:";; esac cat <<\_ACEOF @@ -1742,7 +1742,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bash configure 5.3-rc2 +bash configure 5.3-maint generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -2420,7 +2420,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bash $as_me 5.3-rc2, which was +It was created by bash $as_me 5.3-maint, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -3219,7 +3219,7 @@ ac_config_headers="$ac_config_headers config.h buildconf.h" BASHVERS=5.3 -RELSTATUS=rc2 +RELSTATUS=maint case "$RELSTATUS" in alp*|bet*|dev*|rc*|releng*|maint*) DEBUG='-DDEBUG' MALLOC_DEBUG='-DMALLOC_DEBUG' ;; @@ -23814,7 +23814,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bash $as_me 5.3-rc2, which was +This file was extended by bash $as_me 5.3-maint, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -23882,7 +23882,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -bash config.status 5.3-rc2 +bash config.status 5.3-maint configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 846e55ab..497cdb7f 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ dnl Process this file with autoconf to produce a configure script. AC_REVISION([for Bash 5.3, version 5.080])dnl define(bashvers, 5.3) -define(relstatus, rc2) +define(relstatus, maint) AC_INIT([bash], bashvers-relstatus, [bug-bash@gnu.org]) diff --git a/eval.c b/eval.c index bbf5d88b..e0a5da96 100644 --- a/eval.c +++ b/eval.c @@ -283,7 +283,7 @@ send_pwd_to_eterm (void) #if defined (ARRAY_VARS) /* Caller ensures that A has a non-zero number of elements */ int -execute_array_command (ARRAY *a, void *v) +execute_array_command (ARRAY *a, void *v, int flags) { char *tag; char **argv; @@ -295,7 +295,7 @@ execute_array_command (ARRAY *a, void *v) for (i = 0; i < argc; i++) { if (argv[i] && argv[i][0]) - execute_variable_command (argv[i], tag); + execute_variable_command (argv[i], tag, flags); } strvec_dispose (argv); return 0; @@ -318,7 +318,7 @@ execute_prompt_command (void) if (array_p (pcv)) { if ((pcmds = array_cell (pcv)) && array_num_elements (pcmds) > 0) - execute_array_command (pcmds, "PROMPT_COMMAND"); + execute_array_command (pcmds, "PROMPT_COMMAND", 0); return; } else if (assoc_p (pcv)) @@ -327,7 +327,7 @@ execute_prompt_command (void) command_to_execute = value_cell (pcv); if (command_to_execute && *command_to_execute) - execute_variable_command (command_to_execute, "PROMPT_COMMAND"); + execute_variable_command (command_to_execute, "PROMPT_COMMAND", 0); } /* Call the YACC-generated parser and return the status of the parse. diff --git a/input.h b/input.h index 592b6cb9..f0c2cfc4 100644 --- a/input.h +++ b/input.h @@ -99,7 +99,7 @@ extern int stream_on_stack (enum stream_type); extern char *read_secondary_line (int); extern int find_reserved_word (const char *); extern void gather_here_documents (void); -extern void execute_variable_command (const char *, const char *); +extern void execute_variable_command (const char *, const char *, int); extern int *save_token_state (void); extern void restore_token_state (int *); diff --git a/lib/readline/display.c b/lib/readline/display.c index 9aa8c7b5..edb525d3 100644 --- a/lib/readline/display.c +++ b/lib/readline/display.c @@ -783,7 +783,7 @@ _rl_optimize_redisplay (void) /* Useful shorthand used by rl_redisplay, update_line, rl_move_cursor_relative */ #define INVIS_FIRST() (local_prompt_invis_chars[0]) -#define WRAP_OFFSET(line, offset) ((line <= prompt_last_screen_line) ? local_prompt_invis_chars[line] : 0) +#define WRAP_OFFSET(line, offset) ((line <= prompt_last_screen_line && local_prompt_invis_chars) ? local_prompt_invis_chars[line] : 0) #define W_OFFSET(line, offset) ((line) == 0 ? offset : 0) #define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l])) diff --git a/lib/readline/doc/rltech.texi b/lib/readline/doc/rltech.texi index c8965ef6..ccf74277 100644 --- a/lib/readline/doc/rltech.texi +++ b/lib/readline/doc/rltech.texi @@ -2098,7 +2098,10 @@ Readline. @deftypefun int rl_complete_internal (int what_to_do) Complete the word at or before point. @var{what_to_do} says what to do with the completion. -A value of @samp{?} means list the possible completions. +A value of @samp{?} means list the possible completions, +but to insert a single completion if the last completion failed to find +any matches. +@samp{|} unconditionally lists the possible completions. @samp{TAB} means do standard completion. @samp{*} means insert all of the possible completions. @samp{!} means to display all of the possible completions, diff --git a/lib/readline/mbutil.c b/lib/readline/mbutil.c index 5243fd7b..b1b83b6d 100644 --- a/lib/readline/mbutil.c +++ b/lib/readline/mbutil.c @@ -121,7 +121,7 @@ _rl_utf8_mblen (const char *s, size_t n) return 3; } } - else if (c < 0xf4) + else if (c <= 0xf4) { if (n == 1) return -2; @@ -584,6 +584,7 @@ _rl_find_prev_mbchar (const char *string, int seed, int flags) #endif } +#if defined (HANDLE_MULTIBYTE) /* Compare the first N characters of S1 and S2 without regard to case. If FLAGS&1, apply the mapping specified by completion-map-case and make `-' and `_' equivalent. Returns 1 if the strings are equal. */ @@ -658,3 +659,4 @@ _rl_mb_charcasecmp (const char *s1, mbstate_t *ps1, const char *s2, mbstate_t *p return 1; return (wc1 == wc2); } +#endif diff --git a/parse.y b/parse.y index f41a6d62..0aa8377a 100644 --- a/parse.y +++ b/parse.y @@ -3008,17 +3008,19 @@ discard_until (int character) } void -execute_variable_command (const char *command, const char *vname) +execute_variable_command (const char *command, const char *vname, int flags) { char *last_lastarg; sh_parser_state_t ps; - save_parser_state (&ps); + if (flags) + save_parser_state (&ps); last_lastarg = save_lastarg (); parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE|SEVAL_NOTIFY); - restore_parser_state (&ps); + if (flags) + restore_parser_state (&ps); bind_lastarg (last_lastarg); FREE (last_lastarg); diff --git a/pcomplete.c b/pcomplete.c index 6e056471..bc65ff3f 100644 --- a/pcomplete.c +++ b/pcomplete.c @@ -74,10 +74,6 @@ typedef SHELL_VAR **SVFUNC (void); -#ifndef HAVE_STRPBRK -extern char *strpbrk (char *, char *); -#endif - extern STRING_INT_ALIST word_token_alist[]; extern char *signal_names[]; -- 2.47.2