ยปCore Development>Code coverage>Python/mystrtoul.c

Python code coverage for Python/mystrtoul.c

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