Commit d8c03214 authored by Petr Mladek's avatar Petr Mladek

Merge branch 'for-5.14-vsprintf-scanf' into for-linus

parents 80ae5529 d327ea15
...@@ -19395,6 +19395,7 @@ S: Maintained ...@@ -19395,6 +19395,7 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk.git
F: Documentation/core-api/printk-formats.rst F: Documentation/core-api/printk-formats.rst
F: lib/test_printf.c F: lib/test_printf.c
F: lib/test_scanf.c
F: lib/vsprintf.c F: lib/vsprintf.c
VT1211 HARDWARE MONITOR DRIVER VT1211 HARDWARE MONITOR DRIVER
......
...@@ -111,7 +111,7 @@ static inline u32 __seed(u32 x, u32 m) ...@@ -111,7 +111,7 @@ static inline u32 __seed(u32 x, u32 m)
*/ */
static inline void prandom_seed_state(struct rnd_state *state, u64 seed) static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
{ {
u32 i = (seed >> 32) ^ (seed << 10) ^ seed; u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL;
state->s1 = __seed(i, 2U); state->s1 = __seed(i, 2U);
state->s2 = __seed(i, 8U); state->s2 = __seed(i, 8U);
......
...@@ -2163,6 +2163,9 @@ config TEST_KSTRTOX ...@@ -2163,6 +2163,9 @@ config TEST_KSTRTOX
config TEST_PRINTF config TEST_PRINTF
tristate "Test printf() family of functions at runtime" tristate "Test printf() family of functions at runtime"
config TEST_SCANF
tristate "Test scanf() family of functions at runtime"
config TEST_BITMAP config TEST_BITMAP
tristate "Test bitmap_*() family of functions at runtime" tristate "Test bitmap_*() family of functions at runtime"
help help
......
...@@ -83,6 +83,7 @@ obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o ...@@ -83,6 +83,7 @@ obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
obj-$(CONFIG_TEST_PRINTF) += test_printf.o obj-$(CONFIG_TEST_PRINTF) += test_printf.o
obj-$(CONFIG_TEST_SCANF) += test_scanf.o
obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
obj-$(CONFIG_TEST_STRSCPY) += test_strscpy.o obj-$(CONFIG_TEST_STRSCPY) += test_strscpy.o
obj-$(CONFIG_TEST_UUID) += test_uuid.o obj-$(CONFIG_TEST_UUID) += test_uuid.o
......
...@@ -39,20 +39,22 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) ...@@ -39,20 +39,22 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
/* /*
* Convert non-negative integer string representation in explicitly given radix * Convert non-negative integer string representation in explicitly given radix
* to an integer. * to an integer. A maximum of max_chars characters will be converted.
*
* Return number of characters consumed maybe or-ed with overflow bit. * Return number of characters consumed maybe or-ed with overflow bit.
* If overflow occurs, result integer (incorrect) is still returned. * If overflow occurs, result integer (incorrect) is still returned.
* *
* Don't you dare use this function. * Don't you dare use this function.
*/ */
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p) unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
size_t max_chars)
{ {
unsigned long long res; unsigned long long res;
unsigned int rv; unsigned int rv;
res = 0; res = 0;
rv = 0; rv = 0;
while (1) { while (max_chars--) {
unsigned int c = *s; unsigned int c = *s;
unsigned int lc = c | 0x20; /* don't tolower() this line */ unsigned int lc = c | 0x20; /* don't tolower() this line */
unsigned int val; unsigned int val;
...@@ -82,6 +84,11 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long ...@@ -82,6 +84,11 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long
return rv; return rv;
} }
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
{
return _parse_integer_limit(s, base, p, INT_MAX);
}
static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
{ {
unsigned long long _res; unsigned long long _res;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#define KSTRTOX_OVERFLOW (1U << 31) #define KSTRTOX_OVERFLOW (1U << 31)
const char *_parse_integer_fixup_radix(const char *s, unsigned int *base); const char *_parse_integer_fixup_radix(const char *s, unsigned int *base);
unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *res,
size_t max_chars);
unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res); unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res);
#endif #endif
This diff is collapsed.
...@@ -53,6 +53,31 @@ ...@@ -53,6 +53,31 @@
#include <linux/string_helpers.h> #include <linux/string_helpers.h>
#include "kstrtox.h" #include "kstrtox.h"
static unsigned long long simple_strntoull(const char *startp, size_t max_chars,
char **endp, unsigned int base)
{
const char *cp;
unsigned long long result = 0ULL;
size_t prefix_chars;
unsigned int rv;
cp = _parse_integer_fixup_radix(startp, &base);
prefix_chars = cp - startp;
if (prefix_chars < max_chars) {
rv = _parse_integer_limit(cp, base, &result, max_chars - prefix_chars);
/* FIXME */
cp += (rv & ~KSTRTOX_OVERFLOW);
} else {
/* Field too short for prefix + digit, skip over without converting */
cp = startp + max_chars;
}
if (endp)
*endp = (char *)cp;
return result;
}
/** /**
* simple_strtoull - convert a string to an unsigned long long * simple_strtoull - convert a string to an unsigned long long
* @cp: The start of the string * @cp: The start of the string
...@@ -63,18 +88,7 @@ ...@@ -63,18 +88,7 @@
*/ */
unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base)
{ {
unsigned long long result; return simple_strntoull(cp, INT_MAX, endp, base);
unsigned int rv;
cp = _parse_integer_fixup_radix(cp, &base);
rv = _parse_integer(cp, base, &result);
/* FIXME */
cp += (rv & ~KSTRTOX_OVERFLOW);
if (endp)
*endp = (char *)cp;
return result;
} }
EXPORT_SYMBOL(simple_strtoull); EXPORT_SYMBOL(simple_strtoull);
...@@ -109,6 +123,21 @@ long simple_strtol(const char *cp, char **endp, unsigned int base) ...@@ -109,6 +123,21 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
} }
EXPORT_SYMBOL(simple_strtol); EXPORT_SYMBOL(simple_strtol);
static long long simple_strntoll(const char *cp, size_t max_chars, char **endp,
unsigned int base)
{
/*
* simple_strntoull() safely handles receiving max_chars==0 in the
* case cp[0] == '-' && max_chars == 1.
* If max_chars == 0 we can drop through and pass it to simple_strntoull()
* and the content of *cp is irrelevant.
*/
if (*cp == '-' && max_chars > 0)
return -simple_strntoull(cp + 1, max_chars - 1, endp, base);
return simple_strntoull(cp, max_chars, endp, base);
}
/** /**
* simple_strtoll - convert a string to a signed long long * simple_strtoll - convert a string to a signed long long
* @cp: The start of the string * @cp: The start of the string
...@@ -119,10 +148,7 @@ EXPORT_SYMBOL(simple_strtol); ...@@ -119,10 +148,7 @@ EXPORT_SYMBOL(simple_strtol);
*/ */
long long simple_strtoll(const char *cp, char **endp, unsigned int base) long long simple_strtoll(const char *cp, char **endp, unsigned int base)
{ {
if (*cp == '-') return simple_strntoll(cp, INT_MAX, endp, base);
return -simple_strtoull(cp + 1, endp, base);
return simple_strtoull(cp, endp, base);
} }
EXPORT_SYMBOL(simple_strtoll); EXPORT_SYMBOL(simple_strtoll);
...@@ -3538,8 +3564,12 @@ int vsscanf(const char *buf, const char *fmt, va_list args) ...@@ -3538,8 +3564,12 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
str = skip_spaces(str); str = skip_spaces(str);
digit = *str; digit = *str;
if (is_sign && digit == '-') if (is_sign && digit == '-') {
if (field_width == 1)
break;
digit = *(str + 1); digit = *(str + 1);
}
if (!digit if (!digit
|| (base == 16 && !isxdigit(digit)) || (base == 16 && !isxdigit(digit))
...@@ -3549,25 +3579,13 @@ int vsscanf(const char *buf, const char *fmt, va_list args) ...@@ -3549,25 +3579,13 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
break; break;
if (is_sign) if (is_sign)
val.s = qualifier != 'L' ? val.s = simple_strntoll(str,
simple_strtol(str, &next, base) : field_width >= 0 ? field_width : INT_MAX,
simple_strtoll(str, &next, base); &next, base);
else else
val.u = qualifier != 'L' ? val.u = simple_strntoull(str,
simple_strtoul(str, &next, base) : field_width >= 0 ? field_width : INT_MAX,
simple_strtoull(str, &next, base); &next, base);
if (field_width > 0 && next - str > field_width) {
if (base == 0)
_parse_integer_fixup_radix(str, &base);
while (next - str > field_width) {
if (is_sign)
val.s = div_s64(val.s, base);
else
val.u = div_u64(val.u, base);
--next;
}
}
switch (qualifier) { switch (qualifier) {
case 'H': /* that's 'hh' in format */ case 'H': /* that's 'hh' in format */
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" # No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
all: all:
TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh strscpy.sh TEST_PROGS := printf.sh bitmap.sh prime_numbers.sh scanf.sh strscpy.sh
include ../lib.mk include ../lib.mk
CONFIG_TEST_PRINTF=m CONFIG_TEST_PRINTF=m
CONFIG_TEST_SCANF=m
CONFIG_TEST_BITMAP=m CONFIG_TEST_BITMAP=m
CONFIG_PRIME_NUMBERS=m CONFIG_PRIME_NUMBERS=m
CONFIG_TEST_STRSCPY=m CONFIG_TEST_STRSCPY=m
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Tests the scanf infrastructure using test_scanf kernel module.
$(dirname $0)/../kselftest/module.sh "scanf" test_scanf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment