Skip to content

Commit 80af334

Browse files
sjg20smaeul
authored andcommitted
cli: Correct several bugs in cli_getch()
This function does not behave as expected when unknown escape sequences are sent to it: - it fails to store (and thus echo) the last character of the invalid sequence - it fails to set esc_len to 0 when it finishes emitting the invalid sequence, meaning that the following character will appear to be part of a new escape sequence - it processes the first character of the rejected sequence as a valid character, just starting the sequence all over again The last two bugs conspire to produce an "impossible condition #876" message which is the main symptom of this behaviour. Fix these bugs and add a test to verify the behaviour. Signed-off-by: Simon Glass <[email protected]> Reported-by: Heinrich Schuchardt <[email protected]>
1 parent 3894a2f commit 80af334

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

common/cli_getch.c

+3-2
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static int cli_ch_esc(struct cli_ch_state *cch, int ichar,
129129

130130
*actp = act;
131131

132-
return act == ESC_CONVERTED ? ichar : 0;
132+
return ichar;
133133
}
134134

135135
int cli_ch_process(struct cli_ch_state *cch, int ichar)
@@ -145,6 +145,7 @@ int cli_ch_process(struct cli_ch_state *cch, int ichar)
145145
return cch->esc_save[cch->emit_upto++];
146146
cch->emit_upto = 0;
147147
cch->emitting = false;
148+
cch->esc_len = 0;
148149
}
149150
return 0;
150151
} else if (ichar == -ETIMEDOUT) {
@@ -185,7 +186,7 @@ int cli_ch_process(struct cli_ch_state *cch, int ichar)
185186
cch->esc_save[cch->esc_len++] = ichar;
186187
ichar = cch->esc_save[cch->emit_upto++];
187188
cch->emitting = true;
188-
break;
189+
return ichar;
189190
case ESC_CONVERTED:
190191
/* valid escape sequence, return the resulting char */
191192
cch->esc_len = 0;

test/common/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ obj-y += cmd_ut_common.o
33
obj-$(CONFIG_AUTOBOOT) += test_autoboot.o
44
obj-$(CONFIG_CYCLIC) += cyclic.o
55
obj-$(CONFIG_EVENT) += event.o
6+
obj-y += cread.o

test/common/cread.c

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright 2023 Google LLC
4+
*/
5+
6+
#include <common.h>
7+
#include <cli.h>
8+
#include <test/common.h>
9+
#include <test/test.h>
10+
#include <test/ut.h>
11+
12+
static int cli_ch_test(struct unit_test_state *uts)
13+
{
14+
struct cli_ch_state s_cch, *cch = &s_cch;
15+
16+
cli_ch_init(cch);
17+
18+
/* should be nothing to return at first */
19+
ut_asserteq(0, cli_ch_process(cch, 0));
20+
21+
/* check normal entry */
22+
ut_asserteq('a', cli_ch_process(cch, 'a'));
23+
ut_asserteq('b', cli_ch_process(cch, 'b'));
24+
ut_asserteq('c', cli_ch_process(cch, 'c'));
25+
ut_asserteq(0, cli_ch_process(cch, 0));
26+
27+
/* send an invalid escape sequence */
28+
ut_asserteq(0, cli_ch_process(cch, '\e'));
29+
ut_asserteq(0, cli_ch_process(cch, '['));
30+
31+
/*
32+
* with the next char it sees that the sequence is invalid, so starts
33+
* emitting it
34+
*/
35+
ut_asserteq('\e', cli_ch_process(cch, 'X'));
36+
37+
/* now we set 0 bytes to empty the buffer */
38+
ut_asserteq('[', cli_ch_process(cch, 0));
39+
ut_asserteq('X', cli_ch_process(cch, 0));
40+
ut_asserteq(0, cli_ch_process(cch, 0));
41+
42+
/* things are normal again */
43+
ut_asserteq('a', cli_ch_process(cch, 'a'));
44+
ut_asserteq(0, cli_ch_process(cch, 0));
45+
46+
return 0;
47+
}
48+
COMMON_TEST(cli_ch_test, 0);

0 commit comments

Comments
 (0)