LCOV - code coverage report
Current view: top level - lib/string - parse_int.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 36 36 100.0 %
Date: 2021-11-24 03:28:48 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2003, Roger Dingledine
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : /**
       7             :  * \file parse_int.c
       8             :  * \brief Convert strings into the integers they encode, with bounds checking.
       9             :  **/
      10             : 
      11             : #include "lib/string/parse_int.h"
      12             : #include "lib/cc/compat_compiler.h"
      13             : 
      14             : #include <errno.h>
      15             : #include <stdlib.h>
      16             : #include <string.h>
      17             : 
      18             : /* Helper: common code to check whether the result of a strtol or strtoul or
      19             :  * strtoll is correct. */
      20             : #define CHECK_STRTOX_RESULT()                           \
      21             :   STMT_BEGIN                                            \
      22             :   /* Did an overflow occur? */                          \
      23             :   if (errno == ERANGE)                                  \
      24             :     goto err;                                           \
      25             :   /* Was at least one character converted? */           \
      26             :   if (endptr == s)                                      \
      27             :     goto err;                                           \
      28             :   /* Were there unexpected unconverted characters? */   \
      29             :   if (!next && *endptr)                                 \
      30             :     goto err;                                           \
      31             :   /* Illogical (max, min) inputs? */                    \
      32             :   if (max < min)                                        \
      33             :     goto err;                                           \
      34             :   /* Is r within limits? */                             \
      35             :   if (r < min || r > max)                               \
      36             :     goto err;                                           \
      37             :   if (ok) *ok = 1;                                      \
      38             :   if (next) *next = endptr;                             \
      39             :   return r;                                             \
      40             :  err:                                                   \
      41             :   if (ok) *ok = 0;                                      \
      42             :   if (next) *next = endptr;                             \
      43             :   return 0;                                             \
      44             :   STMT_END
      45             : 
      46             : /** Extract a long from the start of <b>s</b>, in the given numeric
      47             :  * <b>base</b>.  If <b>base</b> is 0, <b>s</b> is parsed as a decimal,
      48             :  * octal, or hex number in the syntax of a C integer literal.  If
      49             :  * there is unconverted data and <b>next</b> is provided, set
      50             :  * *<b>next</b> to the first unconverted character.  An error has
      51             :  * occurred if no characters are converted; or if there are
      52             :  * unconverted characters and <b>next</b> is NULL; or if the parsed
      53             :  * value is not between <b>min</b> and <b>max</b>.  When no error
      54             :  * occurs, return the parsed value and set *<b>ok</b> (if provided) to
      55             :  * 1.  When an error occurs, return 0 and set *<b>ok</b> (if provided)
      56             :  * to 0.
      57             :  */
      58             : long
      59      185313 : tor_parse_long(const char *s, int base, long min, long max,
      60             :                int *ok, char **next)
      61             : {
      62      185313 :   char *endptr;
      63      185313 :   long r;
      64             : 
      65      185313 :   if (base < 0) {
      66           2 :     if (ok)
      67           1 :       *ok = 0;
      68           2 :     return 0;
      69             :   }
      70             : 
      71      185311 :   errno = 0;
      72      185311 :   r = strtol(s, &endptr, base);
      73      185311 :   CHECK_STRTOX_RESULT();
      74             : }
      75             : 
      76             : /** As tor_parse_long(), but return an unsigned long. */
      77             : unsigned long
      78       60818 : tor_parse_ulong(const char *s, int base, unsigned long min,
      79             :                 unsigned long max, int *ok, char **next)
      80             : {
      81       60818 :   char *endptr;
      82       60818 :   unsigned long r;
      83             : 
      84       60818 :   if (base < 0) {
      85           1 :     if (ok)
      86           1 :       *ok = 0;
      87           1 :     return 0;
      88             :   }
      89             : 
      90       60817 :   errno = 0;
      91       60817 :   r = strtoul(s, &endptr, base);
      92       60817 :   CHECK_STRTOX_RESULT();
      93             : }
      94             : 
      95             : /** As tor_parse_long(), but return a double. */
      96             : double
      97          49 : tor_parse_double(const char *s, double min, double max, int *ok, char **next)
      98             : {
      99          49 :   char *endptr;
     100          49 :   double r;
     101             : 
     102          49 :   errno = 0;
     103          49 :   r = strtod(s, &endptr);
     104          49 :   CHECK_STRTOX_RESULT();
     105             : }
     106             : 
     107             : /** As tor_parse_long, but return a uint64_t.  Only base 10 is guaranteed to
     108             :  * work for now. */
     109             : uint64_t
     110       85543 : tor_parse_uint64(const char *s, int base, uint64_t min,
     111             :                  uint64_t max, int *ok, char **next)
     112             : {
     113       85543 :   char *endptr;
     114       85543 :   uint64_t r;
     115             : 
     116       85543 :   if (base < 0) {
     117           1 :     if (ok)
     118           1 :       *ok = 0;
     119           1 :     return 0;
     120             :   }
     121             : 
     122       85542 :   errno = 0;
     123             : #ifdef HAVE_STRTOULL
     124       85542 :   r = (uint64_t)strtoull(s, &endptr, base);
     125             : #elif defined(_WIN32)
     126             :   r = (uint64_t)_strtoui64(s, &endptr, base);
     127             : #elif SIZEOF_LONG == 8
     128             :   r = (uint64_t)strtoul(s, &endptr, base);
     129             : #else
     130             : #error "I don't know how to parse 64-bit numbers."
     131             : #endif /* defined(HAVE_STRTOULL) || ... */
     132             : 
     133       85542 :   CHECK_STRTOX_RESULT();
     134             : }

Generated by: LCOV version 1.14