Tor  0.4.7.0-alpha-dev
parse_int.c
Go to the documentation of this file.
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 tor_parse_long(const char *s, int base, long min, long max,
60  int *ok, char **next)
61 {
62  char *endptr;
63  long r;
64 
65  if (base < 0) {
66  if (ok)
67  *ok = 0;
68  return 0;
69  }
70 
71  errno = 0;
72  r = strtol(s, &endptr, base);
73  CHECK_STRTOX_RESULT();
74 }
75 
76 /** As tor_parse_long(), but return an unsigned long. */
77 unsigned long
78 tor_parse_ulong(const char *s, int base, unsigned long min,
79  unsigned long max, int *ok, char **next)
80 {
81  char *endptr;
82  unsigned long r;
83 
84  if (base < 0) {
85  if (ok)
86  *ok = 0;
87  return 0;
88  }
89 
90  errno = 0;
91  r = strtoul(s, &endptr, base);
92  CHECK_STRTOX_RESULT();
93 }
94 
95 /** As tor_parse_long(), but return a double. */
96 double
97 tor_parse_double(const char *s, double min, double max, int *ok, char **next)
98 {
99  char *endptr;
100  double r;
101 
102  errno = 0;
103  r = strtod(s, &endptr);
104  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 tor_parse_uint64(const char *s, int base, uint64_t min,
111  uint64_t max, int *ok, char **next)
112 {
113  char *endptr;
114  uint64_t r;
115 
116  if (base < 0) {
117  if (ok)
118  *ok = 0;
119  return 0;
120  }
121 
122  errno = 0;
123 #ifdef HAVE_STRTOULL
124  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  CHECK_STRTOX_RESULT();
134 }
Utility macros to handle different features and behavior in different compilers.
uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, uint64_t max, int *ok, char **next)
Definition: parse_int.c:110
long tor_parse_long(const char *s, int base, long min, long max, int *ok, char **next)
Definition: parse_int.c:59
unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, unsigned long max, int *ok, char **next)
Definition: parse_int.c:78
double tor_parse_double(const char *s, double min, double max, int *ok, char **next)
Definition: parse_int.c:97
Header for parse_int.c.