No issues found
1 #include "Python.h"
2
3 #if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
4 #define _SGI_MP_SOURCE
5 #endif
6
7 /* strtol and strtoul, renamed to avoid conflicts */
8
9
10 #include <ctype.h>
11 #ifdef HAVE_ERRNO_H
12 #include <errno.h>
13 #endif
14
15 /* Static overflow check values for bases 2 through 36.
16 * smallmax[base] is the largest unsigned long i such that
17 * i * base doesn't overflow unsigned long.
18 */
19 static unsigned long smallmax[] = {
20 0, /* bases 0 and 1 are invalid */
21 0,
22 ULONG_MAX / 2,
23 ULONG_MAX / 3,
24 ULONG_MAX / 4,
25 ULONG_MAX / 5,
26 ULONG_MAX / 6,
27 ULONG_MAX / 7,
28 ULONG_MAX / 8,
29 ULONG_MAX / 9,
30 ULONG_MAX / 10,
31 ULONG_MAX / 11,
32 ULONG_MAX / 12,
33 ULONG_MAX / 13,
34 ULONG_MAX / 14,
35 ULONG_MAX / 15,
36 ULONG_MAX / 16,
37 ULONG_MAX / 17,
38 ULONG_MAX / 18,
39 ULONG_MAX / 19,
40 ULONG_MAX / 20,
41 ULONG_MAX / 21,
42 ULONG_MAX / 22,
43 ULONG_MAX / 23,
44 ULONG_MAX / 24,
45 ULONG_MAX / 25,
46 ULONG_MAX / 26,
47 ULONG_MAX / 27,
48 ULONG_MAX / 28,
49 ULONG_MAX / 29,
50 ULONG_MAX / 30,
51 ULONG_MAX / 31,
52 ULONG_MAX / 32,
53 ULONG_MAX / 33,
54 ULONG_MAX / 34,
55 ULONG_MAX / 35,
56 ULONG_MAX / 36,
57 };
58
59 /* maximum digits that can't ever overflow for bases 2 through 36,
60 * calculated by [int(math.floor(math.log(2**32, i))) for i in range(2, 37)].
61 * Note that this is pessimistic if sizeof(long) > 4.
62 */
63 #if SIZEOF_LONG == 4
64 static int digitlimit[] = {
65 0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
66 9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
67 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
68 6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
69 #elif SIZEOF_LONG == 8
70 /* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
71 static int digitlimit[] = {
72 0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
73 19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
74 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
75 13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
76 #else
77 #error "Need table for SIZEOF_LONG"
78 #endif
79
80 /*
81 ** strtoul
82 ** This is a general purpose routine for converting
83 ** an ascii string to an integer in an arbitrary base.
84 ** Leading white space is ignored. If 'base' is zero
85 ** it looks for a leading 0, 0b, 0B, 0o, 0O, 0x or 0X
86 ** to tell which base. If these are absent it defaults
87 ** to 10. Base must be 0 or between 2 and 36 (inclusive).
88 ** If 'ptr' is non-NULL it will contain a pointer to
89 ** the end of the scan.
90 ** Errors due to bad pointers will probably result in
91 ** exceptions - we don't check for them.
92 */
93 unsigned long
94 PyOS_strtoul(register char *str, char **ptr, int base)
95 {
96 register unsigned long result = 0; /* return value of the function */
97 register int c; /* current input character */
98 register int ovlimit; /* required digits to overflow */
99
100 /* skip leading white space */
101 while (*str && isspace(Py_CHARMASK(*str)))
102 ++str;
103
104 /* check for leading 0 or 0x for auto-base or base 16 */
105 switch (base) {
106 case 0: /* look for leading 0, 0b, 0o or 0x */
107 if (*str == '0') {
108 ++str;
109 if (*str == 'x' || *str == 'X') {
110 /* there must be at least one digit after 0x */
111 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
112 if (ptr)
113 *ptr = str;
114 return 0;
115 }
116 ++str;
117 base = 16;
118 } else if (*str == 'o' || *str == 'O') {
119 /* there must be at least one digit after 0o */
120 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
121 if (ptr)
122 *ptr = str;
123 return 0;
124 }
125 ++str;
126 base = 8;
127 } else if (*str == 'b' || *str == 'B') {
128 /* there must be at least one digit after 0b */
129 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
130 if (ptr)
131 *ptr = str;
132 return 0;
133 }
134 ++str;
135 base = 2;
136 } else {
137 base = 8;
138 }
139 }
140 else
141 base = 10;
142 break;
143
144 case 2: /* skip leading 0b or 0B */
145 if (*str == '0') {
146 ++str;
147 if (*str == 'b' || *str == 'B') {
148 /* there must be at least one digit after 0b */
149 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
150 if (ptr)
151 *ptr = str;
152 return 0;
153 }
154 ++str;
155 }
156 }
157 break;
158
159 case 8: /* skip leading 0o or 0O */
160 if (*str == '0') {
161 ++str;
162 if (*str == 'o' || *str == 'O') {
163 /* there must be at least one digit after 0o */
164 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
165 if (ptr)
166 *ptr = str;
167 return 0;
168 }
169 ++str;
170 }
171 }
172 break;
173
174 case 16: /* skip leading 0x or 0X */
175 if (*str == '0') {
176 ++str;
177 if (*str == 'x' || *str == 'X') {
178 /* there must be at least one digit after 0x */
179 if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
180 if (ptr)
181 *ptr = str;
182 return 0;
183 }
184 ++str;
185 }
186 }
187 break;
188 }
189
190 /* catch silly bases */
191 if (base < 2 || base > 36) {
192 if (ptr)
193 *ptr = str;
194 return 0;
195 }
196
197 /* skip leading zeroes */
198 while (*str == '0')
199 ++str;
200
201 /* base is guaranteed to be in [2, 36] at this point */
202 ovlimit = digitlimit[base];
203
204 /* do the conversion until non-digit character encountered */
205 while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
206 if (ovlimit > 0) /* no overflow check required */
207 result = result * base + c;
208 else { /* requires overflow check */
209 register unsigned long temp_result;
210
211 if (ovlimit < 0) /* guaranteed overflow */
212 goto overflowed;
213
214 /* there could be an overflow */
215 /* check overflow just from shifting */
216 if (result > smallmax[base])
217 goto overflowed;
218
219 result *= base;
220
221 /* check overflow from the digit's value */
222 temp_result = result + c;
223 if (temp_result < result)
224 goto overflowed;
225
226 result = temp_result;
227 }
228
229 ++str;
230 --ovlimit;
231 }
232
233 /* set pointer to point to the last character scanned */
234 if (ptr)
235 *ptr = str;
236
237 return result;
238
239 overflowed:
240 if (ptr) {
241 /* spool through remaining digit characters */
242 while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
243 ++str;
244 *ptr = str;
245 }
246 errno = ERANGE;
247 return (unsigned long)-1;
248 }
249
250 /* Checking for overflow in PyOS_strtol is a PITA; see comments
251 * about PY_ABS_LONG_MIN in longobject.c.
252 */
253 #define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
254
255 long
256 PyOS_strtol(char *str, char **ptr, int base)
257 {
258 long result;
259 unsigned long uresult;
260 char sign;
261
262 while (*str && isspace(Py_CHARMASK(*str)))
263 str++;
264
265 sign = *str;
266 if (sign == '+' || sign == '-')
267 str++;
268
269 uresult = PyOS_strtoul(str, ptr, base);
270
271 if (uresult <= (unsigned long)LONG_MAX) {
272 result = (long)uresult;
273 if (sign == '-')
274 result = -result;
275 }
276 else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
277 result = LONG_MIN;
278 }
279 else {
280 errno = ERANGE;
281 result = LONG_MAX;
282 }
283 return result;
284 }