1 /* Convert decimal strings with bounds checking and exit on error.
2
3 Copyright (C) 2014-2023 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17
18 #include <config.h>
19
20 #include "xdectoint.h"
21
22 #include <errno.h>
23 #include <inttypes.h>
24 #include <stddef.h>
25 #include <stdlib.h>
26
27 #include "error.h"
28 #include "quote.h"
29 #include "xstrtol.h"
30
31 /* Parse numeric string N_STR of base BASE, and return the value.
32 Exit on parse error or if MIN or MAX are exceeded.
33 Strings can have multiplicative SUFFIXES if specified.
34 ERR is printed along with N_STR on error. */
35
36 __xdectoint_t
__xnumtoint(char const * n_str,int base,__xdectoint_t min,__xdectoint_t max,char const * suffixes,char const * err,int err_exit)37 __xnumtoint (char const *n_str, int base, __xdectoint_t min, __xdectoint_t max,
38 char const *suffixes, char const *err, int err_exit)
39 {
40 strtol_error s_err;
41
42 __xdectoint_t tnum;
43 s_err = __xstrtol (n_str, nullptr, base, &tnum, suffixes);
44
45 if (s_err == LONGINT_OK)
46 {
47 if (tnum < min || max < tnum)
48 {
49 s_err = LONGINT_OVERFLOW;
50 /* Use have the INT range as a heuristic to distinguish
51 type overflow rather than other min/max limits. */
52 if (tnum > INT_MAX / 2)
53 errno = EOVERFLOW;
54 #if __xdectoint_signed
55 else if (tnum < INT_MIN / 2)
56 errno = EOVERFLOW;
57 #endif
58 else
59 errno = ERANGE;
60 }
61 }
62 else if (s_err == LONGINT_OVERFLOW)
63 errno = EOVERFLOW;
64 else if (s_err == LONGINT_INVALID_SUFFIX_CHAR_WITH_OVERFLOW)
65 errno = 0; /* Don't show ERANGE errors for invalid numbers. */
66
67 if (s_err != LONGINT_OK)
68 {
69 /* EINVAL error message is redundant in this context. */
70 error (err_exit ? err_exit : EXIT_FAILURE, errno == EINVAL ? 0 : errno,
71 "%s: %s", err, quote (n_str));
72 unreachable ();
73 }
74
75 return tnum;
76 }
77
78 /* Parse decimal string N_STR, and return the value.
79 Exit on parse error or if MIN or MAX are exceeded.
80 Strings can have multiplicative SUFFIXES if specified.
81 ERR is printed along with N_STR on error. */
82
83 __xdectoint_t
__xdectoint(char const * n_str,__xdectoint_t min,__xdectoint_t max,char const * suffixes,char const * err,int err_exit)84 __xdectoint (char const *n_str, __xdectoint_t min, __xdectoint_t max,
85 char const *suffixes, char const *err, int err_exit)
86 {
87 return __xnumtoint (n_str, 10, min, max, suffixes, err, err_exit);
88 }
89