Blame view

lib/kstrtox.c 10.4 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * Convert integer string representation to an integer.
   * If an integer doesn't fit into specified type, -E is returned.
   *
   * Integer starts with optional sign.
   * kstrtou*() functions do not accept sign "-".
   *
   * Radix 0 means autodetection: leading "0x" implies radix 16,
   * leading "0" implies radix 8, otherwise radix is 10.
   * Autodetection hints work after optional sign, but not before.
   *
   * If -E is returned, result is not touched.
   */
  #include <linux/ctype.h>
  #include <linux/errno.h>
  #include <linux/kernel.h>
  #include <linux/math64.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
19
  #include <linux/export.h>
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
20
  #include <linux/types.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
21
  #include <linux/uaccess.h>
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
22
  #include "kstrtox.h"
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
23

1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
24
  const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
25
  {
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
26
  	if (*base == 0) {
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
27
28
  		if (s[0] == '0') {
  			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
29
  				*base = 16;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
30
  			else
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
31
  				*base = 8;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
32
  		} else
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
33
  			*base = 10;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
34
  	}
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
35
  	if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
36
  		s += 2;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
37
38
39
40
41
42
43
44
45
46
47
  	return s;
  }
  
  /*
   * Convert non-negative integer string representation in explicitly given radix
   * to an integer.
   * Return number of characters consumed maybe or-ed with overflow bit.
   * If overflow occurs, result integer (incorrect) is still returned.
   *
   * Don't you dare use this function.
   */
690d137f4   David Howells   Reduce the number...
48
  unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
49
  {
690d137f4   David Howells   Reduce the number...
50
  	unsigned long long res;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
51
  	unsigned int rv;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
52

690d137f4   David Howells   Reduce the number...
53
  	res = 0;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
54
  	rv = 0;
512750ef8   Alexey Dobriyan   lib/kstrtox.c: de...
55
  	while (1) {
be5f3c777   Alexey Dobriyan   lib/kstrtox.c: us...
56
57
  		unsigned int c = *s;
  		unsigned int lc = c | 0x20; /* don't tolower() this line */
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
58
  		unsigned int val;
be5f3c777   Alexey Dobriyan   lib/kstrtox.c: us...
59
60
61
62
  		if ('0' <= c && c <= '9')
  			val = c - '0';
  		else if ('a' <= lc && lc <= 'f')
  			val = lc - 'a' + 10;
78be959e3   Alexey Dobriyan   kstrtox: simpler ...
63
  		else
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
64
  			break;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
65
66
  
  		if (val >= base)
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
67
  			break;
690d137f4   David Howells   Reduce the number...
68
69
70
71
72
73
  		/*
  		 * Check for overflow only if we are within range of
  		 * it in the max base we support (16)
  		 */
  		if (unlikely(res & (~0ull << 60))) {
  			if (res > div_u64(ULLONG_MAX - val, base))
8cfd56d47   Alexey Dobriyan   lib/kstrtox.c: sm...
74
  				rv |= KSTRTOX_OVERFLOW;
690d137f4   David Howells   Reduce the number...
75
76
  		}
  		res = res * base + val;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
77
  		rv++;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
78
79
  		s++;
  	}
690d137f4   David Howells   Reduce the number...
80
  	*p = res;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
81
82
83
84
85
86
87
88
89
90
91
92
  	return rv;
  }
  
  static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
  {
  	unsigned long long _res;
  	unsigned int rv;
  
  	s = _parse_integer_fixup_radix(s, &base);
  	rv = _parse_integer(s, base, &_res);
  	if (rv & KSTRTOX_OVERFLOW)
  		return -ERANGE;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
93
94
95
96
97
98
99
  	if (rv == 0)
  		return -EINVAL;
  	s += rv;
  	if (*s == '
  ')
  		s++;
  	if (*s)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
100
  		return -EINVAL;
1dff46d69   Alexey Dobriyan   lib/kstrtox: comm...
101
  	*res = _res;
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
102
103
  	return 0;
  }
4c925d603   Eldad Zack   kstrto*: add docu...
104
105
106
107
108
109
110
111
112
113
114
115
116
  /**
   * kstrtoull - convert a string to an unsigned long long
   * @s: The start of the string. The string must be null-terminated, and may also
   *  include a single newline before its terminating null. The first character
   *  may also be a plus sign, but not a minus sign.
   * @base: The number base to use. The maximum supported base is 16. If base is
   *  given as 0, then the base of the string is automatically detected with the
   *  conventional semantics - If it begins with 0x the number will be parsed as a
   *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
   *  parsed as an octal number. Otherwise it will be parsed as a decimal.
   * @res: Where to write the result of the conversion on success.
   *
   * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
ef0f26853   Kars Mulder   kstrto*: do not d...
117
   * Preferred over simple_strtoull(). Return code must be checked.
4c925d603   Eldad Zack   kstrto*: add docu...
118
   */
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
119
120
121
122
123
124
125
  int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
  {
  	if (s[0] == '+')
  		s++;
  	return _kstrtoull(s, base, res);
  }
  EXPORT_SYMBOL(kstrtoull);
4c925d603   Eldad Zack   kstrto*: add docu...
126
127
128
129
130
131
132
133
134
135
136
137
138
  /**
   * kstrtoll - convert a string to a long long
   * @s: The start of the string. The string must be null-terminated, and may also
   *  include a single newline before its terminating null. The first character
   *  may also be a plus sign or a minus sign.
   * @base: The number base to use. The maximum supported base is 16. If base is
   *  given as 0, then the base of the string is automatically detected with the
   *  conventional semantics - If it begins with 0x the number will be parsed as a
   *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
   *  parsed as an octal number. Otherwise it will be parsed as a decimal.
   * @res: Where to write the result of the conversion on success.
   *
   * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
ef0f26853   Kars Mulder   kstrto*: do not d...
139
   * Preferred over simple_strtoll(). Return code must be checked.
4c925d603   Eldad Zack   kstrto*: add docu...
140
   */
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
141
142
143
144
145
146
147
148
149
  int kstrtoll(const char *s, unsigned int base, long long *res)
  {
  	unsigned long long tmp;
  	int rv;
  
  	if (s[0] == '-') {
  		rv = _kstrtoull(s + 1, base, &tmp);
  		if (rv < 0)
  			return rv;
2d2e4715a   Alexey Dobriyan   kstrto*: accept "...
150
  		if ((long long)-tmp > 0)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  			return -ERANGE;
  		*res = -tmp;
  	} else {
  		rv = kstrtoull(s, base, &tmp);
  		if (rv < 0)
  			return rv;
  		if ((long long)tmp < 0)
  			return -ERANGE;
  		*res = tmp;
  	}
  	return 0;
  }
  EXPORT_SYMBOL(kstrtoll);
  
  /* Internal, do not use. */
  int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
  {
  	unsigned long long tmp;
  	int rv;
  
  	rv = kstrtoull(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
174
  	if (tmp != (unsigned long)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(_kstrtoul);
  
  /* Internal, do not use. */
  int _kstrtol(const char *s, unsigned int base, long *res)
  {
  	long long tmp;
  	int rv;
  
  	rv = kstrtoll(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
190
  	if (tmp != (long)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
191
192
193
194
195
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(_kstrtol);
4c925d603   Eldad Zack   kstrto*: add docu...
196
197
198
199
200
201
202
203
204
205
206
207
208
  /**
   * kstrtouint - convert a string to an unsigned int
   * @s: The start of the string. The string must be null-terminated, and may also
   *  include a single newline before its terminating null. The first character
   *  may also be a plus sign, but not a minus sign.
   * @base: The number base to use. The maximum supported base is 16. If base is
   *  given as 0, then the base of the string is automatically detected with the
   *  conventional semantics - If it begins with 0x the number will be parsed as a
   *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
   *  parsed as an octal number. Otherwise it will be parsed as a decimal.
   * @res: Where to write the result of the conversion on success.
   *
   * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
ef0f26853   Kars Mulder   kstrto*: do not d...
209
   * Preferred over simple_strtoul(). Return code must be checked.
4c925d603   Eldad Zack   kstrto*: add docu...
210
   */
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
211
212
213
214
215
216
217
218
  int kstrtouint(const char *s, unsigned int base, unsigned int *res)
  {
  	unsigned long long tmp;
  	int rv;
  
  	rv = kstrtoull(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
219
  	if (tmp != (unsigned int)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
220
221
222
223
224
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(kstrtouint);
4c925d603   Eldad Zack   kstrto*: add docu...
225
226
227
228
229
230
231
232
233
234
235
236
237
  /**
   * kstrtoint - convert a string to an int
   * @s: The start of the string. The string must be null-terminated, and may also
   *  include a single newline before its terminating null. The first character
   *  may also be a plus sign or a minus sign.
   * @base: The number base to use. The maximum supported base is 16. If base is
   *  given as 0, then the base of the string is automatically detected with the
   *  conventional semantics - If it begins with 0x the number will be parsed as a
   *  hexadecimal (case insensitive), if it otherwise begins with 0, it will be
   *  parsed as an octal number. Otherwise it will be parsed as a decimal.
   * @res: Where to write the result of the conversion on success.
   *
   * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
ef0f26853   Kars Mulder   kstrto*: do not d...
238
   * Preferred over simple_strtol(). Return code must be checked.
4c925d603   Eldad Zack   kstrto*: add docu...
239
   */
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
240
241
242
243
244
245
246
247
  int kstrtoint(const char *s, unsigned int base, int *res)
  {
  	long long tmp;
  	int rv;
  
  	rv = kstrtoll(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
248
  	if (tmp != (int)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(kstrtoint);
  
  int kstrtou16(const char *s, unsigned int base, u16 *res)
  {
  	unsigned long long tmp;
  	int rv;
  
  	rv = kstrtoull(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
263
  	if (tmp != (u16)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(kstrtou16);
  
  int kstrtos16(const char *s, unsigned int base, s16 *res)
  {
  	long long tmp;
  	int rv;
  
  	rv = kstrtoll(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
278
  	if (tmp != (s16)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(kstrtos16);
  
  int kstrtou8(const char *s, unsigned int base, u8 *res)
  {
  	unsigned long long tmp;
  	int rv;
  
  	rv = kstrtoull(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
293
  	if (tmp != (u8)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(kstrtou8);
  
  int kstrtos8(const char *s, unsigned int base, s8 *res)
  {
  	long long tmp;
  	int rv;
  
  	rv = kstrtoll(s, base, &tmp);
  	if (rv < 0)
  		return rv;
048e513d8   Alexey Dobriyan   lib/kstrtox.c: de...
308
  	if (tmp != (s8)tmp)
33ee3b2e2   Alexey Dobriyan   kstrto*: converti...
309
310
311
312
313
  		return -ERANGE;
  	*res = tmp;
  	return 0;
  }
  EXPORT_SYMBOL(kstrtos8);
c196e32a1   Alexey Dobriyan   lib: add kstrto*_...
314

ef9515990   Kees Cook   lib: move strtobo...
315
316
317
318
319
  /**
   * kstrtobool - convert common user inputs into boolean values
   * @s: input string
   * @res: result
   *
a81a5a17d   Kees Cook   lib: add "on"/"of...
320
321
322
   * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
   * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL.  Value
   * pointed to by res is updated upon finding a match.
ef9515990   Kees Cook   lib: move strtobo...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
   */
  int kstrtobool(const char *s, bool *res)
  {
  	if (!s)
  		return -EINVAL;
  
  	switch (s[0]) {
  	case 'y':
  	case 'Y':
  	case '1':
  		*res = true;
  		return 0;
  	case 'n':
  	case 'N':
  	case '0':
  		*res = false;
  		return 0;
a81a5a17d   Kees Cook   lib: add "on"/"of...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  	case 'o':
  	case 'O':
  		switch (s[1]) {
  		case 'n':
  		case 'N':
  			*res = true;
  			return 0;
  		case 'f':
  		case 'F':
  			*res = false;
  			return 0;
  		default:
  			break;
  		}
ef9515990   Kees Cook   lib: move strtobo...
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  	default:
  		break;
  	}
  
  	return -EINVAL;
  }
  EXPORT_SYMBOL(kstrtobool);
  
  /*
   * Since "base" would be a nonsense argument, this open-codes the
   * _from_user helper instead of using the helper macro below.
   */
  int kstrtobool_from_user(const char __user *s, size_t count, bool *res)
  {
  	/* Longest string needed to differentiate, newline, terminator */
  	char buf[4];
  
  	count = min(count, sizeof(buf) - 1);
  	if (copy_from_user(buf, s, count))
  		return -EFAULT;
  	buf[count] = '\0';
  	return kstrtobool(buf, res);
  }
  EXPORT_SYMBOL(kstrtobool_from_user);
c196e32a1   Alexey Dobriyan   lib: add kstrto*_...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
  #define kstrto_from_user(f, g, type)					\
  int f(const char __user *s, size_t count, unsigned int base, type *res)	\
  {									\
  	/* sign, base 2 representation, newline, terminator */		\
  	char buf[1 + sizeof(type) * 8 + 1 + 1];				\
  									\
  	count = min(count, sizeof(buf) - 1);				\
  	if (copy_from_user(buf, s, count))				\
  		return -EFAULT;						\
  	buf[count] = '\0';						\
  	return g(buf, base, res);					\
  }									\
  EXPORT_SYMBOL(f)
  
  kstrto_from_user(kstrtoull_from_user,	kstrtoull,	unsigned long long);
  kstrto_from_user(kstrtoll_from_user,	kstrtoll,	long long);
  kstrto_from_user(kstrtoul_from_user,	kstrtoul,	unsigned long);
  kstrto_from_user(kstrtol_from_user,	kstrtol,	long);
  kstrto_from_user(kstrtouint_from_user,	kstrtouint,	unsigned int);
  kstrto_from_user(kstrtoint_from_user,	kstrtoint,	int);
  kstrto_from_user(kstrtou16_from_user,	kstrtou16,	u16);
  kstrto_from_user(kstrtos16_from_user,	kstrtos16,	s16);
  kstrto_from_user(kstrtou8_from_user,	kstrtou8,	u8);
  kstrto_from_user(kstrtos8_from_user,	kstrtos8,	s8);