mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-14 22:44:27 +08:00
efi/printf: Turn vsprintf into vsnprintf
Implement vsnprintf instead of vsprintf to avoid the possibility of a buffer overflow. Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu> Link: https://lore.kernel.org/r/20200518190716.751506-17-nivedita@alum.mit.edu Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
f97ca2c816
commit
8fb331e10b
@ -60,10 +60,14 @@ int efi_printk(const char *fmt, ...)
|
||||
int printed;
|
||||
|
||||
va_start(args, fmt);
|
||||
printed = vsprintf(printf_buf, fmt, args);
|
||||
printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
efi_puts(printf_buf);
|
||||
if (printed >= sizeof(printf_buf)) {
|
||||
efi_puts("[Message truncated]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return printed;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
static
|
||||
int skip_atoi(const char **s)
|
||||
@ -237,16 +238,22 @@ char get_sign(long long *num, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list ap)
|
||||
#define PUTC(c) \
|
||||
do { \
|
||||
if (pos < size) \
|
||||
buf[pos] = (c); \
|
||||
++pos; \
|
||||
} while (0);
|
||||
|
||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
|
||||
{
|
||||
/* The maximum space required is to print a 64-bit number in octal */
|
||||
char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
|
||||
char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
|
||||
long long num;
|
||||
int base;
|
||||
char *str;
|
||||
const char *s;
|
||||
int len;
|
||||
size_t len, pos;
|
||||
char sign;
|
||||
|
||||
int flags; /* flags to number() */
|
||||
@ -274,9 +281,9 @@ int vsprintf(char *buf, const char *fmt, va_list ap)
|
||||
*/
|
||||
va_copy(args, ap);
|
||||
|
||||
for (str = buf; *fmt; ++fmt) {
|
||||
for (pos = 0; *fmt; ++fmt) {
|
||||
if (*fmt != '%' || *++fmt == '%') {
|
||||
*str++ = *fmt;
|
||||
PUTC(*fmt);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -416,40 +423,41 @@ output:
|
||||
/* Leading padding with ' ' */
|
||||
if (!(flags & LEFT))
|
||||
while (field_width-- > 0)
|
||||
*str++ = ' ';
|
||||
PUTC(' ');
|
||||
/* sign */
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
PUTC(sign);
|
||||
/* 0x/0X for hexadecimal */
|
||||
if (flags & SPECIAL) {
|
||||
*str++ = '0';
|
||||
*str++ = 'X' | (flags & SMALL);
|
||||
PUTC('0');
|
||||
PUTC( 'X' | (flags & SMALL));
|
||||
}
|
||||
/* Zero padding and excess precision */
|
||||
while (precision-- > len)
|
||||
*str++ = '0';
|
||||
PUTC('0');
|
||||
/* Actual output */
|
||||
while (len-- > 0)
|
||||
*str++ = *s++;
|
||||
PUTC(*s++);
|
||||
/* Trailing padding with ' ' */
|
||||
while (field_width-- > 0)
|
||||
*str++ = ' ';
|
||||
PUTC(' ');
|
||||
}
|
||||
fail:
|
||||
*str = '\0';
|
||||
|
||||
va_end(args);
|
||||
|
||||
return str - buf;
|
||||
if (size)
|
||||
buf[min(pos, size-1)] = '\0';
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
int sprintf(char *buf, const char *fmt, ...)
|
||||
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i;
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsprintf(buf, fmt, args);
|
||||
i = vsnprintf(buf, size, fmt, args);
|
||||
va_end(args);
|
||||
return i;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user