Tor 0.4.9.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
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 */
58long
59tor_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. */
77unsigned long
78tor_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. */
96double
97tor_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. */
109uint64_t
110tor_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.