The second call to cli_ch_process() is in the wrong place, meaning that
the one of the characters of an invalid escape sequence is swallowed
instead of being returned.

Fix the bug and add a test to cover this.

Signed-off-by: Simon Glass <[email protected]>
Reported-by: Heinrich Schuchardt <[email protected]>
---

 common/cli_readline.c |  3 +--
 include/cli.h         |  4 ++--
 test/common/cread.c   | 45 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/common/cli_readline.c b/common/cli_readline.c
index 709e9c3d38b..e83743e90c9 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -284,10 +284,9 @@ static int cread_line(const char *const prompt, char *buf, 
unsigned int *len,
                        }
 
                        ichar = getcmd_getch();
+                       ichar = cli_ch_process(cch, ichar);
                }
 
-               ichar = cli_ch_process(cch, ichar);
-
                /* ichar=0x0 when error occurs in U-Boot getc */
                if (!ichar)
                        continue;
diff --git a/include/cli.h b/include/cli.h
index c777c90313f..094a6602d70 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -98,8 +98,8 @@ int cli_readline(const char *const prompt);
  *
  * @prompt:    Prompt to display
  * @buffer:    Place to put the line that is entered
- * @timeout:   Timeout in milliseconds, 0 if none
- * Return: command line length excluding terminator, or -ve on error: of the
+ * @timeout:   Timeout in seconds, 0 if none
+ * Return: command line length excluding terminator, or -ve on error: if the
  * timeout is exceeded (either CONFIG_BOOT_RETRY_TIME or the timeout
  * parameter), then -2 is returned. If a break is detected (Ctrl-C) then
  * -1 is returned.
diff --git a/test/common/cread.c b/test/common/cread.c
index 3dce4bdb0ef..7851c16747c 100644
--- a/test/common/cread.c
+++ b/test/common/cread.c
@@ -46,3 +46,48 @@ static int cli_ch_test(struct unit_test_state *uts)
        return 0;
 }
 COMMON_TEST(cli_ch_test, 0);
+
+static int cread_test(struct unit_test_state *uts)
+{
+       int duration;
+       ulong start;
+       char buf[10];
+
+       /*
+        * useful for debugging
+        *
+        * gd->flags &= ~GD_FLG_RECORD;
+        * print_buffer(0, buf, 1, 7, 0);
+        */
+
+       console_record_reset_enable();
+
+       /* simple input */
+       *buf = '\0';
+       ut_asserteq(4, console_in_puts("abc\n"));
+       ut_asserteq(3, cli_readline_into_buffer("-> ", buf, 1));
+       ut_asserteq_str("abc", buf);
+
+       /* try an escape sequence (cursor left after the 'c') */
+       *buf = '\0';
+       ut_asserteq(8, console_in_puts("abc\e[Dx\n"));
+       ut_asserteq(4, cli_readline_into_buffer("-> ", buf, 1));
+       ut_asserteq_str("abxc", buf);
+
+       /* invalid escape sequence */
+       *buf = '\0';
+       ut_asserteq(8, console_in_puts("abc\e[Xx\n"));
+       ut_asserteq(7, cli_readline_into_buffer("-> ", buf, 1));
+       ut_asserteq_str("abc\e[Xx", buf);
+
+       /* check timeout, should be between 1000 and 1050ms */
+       start = get_timer(0);
+       *buf = '\0';
+       ut_asserteq(-2, cli_readline_into_buffer("-> ", buf, 1));
+       duration = get_timer(start) - 1000;
+       ut_assert(duration > 0);
+       ut_assert(duration < 50);
+
+       return 0;
+}
+COMMON_TEST(cread_test, 0);
-- 
2.39.1.519.gcb327c4b5f-goog

Reply via email to