mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 23:41:23 +01:00
lib: sbi: Fix timing of clearing tbuf
A single scan of the format char may add multiple characters to the tbuf, causing a buffer overflow. You should check if tbuf is full in printc so that it does not cause a buffer overflow. Signed-off-by: Xiang W <wxjstz@126.com> Reviewed-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
@@ -121,6 +121,7 @@ unsigned long sbi_ngets(char *str, unsigned long len)
|
|||||||
#define PAD_ZERO 2
|
#define PAD_ZERO 2
|
||||||
#define PAD_ALTERNATE 4
|
#define PAD_ALTERNATE 4
|
||||||
#define PAD_SIGN 8
|
#define PAD_SIGN 8
|
||||||
|
#define USE_TBUF 16
|
||||||
#define PRINT_BUF_LEN 64
|
#define PRINT_BUF_LEN 64
|
||||||
|
|
||||||
#define va_start(v, l) __builtin_va_start((v), l)
|
#define va_start(v, l) __builtin_va_start((v), l)
|
||||||
@@ -128,7 +129,7 @@ unsigned long sbi_ngets(char *str, unsigned long len)
|
|||||||
#define va_arg __builtin_va_arg
|
#define va_arg __builtin_va_arg
|
||||||
typedef __builtin_va_list va_list;
|
typedef __builtin_va_list va_list;
|
||||||
|
|
||||||
static void printc(char **out, u32 *out_len, char ch)
|
static void printc(char **out, u32 *out_len, char ch, int flags)
|
||||||
{
|
{
|
||||||
if (!out) {
|
if (!out) {
|
||||||
sbi_putc(ch);
|
sbi_putc(ch);
|
||||||
@@ -142,8 +143,14 @@ static void printc(char **out, u32 *out_len, char ch)
|
|||||||
if (!out_len || *out_len > 1) {
|
if (!out_len || *out_len > 1) {
|
||||||
*(*out)++ = ch;
|
*(*out)++ = ch;
|
||||||
**out = '\0';
|
**out = '\0';
|
||||||
if (out_len)
|
if (out_len) {
|
||||||
--(*out_len);
|
--(*out_len);
|
||||||
|
if ((flags & USE_TBUF) && *out_len == 1) {
|
||||||
|
nputs_all(console_tbuf, CONSOLE_TBUF_MAX - *out_len);
|
||||||
|
*out = console_tbuf;
|
||||||
|
*out_len = CONSOLE_TBUF_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,16 +161,16 @@ static int prints(char **out, u32 *out_len, const char *string, int width,
|
|||||||
width -= sbi_strlen(string);
|
width -= sbi_strlen(string);
|
||||||
if (!(flags & PAD_RIGHT)) {
|
if (!(flags & PAD_RIGHT)) {
|
||||||
for (; width > 0; --width) {
|
for (; width > 0; --width) {
|
||||||
printc(out, out_len, flags & PAD_ZERO ? '0' : ' ');
|
printc(out, out_len, flags & PAD_ZERO ? '0' : ' ', flags);
|
||||||
++pc;
|
++pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; *string; ++string) {
|
for (; *string; ++string) {
|
||||||
printc(out, out_len, *string);
|
printc(out, out_len, *string, flags);
|
||||||
++pc;
|
++pc;
|
||||||
}
|
}
|
||||||
for (; width > 0; --width) {
|
for (; width > 0; --width) {
|
||||||
printc(out, out_len, ' ');
|
printc(out, out_len, ' ', flags);
|
||||||
++pc;
|
++pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,18 +222,18 @@ static int printi(char **out, u32 *out_len, long long i,
|
|||||||
|
|
||||||
if (flags & PAD_ZERO) {
|
if (flags & PAD_ZERO) {
|
||||||
if (sign) {
|
if (sign) {
|
||||||
printc(out, out_len, sign);
|
printc(out, out_len, sign, flags);
|
||||||
++pc;
|
++pc;
|
||||||
--width;
|
--width;
|
||||||
}
|
}
|
||||||
if (i && (flags & PAD_ALTERNATE)) {
|
if (i && (flags & PAD_ALTERNATE)) {
|
||||||
if (b == 16 || b == 8) {
|
if (b == 16 || b == 8) {
|
||||||
printc(out, out_len, '0');
|
printc(out, out_len, '0', flags);
|
||||||
++pc;
|
++pc;
|
||||||
--width;
|
--width;
|
||||||
}
|
}
|
||||||
if (b == 16) {
|
if (b == 16) {
|
||||||
printc(out, out_len, 'x' - 'a' + letbase);
|
printc(out, out_len, 'x' - 'a' + letbase, flags);
|
||||||
++pc;
|
++pc;
|
||||||
--width;
|
--width;
|
||||||
}
|
}
|
||||||
@@ -265,15 +272,11 @@ static int print(char **out, u32 *out_len, const char *format, va_list args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (; *format != 0; ++format) {
|
for (; *format != 0; ++format) {
|
||||||
if (use_tbuf && !console_tbuf_len) {
|
width = flags = 0;
|
||||||
nputs_all(console_tbuf, CONSOLE_TBUF_MAX);
|
if (use_tbuf)
|
||||||
console_tbuf_len = CONSOLE_TBUF_MAX;
|
flags |= USE_TBUF;
|
||||||
tout = console_tbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*format == '%') {
|
if (*format == '%') {
|
||||||
++format;
|
++format;
|
||||||
width = flags = 0;
|
|
||||||
if (*format == '\0')
|
if (*format == '\0')
|
||||||
break;
|
break;
|
||||||
if (*format == '%')
|
if (*format == '%')
|
||||||
@@ -371,7 +374,7 @@ static int print(char **out, u32 *out_len, const char *format, va_list args)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
literal:
|
literal:
|
||||||
printc(out, out_len, *format);
|
printc(out, out_len, *format, flags);
|
||||||
++pc;
|
++pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user