[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Nano-devel] [PATCH] input: consume only the actual length of an escape
From: |
Benno Schulenberg |
Subject: |
[Nano-devel] [PATCH] input: consume only the actual length of an escape sequence |
Date: |
Sat, 20 Jan 2018 19:41:31 +0100 |
Instead of assuming that the entire contents of the keybuffer are an
escape sequence, even if this is far longer than any escape sequence
can be.
This fixes https://savannah.gnu.org/bugs/?48659.
[In order to make https://savannah.gnu.org/bugs/?52931 complete.]
[Comments welcome.]
---
src/winio.c | 42 ++++++++++++++++++++++++++++++++++--------
1 file changed, 34 insertions(+), 8 deletions(-)
diff --git a/src/winio.c b/src/winio.c
index 7ab42e7c..908a94d8 100644
--- a/src/winio.c
+++ b/src/winio.c
@@ -761,15 +761,17 @@ int parse_kbinput(WINDOW *win)
* keypad values, into their corresponding key values. These sequences
* are generated when the keypad doesn't support the needed keys.
* Assume that Escape has already been read in. */
-int convert_sequence(const int *seq, size_t length)
+int convert_sequence(const int *seq, size_t length, int *consumed)
{
if (length > 1) {
+ *consumed = 2;
switch (seq[0]) {
case 'O':
switch (seq[1]) {
case '1':
if (length > 4 && seq[2] ==
';') {
+ *consumed = 5;
switch (seq[3]) {
case '2':
switch (seq[4]) {
@@ -806,6 +808,7 @@ int convert_sequence(const int *seq, size_t length)
}
break;
case '2':
+ *consumed = 4;
if (length >= 3) {
switch (seq[2]) {
case 'P': /*
Esc O 2 P == F13 on xterm. */
@@ -820,6 +823,7 @@ int convert_sequence(const int *seq, size_t length)
}
break;
case '5':
+ *consumed = 4;
if (length >= 3) {
switch (seq[2]) {
case 'A': /*
Esc O 5 A == Ctrl-Up on Haiku. */
@@ -832,6 +836,7 @@ int convert_sequence(const int *seq, size_t length)
return
CONTROL_LEFT;
}
}
+ break;
case 'A': /* Esc O A == Up on
VT100/VT320/xterm. */
case 'B': /* Esc O B == Down on
VT100/VT320/xterm. */
case 'C': /* Esc O C == Right on
VT100/VT320/xterm. */
@@ -934,6 +939,7 @@ int convert_sequence(const int *seq, size_t length)
switch (seq[1]) {
case '1':
if (length > 3 && seq[3] ==
'~') {
+ *consumed = 4;
switch (seq[2]) {
case '1': /*
Esc [ 1 1 ~ == F1 on rxvt/Eterm. */
return
KEY_F(1);
@@ -955,6 +961,7 @@ int convert_sequence(const int *seq, size_t length)
}
} else if (length > 4 && seq[2]
== ';') {
+ *consumed = 5;
switch (seq[3]) {
case '2':
switch (seq[4]) {
@@ -1031,12 +1038,15 @@ int convert_sequence(const int *seq, size_t length)
#endif
}
- } else if (length > 2 && seq[2]
== '~')
+ } else if (length > 2 && seq[2]
== '~') {
+ *consumed = 3;
/* Esc [ 1 ~ == Home on
VT320/Linux console. */
return KEY_HOME;
+ }
break;
case '2':
if (length > 3 && seq[3] ==
'~') {
+ *consumed = 4;
switch (seq[2]) {
case '0': /*
Esc [ 2 0 ~ == F9 on VT220/VT320/
* Linux console/xterm/rxvt/Eterm. */
@@ -1064,23 +1074,27 @@ int convert_sequence(const int *seq, size_t length)
break;
case '3': /* Esc [ 3 ~ == Delete on
VT220/VT320/
* Linux
console/xterm/Terminal. */
+ *consumed = 3;
if (length > 2 && seq[2] == '~')
return KEY_DC;
break;
case '4': /* Esc [ 4 ~ == End on
VT220/VT320/
* Linux
console/xterm. */
+ *consumed = 3;
if (length > 2 && seq[2] == '~')
return KEY_END;
break;
case '5': /* Esc [ 5 ~ == PageUp on
VT220/VT320/
* Linux
console/xterm/Terminal;
* Esc [ 5 ^ ==
PageUp on Eterm. */
+ *consumed = 3;
if (length > 2 && (seq[2] ==
'~' || seq[2] == '^'))
return KEY_PPAGE;
break;
case '6': /* Esc [ 6 ~ == PageDown on
VT220/VT320/
* Linux
console/xterm/Terminal;
* Esc [ 6 ^ ==
PageDown on Eterm. */
+ *consumed = 3;
if (length > 2 && (seq[2] ==
'~' || seq[2] == '^'))
return KEY_NPAGE;
break;
@@ -1088,6 +1102,7 @@ int convert_sequence(const int *seq, size_t length)
* Esc [ 7 $ ==
Shift-Home on Eterm/rxvt;
* Esc [ 7 ^ ==
Control-Home on Eterm/rxvt;
* Esc [ 7 @ ==
Shift-Control-Home on same. */
+ *consumed = 3;
if (length > 2 && seq[2] == '~')
return KEY_HOME;
else if (length > 2 && seq[2]
== '$')
@@ -1103,6 +1118,7 @@ int convert_sequence(const int *seq, size_t length)
* Esc [ 8 $ ==
Shift-End on Eterm/rxvt;
* Esc [ 8 ^ ==
Control-End on Eterm/rxvt;
* Esc [ 8 @ ==
Shift-Control-End on same. */
+ *consumed = 3;
if (length > 2 && seq[2] == '~')
return KEY_END;
else if (length > 2 && seq[2]
== '$')
@@ -1144,6 +1160,7 @@ int convert_sequence(const int *seq, size_t length)
return KEY_F(2);
case 'O':
if (length > 2) {
+ *consumed = 3;
switch (seq[2]) {
case 'P': /*
Esc [ O P == F1 on xterm. */
return
KEY_F(1);
@@ -1189,6 +1206,7 @@ int convert_sequence(const int *seq, size_t length)
return arrow_from_abcd(seq[1]);
case '[':
if (length > 2) {
+ *consumed = 3;
switch (seq[2]) {
case 'A': /*
Esc [ [ A == F1 on Linux console. */
return
KEY_F(1);
@@ -1234,15 +1252,23 @@ int arrow_from_abcd(int kbinput)
* isn't empty, and that the initial escape has already been read in. */
int parse_escape_sequence(WINDOW *win, int kbinput)
{
- int retval, *sequence, length;
+ int retval, *sequence, length, consumed;
- /* Put back the non-escape character, get the complete escape
- * sequence, translate the sequence into its corresponding key
- * value, and save that as the result. */
+ /* Put back the non-escape code, then grab at most five integers
+ * (the longest possible escape sequence) from the keybuffer and
+ * translate the sequence into its corresponding keycode. */
unget_input(kbinput);
- length = key_buffer_len;
+ length = (key_buffer_len < 5 ? key_buffer_len : 5);
sequence = get_input(NULL, length);
- retval = convert_sequence(sequence, length);
+ retval = convert_sequence(sequence, length, &consumed);
+
+ if (length < consumed)
+ fprintf(stderr, "Overconsumed keycodes -- please report a
bug.\n");
+
+ /* If not all grabbed integers were consumed, put the leftovers back. */
+ for (int i = length - consumed; i > 0; i--)
+ unget_input(sequence[consumed - 1 + i]);
+
free(sequence);
/* If we got an unrecognized escape sequence, notify the user. */
--
2.14.3
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Nano-devel] [PATCH] input: consume only the actual length of an escape sequence,
Benno Schulenberg <=