cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kstrtox.c (11087B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Convert integer string representation to an integer.
      4 * If an integer doesn't fit into specified type, -E is returned.
      5 *
      6 * Integer starts with optional sign.
      7 * kstrtou*() functions do not accept sign "-".
      8 *
      9 * Radix 0 means autodetection: leading "0x" implies radix 16,
     10 * leading "0" implies radix 8, otherwise radix is 10.
     11 * Autodetection hints work after optional sign, but not before.
     12 *
     13 * If -E is returned, result is not touched.
     14 */
     15#include <linux/ctype.h>
     16#include <linux/errno.h>
     17#include <linux/export.h>
     18#include <linux/kstrtox.h>
     19#include <linux/math64.h>
     20#include <linux/types.h>
     21#include <linux/uaccess.h>
     22
     23#include "kstrtox.h"
     24
     25noinline
     26const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
     27{
     28	if (*base == 0) {
     29		if (s[0] == '0') {
     30			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
     31				*base = 16;
     32			else
     33				*base = 8;
     34		} else
     35			*base = 10;
     36	}
     37	if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
     38		s += 2;
     39	return s;
     40}
     41
     42/*
     43 * Convert non-negative integer string representation in explicitly given radix
     44 * to an integer. A maximum of max_chars characters will be converted.
     45 *
     46 * Return number of characters consumed maybe or-ed with overflow bit.
     47 * If overflow occurs, result integer (incorrect) is still returned.
     48 *
     49 * Don't you dare use this function.
     50 */
     51noinline
     52unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p,
     53				  size_t max_chars)
     54{
     55	unsigned long long res;
     56	unsigned int rv;
     57
     58	res = 0;
     59	rv = 0;
     60	while (max_chars--) {
     61		unsigned int c = *s;
     62		unsigned int lc = c | 0x20; /* don't tolower() this line */
     63		unsigned int val;
     64
     65		if ('0' <= c && c <= '9')
     66			val = c - '0';
     67		else if ('a' <= lc && lc <= 'f')
     68			val = lc - 'a' + 10;
     69		else
     70			break;
     71
     72		if (val >= base)
     73			break;
     74		/*
     75		 * Check for overflow only if we are within range of
     76		 * it in the max base we support (16)
     77		 */
     78		if (unlikely(res & (~0ull << 60))) {
     79			if (res > div_u64(ULLONG_MAX - val, base))
     80				rv |= KSTRTOX_OVERFLOW;
     81		}
     82		res = res * base + val;
     83		rv++;
     84		s++;
     85	}
     86	*p = res;
     87	return rv;
     88}
     89
     90noinline
     91unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
     92{
     93	return _parse_integer_limit(s, base, p, INT_MAX);
     94}
     95
     96static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
     97{
     98	unsigned long long _res;
     99	unsigned int rv;
    100
    101	s = _parse_integer_fixup_radix(s, &base);
    102	rv = _parse_integer(s, base, &_res);
    103	if (rv & KSTRTOX_OVERFLOW)
    104		return -ERANGE;
    105	if (rv == 0)
    106		return -EINVAL;
    107	s += rv;
    108	if (*s == '\n')
    109		s++;
    110	if (*s)
    111		return -EINVAL;
    112	*res = _res;
    113	return 0;
    114}
    115
    116/**
    117 * kstrtoull - convert a string to an unsigned long long
    118 * @s: The start of the string. The string must be null-terminated, and may also
    119 *  include a single newline before its terminating null. The first character
    120 *  may also be a plus sign, but not a minus sign.
    121 * @base: The number base to use. The maximum supported base is 16. If base is
    122 *  given as 0, then the base of the string is automatically detected with the
    123 *  conventional semantics - If it begins with 0x the number will be parsed as a
    124 *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
    125 *  parsed as an octal number. Otherwise it will be parsed as a decimal.
    126 * @res: Where to write the result of the conversion on success.
    127 *
    128 * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
    129 * Preferred over simple_strtoull(). Return code must be checked.
    130 */
    131noinline
    132int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
    133{
    134	if (s[0] == '+')
    135		s++;
    136	return _kstrtoull(s, base, res);
    137}
    138EXPORT_SYMBOL(kstrtoull);
    139
    140/**
    141 * kstrtoll - convert a string to a long long
    142 * @s: The start of the string. The string must be null-terminated, and may also
    143 *  include a single newline before its terminating null. The first character
    144 *  may also be a plus sign or a minus sign.
    145 * @base: The number base to use. The maximum supported base is 16. If base is
    146 *  given as 0, then the base of the string is automatically detected with the
    147 *  conventional semantics - If it begins with 0x the number will be parsed as a
    148 *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
    149 *  parsed as an octal number. Otherwise it will be parsed as a decimal.
    150 * @res: Where to write the result of the conversion on success.
    151 *
    152 * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
    153 * Preferred over simple_strtoll(). Return code must be checked.
    154 */
    155noinline
    156int kstrtoll(const char *s, unsigned int base, long long *res)
    157{
    158	unsigned long long tmp;
    159	int rv;
    160
    161	if (s[0] == '-') {
    162		rv = _kstrtoull(s + 1, base, &tmp);
    163		if (rv < 0)
    164			return rv;
    165		if ((long long)-tmp > 0)
    166			return -ERANGE;
    167		*res = -tmp;
    168	} else {
    169		rv = kstrtoull(s, base, &tmp);
    170		if (rv < 0)
    171			return rv;
    172		if ((long long)tmp < 0)
    173			return -ERANGE;
    174		*res = tmp;
    175	}
    176	return 0;
    177}
    178EXPORT_SYMBOL(kstrtoll);
    179
    180/* Internal, do not use. */
    181int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
    182{
    183	unsigned long long tmp;
    184	int rv;
    185
    186	rv = kstrtoull(s, base, &tmp);
    187	if (rv < 0)
    188		return rv;
    189	if (tmp != (unsigned long)tmp)
    190		return -ERANGE;
    191	*res = tmp;
    192	return 0;
    193}
    194EXPORT_SYMBOL(_kstrtoul);
    195
    196/* Internal, do not use. */
    197int _kstrtol(const char *s, unsigned int base, long *res)
    198{
    199	long long tmp;
    200	int rv;
    201
    202	rv = kstrtoll(s, base, &tmp);
    203	if (rv < 0)
    204		return rv;
    205	if (tmp != (long)tmp)
    206		return -ERANGE;
    207	*res = tmp;
    208	return 0;
    209}
    210EXPORT_SYMBOL(_kstrtol);
    211
    212/**
    213 * kstrtouint - convert a string to an unsigned int
    214 * @s: The start of the string. The string must be null-terminated, and may also
    215 *  include a single newline before its terminating null. The first character
    216 *  may also be a plus sign, but not a minus sign.
    217 * @base: The number base to use. The maximum supported base is 16. If base is
    218 *  given as 0, then the base of the string is automatically detected with the
    219 *  conventional semantics - If it begins with 0x the number will be parsed as a
    220 *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
    221 *  parsed as an octal number. Otherwise it will be parsed as a decimal.
    222 * @res: Where to write the result of the conversion on success.
    223 *
    224 * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
    225 * Preferred over simple_strtoul(). Return code must be checked.
    226 */
    227noinline
    228int kstrtouint(const char *s, unsigned int base, unsigned int *res)
    229{
    230	unsigned long long tmp;
    231	int rv;
    232
    233	rv = kstrtoull(s, base, &tmp);
    234	if (rv < 0)
    235		return rv;
    236	if (tmp != (unsigned int)tmp)
    237		return -ERANGE;
    238	*res = tmp;
    239	return 0;
    240}
    241EXPORT_SYMBOL(kstrtouint);
    242
    243/**
    244 * kstrtoint - convert a string to an int
    245 * @s: The start of the string. The string must be null-terminated, and may also
    246 *  include a single newline before its terminating null. The first character
    247 *  may also be a plus sign or a minus sign.
    248 * @base: The number base to use. The maximum supported base is 16. If base is
    249 *  given as 0, then the base of the string is automatically detected with the
    250 *  conventional semantics - If it begins with 0x the number will be parsed as a
    251 *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
    252 *  parsed as an octal number. Otherwise it will be parsed as a decimal.
    253 * @res: Where to write the result of the conversion on success.
    254 *
    255 * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
    256 * Preferred over simple_strtol(). Return code must be checked.
    257 */
    258noinline
    259int kstrtoint(const char *s, unsigned int base, int *res)
    260{
    261	long long tmp;
    262	int rv;
    263
    264	rv = kstrtoll(s, base, &tmp);
    265	if (rv < 0)
    266		return rv;
    267	if (tmp != (int)tmp)
    268		return -ERANGE;
    269	*res = tmp;
    270	return 0;
    271}
    272EXPORT_SYMBOL(kstrtoint);
    273
    274noinline
    275int kstrtou16(const char *s, unsigned int base, u16 *res)
    276{
    277	unsigned long long tmp;
    278	int rv;
    279
    280	rv = kstrtoull(s, base, &tmp);
    281	if (rv < 0)
    282		return rv;
    283	if (tmp != (u16)tmp)
    284		return -ERANGE;
    285	*res = tmp;
    286	return 0;
    287}
    288EXPORT_SYMBOL(kstrtou16);
    289
    290noinline
    291int kstrtos16(const char *s, unsigned int base, s16 *res)
    292{
    293	long long tmp;
    294	int rv;
    295
    296	rv = kstrtoll(s, base, &tmp);
    297	if (rv < 0)
    298		return rv;
    299	if (tmp != (s16)tmp)
    300		return -ERANGE;
    301	*res = tmp;
    302	return 0;
    303}
    304EXPORT_SYMBOL(kstrtos16);
    305
    306noinline
    307int kstrtou8(const char *s, unsigned int base, u8 *res)
    308{
    309	unsigned long long tmp;
    310	int rv;
    311
    312	rv = kstrtoull(s, base, &tmp);
    313	if (rv < 0)
    314		return rv;
    315	if (tmp != (u8)tmp)
    316		return -ERANGE;
    317	*res = tmp;
    318	return 0;
    319}
    320EXPORT_SYMBOL(kstrtou8);
    321
    322noinline
    323int kstrtos8(const char *s, unsigned int base, s8 *res)
    324{
    325	long long tmp;
    326	int rv;
    327
    328	rv = kstrtoll(s, base, &tmp);
    329	if (rv < 0)
    330		return rv;
    331	if (tmp != (s8)tmp)
    332		return -ERANGE;
    333	*res = tmp;
    334	return 0;
    335}
    336EXPORT_SYMBOL(kstrtos8);
    337
    338/**
    339 * kstrtobool - convert common user inputs into boolean values
    340 * @s: input string
    341 * @res: result
    342 *
    343 * This routine returns 0 iff the first character is one of 'YyTt1NnFf0', or
    344 * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL.  Value
    345 * pointed to by res is updated upon finding a match.
    346 */
    347noinline
    348int kstrtobool(const char *s, bool *res)
    349{
    350	if (!s)
    351		return -EINVAL;
    352
    353	switch (s[0]) {
    354	case 'y':
    355	case 'Y':
    356	case 't':
    357	case 'T':
    358	case '1':
    359		*res = true;
    360		return 0;
    361	case 'n':
    362	case 'N':
    363	case 'f':
    364	case 'F':
    365	case '0':
    366		*res = false;
    367		return 0;
    368	case 'o':
    369	case 'O':
    370		switch (s[1]) {
    371		case 'n':
    372		case 'N':
    373			*res = true;
    374			return 0;
    375		case 'f':
    376		case 'F':
    377			*res = false;
    378			return 0;
    379		default:
    380			break;
    381		}
    382		break;
    383	default:
    384		break;
    385	}
    386
    387	return -EINVAL;
    388}
    389EXPORT_SYMBOL(kstrtobool);
    390
    391/*
    392 * Since "base" would be a nonsense argument, this open-codes the
    393 * _from_user helper instead of using the helper macro below.
    394 */
    395int kstrtobool_from_user(const char __user *s, size_t count, bool *res)
    396{
    397	/* Longest string needed to differentiate, newline, terminator */
    398	char buf[4];
    399
    400	count = min(count, sizeof(buf) - 1);
    401	if (copy_from_user(buf, s, count))
    402		return -EFAULT;
    403	buf[count] = '\0';
    404	return kstrtobool(buf, res);
    405}
    406EXPORT_SYMBOL(kstrtobool_from_user);
    407
    408#define kstrto_from_user(f, g, type)					\
    409int f(const char __user *s, size_t count, unsigned int base, type *res)	\
    410{									\
    411	/* sign, base 2 representation, newline, terminator */		\
    412	char buf[1 + sizeof(type) * 8 + 1 + 1];				\
    413									\
    414	count = min(count, sizeof(buf) - 1);				\
    415	if (copy_from_user(buf, s, count))				\
    416		return -EFAULT;						\
    417	buf[count] = '\0';						\
    418	return g(buf, base, res);					\
    419}									\
    420EXPORT_SYMBOL(f)
    421
    422kstrto_from_user(kstrtoull_from_user,	kstrtoull,	unsigned long long);
    423kstrto_from_user(kstrtoll_from_user,	kstrtoll,	long long);
    424kstrto_from_user(kstrtoul_from_user,	kstrtoul,	unsigned long);
    425kstrto_from_user(kstrtol_from_user,	kstrtol,	long);
    426kstrto_from_user(kstrtouint_from_user,	kstrtouint,	unsigned int);
    427kstrto_from_user(kstrtoint_from_user,	kstrtoint,	int);
    428kstrto_from_user(kstrtou16_from_user,	kstrtou16,	u16);
    429kstrto_from_user(kstrtos16_from_user,	kstrtos16,	s16);
    430kstrto_from_user(kstrtou8_from_user,	kstrtou8,	u8);
    431kstrto_from_user(kstrtos8_from_user,	kstrtos8,	s8);