1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
READLINE PATCH REPORT
=====================
Readline-Release: 8.2
Patch-ID: readline82-013
Bug-Reported-by: Grisha Levit <grishalevit@gmail.com>
Bug-Reference-ID: <CAMu=Brrv5qKY6LPfw8PxqNXNO8rNsZo0Fb=BcFb-uHObWPqnrw@mail.gmail.
Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2023-04/msg00082.html
Bug-Description:
When readline is accumulating bytes until it reads a complete multibyte
character, reading a byte that makes the multibyte character invalid can
result in discarding the bytes in the partial character.
--- a/patchlevel
+++ b/patchlevel
@@ -1,3 +1,3 @@
# Do not edit -- exists only for use by patch
-12
+13
--- a/text.c
+++ b/text.c
@@ -85,7 +85,8 @@ int _rl_optimize_typeahead = 1; /* rl_in
int
rl_insert_text (const char *string)
{
- register int i, l;
+ register int i;
+ size_t l;
l = (string && *string) ? strlen (string) : 0;
if (l == 0)
@@ -704,7 +705,11 @@ static mbstate_t ps = {0};
/* Insert the character C at the current location, moving point forward.
If C introduces a multibyte sequence, we read the whole sequence and
- then insert the multibyte char into the line buffer. */
+ then insert the multibyte char into the line buffer.
+ If C == 0, we immediately insert any pending partial multibyte character,
+ assuming that we have read a character that doesn't map to self-insert.
+ This doesn't completely handle characters that are part of a multibyte
+ character but map to editing functions. */
int
_rl_insert_char (int count, int c)
{
@@ -718,11 +723,28 @@ _rl_insert_char (int count, int c)
static int stored_count = 0;
#endif
+#if !defined (HANDLE_MULTIBYTE)
if (count <= 0)
return 0;
+#else
+ if (count < 0)
+ return 0;
+ if (count == 0)
+ {
+ if (pending_bytes_length == 0)
+ return 0;
+ if (stored_count <= 0)
+ stored_count = count;
+ else
+ count = stored_count;
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ memcpy (incoming, pending_bytes, pending_bytes_length);
+ incoming[pending_bytes_length] = '\0';
+ incoming_length = pending_bytes_length;
+ pending_bytes_length = 0;
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (MB_CUR_MAX == 1 || rl_byte_oriented)
{
incoming[0] = c;
incoming[1] = '\0';
@@ -730,6 +752,9 @@ _rl_insert_char (int count, int c)
}
else if (_rl_utf8locale && (c & 0x80) == 0)
{
+ if (pending_bytes_length)
+ _rl_insert_char (0, 0);
+
incoming[0] = c;
incoming[1] = '\0';
incoming_length = 1;
@@ -764,7 +789,8 @@ _rl_insert_char (int count, int c)
incoming[1] = '\0';
incoming_length = 1;
pending_bytes_length--;
- memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+ if (pending_bytes_length)
+ memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
/* Clear the state of the byte sequence, because in this case the
effect of mbstate is undefined. */
memset (&ps, 0, sizeof (mbstate_t));
@@ -827,7 +853,11 @@ _rl_insert_char (int count, int c)
rl_insert_text (string);
xfree (string);
+#if defined (HANDLE_MULTIBYTE)
+ return (pending_bytes_length != 0);
+#else
return 0;
+#endif
}
if (count > TEXT_COUNT_MAX)
@@ -860,6 +890,8 @@ _rl_insert_char (int count, int c)
xfree (string);
incoming_length = 0;
stored_count = 0;
+
+ return (pending_bytes_length != 0);
#else /* !HANDLE_MULTIBYTE */
char str[TEXT_COUNT_MAX+1];
@@ -873,9 +905,9 @@ _rl_insert_char (int count, int c)
rl_insert_text (str);
count -= decreaser;
}
-#endif /* !HANDLE_MULTIBYTE */
return 0;
+#endif /* !HANDLE_MULTIBYTE */
}
if (MB_CUR_MAX == 1 || rl_byte_oriented)
@@ -903,9 +935,11 @@ _rl_insert_char (int count, int c)
rl_insert_text (incoming);
stored_count = 0;
}
-#endif
-
+
+ return (pending_bytes_length != 0);
+#else
return 0;
+#endif
}
/* Overwrite the character at point (or next COUNT characters) with C.
@@ -983,6 +1017,11 @@ rl_insert (int count, int c)
break;
}
+ /* If we didn't insert n and there are pending bytes, we need to insert
+ them if _rl_insert_char didn't do that on its own. */
+ if (r == 1 && rl_insert_mode == RL_IM_INSERT)
+ r = _rl_insert_char (0, 0); /* flush partial multibyte char */
+
if (n != (unsigned short)-2) /* -2 = sentinel value for having inserted N */
{
/* setting rl_pending_input inhibits setting rl_last_func so we do it
@@ -1054,6 +1093,8 @@ _rl_insert_next_callback (_rl_callback_g
int
rl_quoted_insert (int count, int key)
{
+ int r;
+
/* Let's see...should the callback interface futz with signal handling? */
#if defined (HANDLE_SIGNALS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
@@ -1072,15 +1113,17 @@ rl_quoted_insert (int count, int key)
/* A negative count means to quote the next -COUNT characters. */
if (count < 0)
{
- int r;
-
do
r = _rl_insert_next (1);
while (r == 0 && ++count < 0);
- return r;
}
+ else
+ r = _rl_insert_next (count);
- return _rl_insert_next (count);
+ if (r == 1)
+ _rl_insert_char (0, 0); /* insert partial multibyte character */
+
+ return r;
}
/* Insert a tab character. */
|