1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker #include <errno.h>
26*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Worker #include "strtoofft.h"
29*6236dae4SAndroid Build Coastguard Worker
30*6236dae4SAndroid Build Coastguard Worker /*
31*6236dae4SAndroid Build Coastguard Worker * NOTE:
32*6236dae4SAndroid Build Coastguard Worker *
33*6236dae4SAndroid Build Coastguard Worker * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
34*6236dae4SAndroid Build Coastguard Worker * could use in case strtoll() does not exist... See
35*6236dae4SAndroid Build Coastguard Worker * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
36*6236dae4SAndroid Build Coastguard Worker */
37*6236dae4SAndroid Build Coastguard Worker
38*6236dae4SAndroid Build Coastguard Worker #if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
39*6236dae4SAndroid Build Coastguard Worker # ifdef HAVE_STRTOLL
40*6236dae4SAndroid Build Coastguard Worker # define strtooff strtoll
41*6236dae4SAndroid Build Coastguard Worker # else
42*6236dae4SAndroid Build Coastguard Worker # if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
43*6236dae4SAndroid Build Coastguard Worker # if defined(_SAL_VERSION)
44*6236dae4SAndroid Build Coastguard Worker _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
45*6236dae4SAndroid Build Coastguard Worker _In_z_ const char *_String,
46*6236dae4SAndroid Build Coastguard Worker _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
47*6236dae4SAndroid Build Coastguard Worker # else
48*6236dae4SAndroid Build Coastguard Worker _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
49*6236dae4SAndroid Build Coastguard Worker char **_EndPtr, int _Radix);
50*6236dae4SAndroid Build Coastguard Worker # endif
51*6236dae4SAndroid Build Coastguard Worker # define strtooff _strtoi64
52*6236dae4SAndroid Build Coastguard Worker # else
53*6236dae4SAndroid Build Coastguard Worker # define PRIVATE_STRTOOFF 1
54*6236dae4SAndroid Build Coastguard Worker # endif
55*6236dae4SAndroid Build Coastguard Worker # endif
56*6236dae4SAndroid Build Coastguard Worker #else
57*6236dae4SAndroid Build Coastguard Worker # define strtooff strtol
58*6236dae4SAndroid Build Coastguard Worker #endif
59*6236dae4SAndroid Build Coastguard Worker
60*6236dae4SAndroid Build Coastguard Worker #ifdef PRIVATE_STRTOOFF
61*6236dae4SAndroid Build Coastguard Worker
62*6236dae4SAndroid Build Coastguard Worker /* Range tests can be used for alphanum decoding if characters are consecutive,
63*6236dae4SAndroid Build Coastguard Worker like in ASCII. Else an array is scanned. Determine this condition now. */
64*6236dae4SAndroid Build Coastguard Worker
65*6236dae4SAndroid Build Coastguard Worker #if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
66*6236dae4SAndroid Build Coastguard Worker
67*6236dae4SAndroid Build Coastguard Worker #define NO_RANGE_TEST
68*6236dae4SAndroid Build Coastguard Worker
69*6236dae4SAndroid Build Coastguard Worker static const char valchars[] =
70*6236dae4SAndroid Build Coastguard Worker "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
71*6236dae4SAndroid Build Coastguard Worker #endif
72*6236dae4SAndroid Build Coastguard Worker
73*6236dae4SAndroid Build Coastguard Worker static int get_char(char c, int base);
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard Worker /**
76*6236dae4SAndroid Build Coastguard Worker * Custom version of the strtooff function. This extracts a curl_off_t
77*6236dae4SAndroid Build Coastguard Worker * value from the given input string and returns it.
78*6236dae4SAndroid Build Coastguard Worker */
strtooff(const char * nptr,char ** endptr,int base)79*6236dae4SAndroid Build Coastguard Worker static curl_off_t strtooff(const char *nptr, char **endptr, int base)
80*6236dae4SAndroid Build Coastguard Worker {
81*6236dae4SAndroid Build Coastguard Worker char *end;
82*6236dae4SAndroid Build Coastguard Worker bool is_negative = FALSE;
83*6236dae4SAndroid Build Coastguard Worker bool overflow = FALSE;
84*6236dae4SAndroid Build Coastguard Worker int i;
85*6236dae4SAndroid Build Coastguard Worker curl_off_t value = 0;
86*6236dae4SAndroid Build Coastguard Worker
87*6236dae4SAndroid Build Coastguard Worker /* Skip leading whitespace. */
88*6236dae4SAndroid Build Coastguard Worker end = (char *)nptr;
89*6236dae4SAndroid Build Coastguard Worker while(ISBLANK(end[0])) {
90*6236dae4SAndroid Build Coastguard Worker end++;
91*6236dae4SAndroid Build Coastguard Worker }
92*6236dae4SAndroid Build Coastguard Worker
93*6236dae4SAndroid Build Coastguard Worker /* Handle the sign, if any. */
94*6236dae4SAndroid Build Coastguard Worker if(end[0] == '-') {
95*6236dae4SAndroid Build Coastguard Worker is_negative = TRUE;
96*6236dae4SAndroid Build Coastguard Worker end++;
97*6236dae4SAndroid Build Coastguard Worker }
98*6236dae4SAndroid Build Coastguard Worker else if(end[0] == '+') {
99*6236dae4SAndroid Build Coastguard Worker end++;
100*6236dae4SAndroid Build Coastguard Worker }
101*6236dae4SAndroid Build Coastguard Worker else if(end[0] == '\0') {
102*6236dae4SAndroid Build Coastguard Worker /* We had nothing but perhaps some whitespace -- there was no number. */
103*6236dae4SAndroid Build Coastguard Worker if(endptr) {
104*6236dae4SAndroid Build Coastguard Worker *endptr = end;
105*6236dae4SAndroid Build Coastguard Worker }
106*6236dae4SAndroid Build Coastguard Worker return 0;
107*6236dae4SAndroid Build Coastguard Worker }
108*6236dae4SAndroid Build Coastguard Worker
109*6236dae4SAndroid Build Coastguard Worker /* Handle special beginnings, if present and allowed. */
110*6236dae4SAndroid Build Coastguard Worker if(end[0] == '0' && end[1] == 'x') {
111*6236dae4SAndroid Build Coastguard Worker if(base == 16 || base == 0) {
112*6236dae4SAndroid Build Coastguard Worker end += 2;
113*6236dae4SAndroid Build Coastguard Worker base = 16;
114*6236dae4SAndroid Build Coastguard Worker }
115*6236dae4SAndroid Build Coastguard Worker }
116*6236dae4SAndroid Build Coastguard Worker else if(end[0] == '0') {
117*6236dae4SAndroid Build Coastguard Worker if(base == 8 || base == 0) {
118*6236dae4SAndroid Build Coastguard Worker end++;
119*6236dae4SAndroid Build Coastguard Worker base = 8;
120*6236dae4SAndroid Build Coastguard Worker }
121*6236dae4SAndroid Build Coastguard Worker }
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard Worker /* Matching strtol, if the base is 0 and it does not look like
124*6236dae4SAndroid Build Coastguard Worker * the number is octal or hex, we assume it is base 10.
125*6236dae4SAndroid Build Coastguard Worker */
126*6236dae4SAndroid Build Coastguard Worker if(base == 0) {
127*6236dae4SAndroid Build Coastguard Worker base = 10;
128*6236dae4SAndroid Build Coastguard Worker }
129*6236dae4SAndroid Build Coastguard Worker
130*6236dae4SAndroid Build Coastguard Worker /* Loop handling digits. */
131*6236dae4SAndroid Build Coastguard Worker for(i = get_char(end[0], base);
132*6236dae4SAndroid Build Coastguard Worker i != -1;
133*6236dae4SAndroid Build Coastguard Worker end++, i = get_char(end[0], base)) {
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard Worker if(value > (CURL_OFF_T_MAX - i) / base) {
136*6236dae4SAndroid Build Coastguard Worker overflow = TRUE;
137*6236dae4SAndroid Build Coastguard Worker break;
138*6236dae4SAndroid Build Coastguard Worker }
139*6236dae4SAndroid Build Coastguard Worker value = base * value + i;
140*6236dae4SAndroid Build Coastguard Worker }
141*6236dae4SAndroid Build Coastguard Worker
142*6236dae4SAndroid Build Coastguard Worker if(!overflow) {
143*6236dae4SAndroid Build Coastguard Worker if(is_negative) {
144*6236dae4SAndroid Build Coastguard Worker /* Fix the sign. */
145*6236dae4SAndroid Build Coastguard Worker value *= -1;
146*6236dae4SAndroid Build Coastguard Worker }
147*6236dae4SAndroid Build Coastguard Worker }
148*6236dae4SAndroid Build Coastguard Worker else {
149*6236dae4SAndroid Build Coastguard Worker if(is_negative)
150*6236dae4SAndroid Build Coastguard Worker value = CURL_OFF_T_MIN;
151*6236dae4SAndroid Build Coastguard Worker else
152*6236dae4SAndroid Build Coastguard Worker value = CURL_OFF_T_MAX;
153*6236dae4SAndroid Build Coastguard Worker
154*6236dae4SAndroid Build Coastguard Worker errno = ERANGE;
155*6236dae4SAndroid Build Coastguard Worker }
156*6236dae4SAndroid Build Coastguard Worker
157*6236dae4SAndroid Build Coastguard Worker if(endptr)
158*6236dae4SAndroid Build Coastguard Worker *endptr = end;
159*6236dae4SAndroid Build Coastguard Worker
160*6236dae4SAndroid Build Coastguard Worker return value;
161*6236dae4SAndroid Build Coastguard Worker }
162*6236dae4SAndroid Build Coastguard Worker
163*6236dae4SAndroid Build Coastguard Worker /**
164*6236dae4SAndroid Build Coastguard Worker * Returns the value of c in the given base, or -1 if c cannot
165*6236dae4SAndroid Build Coastguard Worker * be interpreted properly in that base (i.e., is out of range,
166*6236dae4SAndroid Build Coastguard Worker * is a null, etc.).
167*6236dae4SAndroid Build Coastguard Worker *
168*6236dae4SAndroid Build Coastguard Worker * @param c the character to interpret according to base
169*6236dae4SAndroid Build Coastguard Worker * @param base the base in which to interpret c
170*6236dae4SAndroid Build Coastguard Worker *
171*6236dae4SAndroid Build Coastguard Worker * @return the value of c in base, or -1 if c is not in range
172*6236dae4SAndroid Build Coastguard Worker */
get_char(char c,int base)173*6236dae4SAndroid Build Coastguard Worker static int get_char(char c, int base)
174*6236dae4SAndroid Build Coastguard Worker {
175*6236dae4SAndroid Build Coastguard Worker #ifndef NO_RANGE_TEST
176*6236dae4SAndroid Build Coastguard Worker int value = -1;
177*6236dae4SAndroid Build Coastguard Worker if(c <= '9' && c >= '0') {
178*6236dae4SAndroid Build Coastguard Worker value = c - '0';
179*6236dae4SAndroid Build Coastguard Worker }
180*6236dae4SAndroid Build Coastguard Worker else if(c <= 'Z' && c >= 'A') {
181*6236dae4SAndroid Build Coastguard Worker value = c - 'A' + 10;
182*6236dae4SAndroid Build Coastguard Worker }
183*6236dae4SAndroid Build Coastguard Worker else if(c <= 'z' && c >= 'a') {
184*6236dae4SAndroid Build Coastguard Worker value = c - 'a' + 10;
185*6236dae4SAndroid Build Coastguard Worker }
186*6236dae4SAndroid Build Coastguard Worker #else
187*6236dae4SAndroid Build Coastguard Worker const char *cp;
188*6236dae4SAndroid Build Coastguard Worker int value;
189*6236dae4SAndroid Build Coastguard Worker
190*6236dae4SAndroid Build Coastguard Worker cp = memchr(valchars, c, 10 + 26 + 26);
191*6236dae4SAndroid Build Coastguard Worker
192*6236dae4SAndroid Build Coastguard Worker if(!cp)
193*6236dae4SAndroid Build Coastguard Worker return -1;
194*6236dae4SAndroid Build Coastguard Worker
195*6236dae4SAndroid Build Coastguard Worker value = cp - valchars;
196*6236dae4SAndroid Build Coastguard Worker
197*6236dae4SAndroid Build Coastguard Worker if(value >= 10 + 26)
198*6236dae4SAndroid Build Coastguard Worker value -= 26; /* Lowercase. */
199*6236dae4SAndroid Build Coastguard Worker #endif
200*6236dae4SAndroid Build Coastguard Worker
201*6236dae4SAndroid Build Coastguard Worker if(value >= base) {
202*6236dae4SAndroid Build Coastguard Worker value = -1;
203*6236dae4SAndroid Build Coastguard Worker }
204*6236dae4SAndroid Build Coastguard Worker
205*6236dae4SAndroid Build Coastguard Worker return value;
206*6236dae4SAndroid Build Coastguard Worker }
207*6236dae4SAndroid Build Coastguard Worker #endif /* Only present if we need strtoll, but do not have it. */
208*6236dae4SAndroid Build Coastguard Worker
209*6236dae4SAndroid Build Coastguard Worker /*
210*6236dae4SAndroid Build Coastguard Worker * Parse a *positive* up to 64-bit number written in ASCII.
211*6236dae4SAndroid Build Coastguard Worker */
curlx_strtoofft(const char * str,char ** endp,int base,curl_off_t * num)212*6236dae4SAndroid Build Coastguard Worker CURLofft curlx_strtoofft(const char *str, char **endp, int base,
213*6236dae4SAndroid Build Coastguard Worker curl_off_t *num)
214*6236dae4SAndroid Build Coastguard Worker {
215*6236dae4SAndroid Build Coastguard Worker char *end = NULL;
216*6236dae4SAndroid Build Coastguard Worker curl_off_t number;
217*6236dae4SAndroid Build Coastguard Worker errno = 0;
218*6236dae4SAndroid Build Coastguard Worker *num = 0; /* clear by default */
219*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(base); /* starting now, avoid base zero */
220*6236dae4SAndroid Build Coastguard Worker
221*6236dae4SAndroid Build Coastguard Worker while(*str && ISBLANK(*str))
222*6236dae4SAndroid Build Coastguard Worker str++;
223*6236dae4SAndroid Build Coastguard Worker if(('-' == *str) || (ISSPACE(*str))) {
224*6236dae4SAndroid Build Coastguard Worker if(endp)
225*6236dae4SAndroid Build Coastguard Worker *endp = (char *)str; /* did not actually move */
226*6236dae4SAndroid Build Coastguard Worker return CURL_OFFT_INVAL; /* nothing parsed */
227*6236dae4SAndroid Build Coastguard Worker }
228*6236dae4SAndroid Build Coastguard Worker number = strtooff(str, &end, base);
229*6236dae4SAndroid Build Coastguard Worker if(endp)
230*6236dae4SAndroid Build Coastguard Worker *endp = end;
231*6236dae4SAndroid Build Coastguard Worker if(errno == ERANGE)
232*6236dae4SAndroid Build Coastguard Worker /* overflow/underflow */
233*6236dae4SAndroid Build Coastguard Worker return CURL_OFFT_FLOW;
234*6236dae4SAndroid Build Coastguard Worker else if(str == end)
235*6236dae4SAndroid Build Coastguard Worker /* nothing parsed */
236*6236dae4SAndroid Build Coastguard Worker return CURL_OFFT_INVAL;
237*6236dae4SAndroid Build Coastguard Worker
238*6236dae4SAndroid Build Coastguard Worker *num = number;
239*6236dae4SAndroid Build Coastguard Worker return CURL_OFFT_OK;
240*6236dae4SAndroid Build Coastguard Worker }
241