LCOV - code coverage report
Current view: top level - lib - kstrtox.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 73 157 46.5 %
Date: 2021-04-22 12:43:58 Functions: 7 25 28.0 %

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

Generated by: LCOV version 1.14