summaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-12-10 10:53:36 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2021-12-13 23:37:32 +0100
commit008af161010e78636c701e9f462df06515415518 (patch)
treef68da6144479605800791799df5faa3580481c24 /drivers/serial
parente4a8037de80559271ff143bcd93540317422577a (diff)
downloadbarebox-008af161010e78636c701e9f462df06515415518.tar.gz
barebox-008af161010e78636c701e9f462df06515415518.tar.xz
efi-stdio: Fix out of bounds error in puts
In efi_console_puts we use 'nbytes' as counter to break out of iterating over the input string. An escape sequence consumes more than 1 input character, still nbytes is only decremented by one. This results in iterating past the end of the input string once an escape sequence is in the buffer. This patch introduces efi_console_add_char() to write a character in the buffer and efi_console_flush() to print out the current buffer. This fixes the issue and also allows us to prevent writing past the end of the internal output buffer. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/efi-stdio.c60
1 files changed, 39 insertions, 21 deletions
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
index c2a29f8b2f..ef7dc77964 100644
--- a/drivers/serial/efi-stdio.c
+++ b/drivers/serial/efi-stdio.c
@@ -23,7 +23,8 @@ struct efi_console_priv {
struct efi_simple_text_input_ex_protocol *inex;
struct console_device cdev;
int lastkey;
- u16 efi_console_buffer[CONFIG_CBSIZE];
+ u16 efi_console_buffer[CONFIG_CBSIZE + 1];
+ int pos;
unsigned long columns, rows;
@@ -256,34 +257,51 @@ static int efi_process_escape(struct efi_console_priv *priv, const char *inp)
return 1;
}
+static void efi_console_add_char(struct efi_console_priv *priv, int c)
+{
+ if (priv->pos >= CONFIG_CBSIZE)
+ return;
+
+ priv->efi_console_buffer[priv->pos] = c;
+ priv->pos++;
+}
+
+static void efi_console_flush(struct efi_console_priv *priv)
+{
+ priv->efi_console_buffer[priv->pos] = 0;
+
+ priv->out->output_string(priv->out, priv->efi_console_buffer);
+
+ priv->pos = 0;
+}
+
static int efi_console_puts(struct console_device *cdev, const char *s,
size_t nbytes)
{
struct efi_console_priv *priv = to_efi(cdev);
- int n = 0;
-
- while (nbytes--) {
- if (*s == 27) {
- priv->efi_console_buffer[n] = 0;
- priv->out->output_string(priv->out,
- priv->efi_console_buffer);
- n = 0;
- s += efi_process_escape(priv, s);
- continue;
- }
+ int pos = 0;
- if (*s == '\n')
- priv->efi_console_buffer[n++] = '\r';
- priv->efi_console_buffer[n] = *s;
- s++;
- n++;
+ while (pos < nbytes) {
+ switch (s[pos]) {
+ case 27:
+ efi_console_flush(priv);
+ pos += efi_process_escape(priv, s + pos);
+ break;
+ case '\n':
+ efi_console_add_char(priv, '\r');
+ efi_console_add_char(priv, '\n');
+ pos++;
+ break;
+ default:
+ efi_console_add_char(priv, s[pos]);
+ pos++;
+ break;
+ }
}
- priv->efi_console_buffer[n] = 0;
-
- priv->out->output_string(priv->out, priv->efi_console_buffer);
+ efi_console_flush(priv);
- return n;
+ return nbytes;
}
static int efi_console_tstc(struct console_device *cdev)