nano-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]