fix for invalid bracketed paste prefix when the final character is wrong; fixes for unlikely SIGINTs while readline is reading from the keyboard; android fix for generating $'...' strings in the presence of invalid multibyte characters

This commit is contained in:
Chet Ramey
2025-09-18 17:35:34 -04:00
parent b88cd1c366
commit 013fae2c98
6 changed files with 95 additions and 54 deletions
+38 -4
View File
@@ -11723,10 +11723,11 @@ lib/readline/macro.c
reading input from a bound macro.
Suggested by Grisha Levit <grishalevit@gmail.com>
lib/readline/readline.c,lib/readline/text.c
- _rl_dispatch_subseq,_rl_insert_next,_rl_char_search: if we're
defining a keyboard macro, don't insert the expanded value of a
macro that is bound to a key sequence added to the keyboard macro
lib/readline/readline.c,lib/readline/text.c,lib/readline/kill.c
- _rl_dispatch_subseq,_rl_insert_next,_rl_char_search,
_rl_bracketed_text: if we're defining a keyboard macro, don't
insert the expanded value of a macro that is bound to a key
sequence added to the keyboard macro
Report and patch from Grisha Levit <grishalevit@gmail.com>
9/12
@@ -11734,3 +11735,36 @@ lib/readline/readline.c,lib/readline/text.c
builtins/mkbuiltins.c
- some minor code cleanups
Patch from Martin D Kealey <martin@kurahaupo.gen.nz>
9/15
----
lib/readline/kill.c
- _rl_read_bracketed_paste_prefix: if we read the bracketed paste
prefix except for the last character (key != BRACK_PASTE_LAST),
return 0, since we didn't read a valid prefix
Report from Grisha Levit <grishalevit@gmail.com>
- _rl_bracketed_text: if _rl_read_key returns < 0, abort trying
to read the string
lib/readline/text.c
- _rl_readstr_init: set _rl_rscxt after we finish initializing cxt,
before the call to rl_message
Report from Grisha Levit <grishalevit@gmail.com>
- _rl_readstr_getchar: if _rl_read_mbstring returns and _rl_caught_signal
is != 0, treat this as a failure and return -1 after handling the
signal
- _rl_read_command_name: if _rl_readstr_getchar returns -1, but
_rl_rscxt is NULL, assume this was the result of a signal and call
_rl_abort_internal accordingly
Report from Grisha Levit <grishalevit@gmail.com>
lib/readline/input.c
- rl_getc: skip trying to read a character if we have a signal pending
when we enter this function in all cases, not just callback mode.
Suggestion from Grisha Levit <grishalevit@gmail.com>
lib/sh/strtrans.c
- ansic_quote: handle the undefined state of the internal state
pointer when encountering an invalid wide character by using our
own mbstate_t and reinitializing it on EILSEQ.
Report and patch from Grisha Levit <grishalevit@gmail.com>
+4
View File
@@ -44,11 +44,15 @@ Options which set attributes:
-A to make NAMEs associative arrays (if supported)
#endif
-i to make NAMEs have the `integer' attribute
#ifdef CASEMOD_ATTRS
-l to convert the value of each NAME to lower case on assignment
#endif
-n make NAME a reference to the variable named by its value
-r to make NAMEs readonly
-t to make NAMEs have the `trace' attribute
#ifdef CASEMOD_ATTRS
-u to convert the value of each NAME to upper case on assignment
#endif
-x to make NAMEs export
Using `+' instead of `-' turns off the given attribute, except for a,
+5 -7
View File
@@ -859,16 +859,14 @@ rl_getc (FILE *stream)
RL_CHECK_SIGNALS ();
#if defined (READLINE_CALLBACKS)
/* Do signal handling post-processing here, but just in callback mode
for right now because the signal cleanup can change some of the
/* Do signal handling post-processing here, not just in callback mode
now, because the signal cleanup can change some of the readline and
callback state, and we need to either let the application have a
chance to react or abort some current operation that gets cleaned
up by rl_callback_sigcleanup(). If not, we'll just run through the
loop again. */
if (osig != 0 && (ostate & RL_STATE_CALLBACK)) /* XXX - when not in callback mode also? */
up by rl_callback_sigcleanup() or another signal cleanup function.
If not, we'll just run through the loop again. */
if (osig != 0)
goto postproc_signal;
#endif
/* We know at this point that _rl_caught_signal == 0 */
+8 -4
View File
@@ -1,6 +1,6 @@
/* kill.c -- kill ring management. */
/* Copyright (C) 1994-2024 Free Software Foundation, Inc.
/* Copyright (C) 1994-2025 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.
@@ -718,7 +718,7 @@ _rl_bracketed_text (size_t *lenp)
RL_SETSTATE (RL_STATE_MOREINPUT);
while ((c = rl_read_key ()) >= 0)
{
if (RL_ISSTATE (RL_STATE_MACRODEF))
if (RL_ISSTATE (RL_STATE_MACRODEF) && RL_ISSTATE (RL_STATE_MACROINPUT) == 0)
_rl_add_macro_char (c);
if (c == '\r') /* XXX */
@@ -736,7 +736,11 @@ _rl_bracketed_text (size_t *lenp)
}
}
RL_UNSETSTATE (RL_STATE_MOREINPUT);
if (c < 0) /* read error */
{
free (buf);
_rl_abort_internal ();
}
if (len == cap)
buf = xrealloc (buf, cap + 1);
buf[len] = '\0';
@@ -790,7 +794,7 @@ _rl_read_bracketed_paste_prefix (int c)
break;
}
if (ind < BRACK_PASTE_SLEN-1) /* read incomplete sequence */
if (ind < BRACK_PASTE_SLEN-1 || key != BRACK_PASTE_LAST) /* read incomplete sequence */
{
while (ind >= 0)
_rl_unget_char (pbuf[ind--]);
+9 -3
View File
@@ -39,6 +39,7 @@
# include <locale.h>
#endif
#include <signal.h>
#include <stdio.h>
/* System-specific feature definitions and include files. */
@@ -2029,11 +2030,11 @@ _rl_readstr_init (int pchar, int flags)
RL_SETSTATE (RL_STATE_READSTR);
cxt->flags |= READSTR_FREEPMT;
_rl_rscxt = cxt;
rl_message ("%s", p);
xfree (p);
_rl_rscxt = cxt;
return cxt;
}
@@ -2081,7 +2082,7 @@ _rl_readstr_getchar (_rl_readstr_cxt *cxt)
RL_SETSTATE(RL_STATE_MOREINPUT);
c = cxt->lastc = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#if defined (HANDLE_MULTIBYTE)
/* This ends up with C (and LASTC) being set to the last byte of the
multibyte character. In most cases c == lastc == mb[0] */
@@ -2089,6 +2090,9 @@ _rl_readstr_getchar (_rl_readstr_cxt *cxt)
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
#endif
if (_rl_caught_signal == SIGINT) /* XXX maybe more signals here */
c = -1;
RL_CHECK_SIGNALS ();
return c;
}
@@ -2331,6 +2335,8 @@ _rl_read_command_name ()
if (c < 0)
{
if (_rl_rscxt == 0) /* signal */
_rl_abort_internal ();
_rl_readstr_restore (cxt);
_rl_readstr_cleanup (cxt, r);
return NULL;
+31 -36
View File
@@ -227,30 +227,24 @@ ansic_quote (const char *str, int flags, int *rlen)
{
char *r, *ret;
const char *s;
size_t l, rsize;
unsigned char c;
#if defined (HANDLE_MULTIBYTE)
size_t clen;
int b;
#if defined (HANDLE_MULTIBYTE)
wchar_t wc;
DECLARE_MBSTATE;
#endif
if (str == 0 || *str == 0)
return ((char *)0);
l = strlen (str);
rsize = 4 * l + 4;
r = ret = (char *)xmalloc (rsize);
r = ret = (char *)xmalloc (4 * strlen (str) + 4);
*r++ = '$';
*r++ = '\'';
for (s = str; c = *s; s++)
{
b = 1; /* 1 == add backslash; 0 == no backslash */
l = 1;
clen = 1;
switch (c)
{
case ESC: c = 'E'; break;
@@ -266,37 +260,38 @@ ansic_quote (const char *str, int flags, int *rlen)
break;
default:
#if defined (HANDLE_MULTIBYTE)
b = is_basic (c);
/* XXX - clen comparison to 0 is dicey */
if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || MB_INVALIDCH (clen) || iswprint (wc) == 0)) ||
(b == 1 && ISPRINT (c) == 0))
#else
if (ISPRINT (c) == 0)
#endif
if (is_basic (c) == 0)
{
*r++ = '\\';
*r++ = TOCHAR ((c >> 6) & 07);
*r++ = TOCHAR ((c >> 3) & 07);
*r++ = TOCHAR (c & 07);
continue;
clen = mbrtowc (&wc, s, MB_CUR_MAX, &state);
if (clen == 0)
break;
if (MB_INVALIDCH (clen))
INITIALIZE_MBSTATE;
else if (iswprint (wc))
{
for (b = 0; b < (int)clen; b++)
*r++ = (unsigned char)s[b];
s += clen - 1; /* -1 because of the increment above */
continue;
}
}
l = 0;
break;
}
if (b == 0 && clen == 0)
break;
else
#endif
if (ISPRINT (c))
{
*r++ = c;
continue;
}
if (l)
*r++ = '\\';
if (clen == 1)
*r++ = c;
else
{
for (b = 0; b < (int)clen; b++)
*r++ = (unsigned char)s[b];
s += clen - 1; /* -1 because of the increment above */
*r++ = '\\';
*r++ = TOCHAR ((c >> 6) & 07);
*r++ = TOCHAR ((c >> 3) & 07);
*r++ = TOCHAR (c & 07);
continue;
}
*r++ = '\\';
*r++ = c;
}
*r++ = '\'';