xref: /openbmc/linux/lib/kstrtox.c (revision a67ff6a54095e27093ea501fb143fefe51a536c2)
1  /*
2   * Convert integer string representation to an integer.
3   * If an integer doesn't fit into specified type, -E is returned.
4   *
5   * Integer starts with optional sign.
6   * kstrtou*() functions do not accept sign "-".
7   *
8   * Radix 0 means autodetection: leading "0x" implies radix 16,
9   * leading "0" implies radix 8, otherwise radix is 10.
10   * Autodetection hints work after optional sign, but not before.
11   *
12   * If -E is returned, result is not touched.
13   */
14  #include <linux/ctype.h>
15  #include <linux/errno.h>
16  #include <linux/kernel.h>
17  #include <linux/math64.h>
18  #include <linux/module.h>
19  #include <linux/types.h>
20  #include <asm/uaccess.h>
21  #include "kstrtox.h"
22  
23  const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
24  {
25  	if (*base == 0) {
26  		if (s[0] == '0') {
27  			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
28  				*base = 16;
29  			else
30  				*base = 8;
31  		} else
32  			*base = 10;
33  	}
34  	if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
35  		s += 2;
36  	return s;
37  }
38  
39  /*
40   * Convert non-negative integer string representation in explicitly given radix
41   * to an integer.
42   * Return number of characters consumed maybe or-ed with overflow bit.
43   * If overflow occurs, result integer (incorrect) is still returned.
44   *
45   * Don't you dare use this function.
46   */
47  unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res)
48  {
49  	unsigned int rv;
50  	int overflow;
51  
52  	*res = 0;
53  	rv = 0;
54  	overflow = 0;
55  	while (*s) {
56  		unsigned int val;
57  
58  		if ('0' <= *s && *s <= '9')
59  			val = *s - '0';
60  		else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
61  			val = _tolower(*s) - 'a' + 10;
62  		else
63  			break;
64  
65  		if (val >= base)
66  			break;
67  		if (*res > div_u64(ULLONG_MAX - val, base))
68  			overflow = 1;
69  		*res = *res * base + val;
70  		rv++;
71  		s++;
72  	}
73  	if (overflow)
74  		rv |= KSTRTOX_OVERFLOW;
75  	return rv;
76  }
77  
78  static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
79  {
80  	unsigned long long _res;
81  	unsigned int rv;
82  
83  	s = _parse_integer_fixup_radix(s, &base);
84  	rv = _parse_integer(s, base, &_res);
85  	if (rv & KSTRTOX_OVERFLOW)
86  		return -ERANGE;
87  	rv &= ~KSTRTOX_OVERFLOW;
88  	if (rv == 0)
89  		return -EINVAL;
90  	s += rv;
91  	if (*s == '\n')
92  		s++;
93  	if (*s)
94  		return -EINVAL;
95  	*res = _res;
96  	return 0;
97  }
98  
99  int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
100  {
101  	if (s[0] == '+')
102  		s++;
103  	return _kstrtoull(s, base, res);
104  }
105  EXPORT_SYMBOL(kstrtoull);
106  
107  int kstrtoll(const char *s, unsigned int base, long long *res)
108  {
109  	unsigned long long tmp;
110  	int rv;
111  
112  	if (s[0] == '-') {
113  		rv = _kstrtoull(s + 1, base, &tmp);
114  		if (rv < 0)
115  			return rv;
116  		if ((long long)(-tmp) >= 0)
117  			return -ERANGE;
118  		*res = -tmp;
119  	} else {
120  		rv = kstrtoull(s, base, &tmp);
121  		if (rv < 0)
122  			return rv;
123  		if ((long long)tmp < 0)
124  			return -ERANGE;
125  		*res = tmp;
126  	}
127  	return 0;
128  }
129  EXPORT_SYMBOL(kstrtoll);
130  
131  /* Internal, do not use. */
132  int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
133  {
134  	unsigned long long tmp;
135  	int rv;
136  
137  	rv = kstrtoull(s, base, &tmp);
138  	if (rv < 0)
139  		return rv;
140  	if (tmp != (unsigned long long)(unsigned long)tmp)
141  		return -ERANGE;
142  	*res = tmp;
143  	return 0;
144  }
145  EXPORT_SYMBOL(_kstrtoul);
146  
147  /* Internal, do not use. */
148  int _kstrtol(const char *s, unsigned int base, long *res)
149  {
150  	long long tmp;
151  	int rv;
152  
153  	rv = kstrtoll(s, base, &tmp);
154  	if (rv < 0)
155  		return rv;
156  	if (tmp != (long long)(long)tmp)
157  		return -ERANGE;
158  	*res = tmp;
159  	return 0;
160  }
161  EXPORT_SYMBOL(_kstrtol);
162  
163  int kstrtouint(const char *s, unsigned int base, unsigned int *res)
164  {
165  	unsigned long long tmp;
166  	int rv;
167  
168  	rv = kstrtoull(s, base, &tmp);
169  	if (rv < 0)
170  		return rv;
171  	if (tmp != (unsigned long long)(unsigned int)tmp)
172  		return -ERANGE;
173  	*res = tmp;
174  	return 0;
175  }
176  EXPORT_SYMBOL(kstrtouint);
177  
178  int kstrtoint(const char *s, unsigned int base, int *res)
179  {
180  	long long tmp;
181  	int rv;
182  
183  	rv = kstrtoll(s, base, &tmp);
184  	if (rv < 0)
185  		return rv;
186  	if (tmp != (long long)(int)tmp)
187  		return -ERANGE;
188  	*res = tmp;
189  	return 0;
190  }
191  EXPORT_SYMBOL(kstrtoint);
192  
193  int kstrtou16(const char *s, unsigned int base, u16 *res)
194  {
195  	unsigned long long tmp;
196  	int rv;
197  
198  	rv = kstrtoull(s, base, &tmp);
199  	if (rv < 0)
200  		return rv;
201  	if (tmp != (unsigned long long)(u16)tmp)
202  		return -ERANGE;
203  	*res = tmp;
204  	return 0;
205  }
206  EXPORT_SYMBOL(kstrtou16);
207  
208  int kstrtos16(const char *s, unsigned int base, s16 *res)
209  {
210  	long long tmp;
211  	int rv;
212  
213  	rv = kstrtoll(s, base, &tmp);
214  	if (rv < 0)
215  		return rv;
216  	if (tmp != (long long)(s16)tmp)
217  		return -ERANGE;
218  	*res = tmp;
219  	return 0;
220  }
221  EXPORT_SYMBOL(kstrtos16);
222  
223  int kstrtou8(const char *s, unsigned int base, u8 *res)
224  {
225  	unsigned long long tmp;
226  	int rv;
227  
228  	rv = kstrtoull(s, base, &tmp);
229  	if (rv < 0)
230  		return rv;
231  	if (tmp != (unsigned long long)(u8)tmp)
232  		return -ERANGE;
233  	*res = tmp;
234  	return 0;
235  }
236  EXPORT_SYMBOL(kstrtou8);
237  
238  int kstrtos8(const char *s, unsigned int base, s8 *res)
239  {
240  	long long tmp;
241  	int rv;
242  
243  	rv = kstrtoll(s, base, &tmp);
244  	if (rv < 0)
245  		return rv;
246  	if (tmp != (long long)(s8)tmp)
247  		return -ERANGE;
248  	*res = tmp;
249  	return 0;
250  }
251  EXPORT_SYMBOL(kstrtos8);
252  
253  #define kstrto_from_user(f, g, type)					\
254  int f(const char __user *s, size_t count, unsigned int base, type *res)	\
255  {									\
256  	/* sign, base 2 representation, newline, terminator */		\
257  	char buf[1 + sizeof(type) * 8 + 1 + 1];				\
258  									\
259  	count = min(count, sizeof(buf) - 1);				\
260  	if (copy_from_user(buf, s, count))				\
261  		return -EFAULT;						\
262  	buf[count] = '\0';						\
263  	return g(buf, base, res);					\
264  }									\
265  EXPORT_SYMBOL(f)
266  
267  kstrto_from_user(kstrtoull_from_user,	kstrtoull,	unsigned long long);
268  kstrto_from_user(kstrtoll_from_user,	kstrtoll,	long long);
269  kstrto_from_user(kstrtoul_from_user,	kstrtoul,	unsigned long);
270  kstrto_from_user(kstrtol_from_user,	kstrtol,	long);
271  kstrto_from_user(kstrtouint_from_user,	kstrtouint,	unsigned int);
272  kstrto_from_user(kstrtoint_from_user,	kstrtoint,	int);
273  kstrto_from_user(kstrtou16_from_user,	kstrtou16,	u16);
274  kstrto_from_user(kstrtos16_from_user,	kstrtos16,	s16);
275  kstrto_from_user(kstrtou8_from_user,	kstrtou8,	u8);
276  kstrto_from_user(kstrtos8_from_user,	kstrtos8,	s8);
277