Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx> --- include/linux/kernel.h | 4 ++++ lib/vsprintf.c | 43 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 0d91e0af01250c1d82f4a2ea562d2619b9cc6e9c..b348b84ce9c4e95031f67e0cbac5de8deca69aac 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -227,8 +227,12 @@ const char *kvasprintf_const(gfp_t gfp, const char *fmt, va_list args); extern __scanf(2, 3) int sscanf(const char *, const char *, ...); +extern __scanf(2, 3) +int sscanf_strict(const char *, const char *, ...); extern __scanf(2, 0) int vsscanf(const char *, const char *, va_list); +extern __scanf(2, 0) +int vsscanf_strict(const char *, const char *, va_list); extern int no_hash_pointers_enable(char *str); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 9846d2385f5b9e8f3945a5664d81047e97cf10d5..2dae357b367e1da8b1004ed6e85e051a045ca36b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -3414,6 +3414,8 @@ EXPORT_SYMBOL_GPL(bprintf); #endif /* CONFIG_BINARY_PRINTF */ +static int vsscanf_internal(const char *buf, const char *fmt, va_list args, bool strict); + /** * vsscanf - Unformat a buffer into a list of arguments * @buf: input buffer @@ -3421,6 +3423,23 @@ EXPORT_SYMBOL_GPL(bprintf); * @args: arguments */ int vsscanf(const char *buf, const char *fmt, va_list args) +{ + return vsscanf_internal(buf, fmt, args, false); +} + +/** + * vsscanf_strict - Unformat a buffer into a list of arguments, but + * do not skip spaces. + * @buf: input buffer + * @fmt: format of buffer + * @args: arguments + */ +int vsscanf_strict(const char *buf, const char *fmt, va_list args) +{ + return vsscanf_internal(buf, fmt, args, true); +} + +static int vsscanf_internal(const char *buf, const char *fmt, va_list args, bool strict) { const char *str = buf; char *next; @@ -3530,8 +3549,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args) char *s = (char *)va_arg(args, char *); if (field_width == -1) field_width = SHRT_MAX; - /* first, skip leading white space in buffer */ - str = skip_spaces(str); + if (!strict) { + /* first, skip leading white space in buffer */ + str = skip_spaces(str); + } /* now copy until next white space */ while (*str && !isspace(*str) && field_width--) @@ -3621,7 +3642,8 @@ int vsscanf(const char *buf, const char *fmt, va_list args) /* have some sort of integer conversion. * first, skip white space in buffer. */ - str = skip_spaces(str); + if (!strict) + str = skip_spaces(str); digit = *str; if (is_sign && digit == '-') { @@ -3721,6 +3743,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args) str = next; } + if (strict && *str) + return -EINVAL; + return num; } EXPORT_SYMBOL(vsscanf); @@ -3743,3 +3768,15 @@ int sscanf(const char *buf, const char *fmt, ...) return i; } EXPORT_SYMBOL(sscanf); +int sscanf_strict(const char *buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsscanf_strict(buf, fmt, args); + va_end(args); + + return i; +} +EXPORT_SYMBOL(sscanf_strict); -- Sincerely, Demi Marie Obenour (she/her/hers) Invisible Things Lab