Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Copyright (C) Swen Schillig 2019
5 : *
6 : * ** NOTE! The following LGPL license applies to this file.
7 : * ** This does NOT imply that all of Samba is released
8 : * ** under the LGPL
9 : *
10 : * This library is free software; you can redistribute it and/or
11 : * modify it under the terms of the GNU Lesser General Public
12 : * License as published by the Free Software Foundation; either
13 : * version 3 of the License, or (at your option) any later version.
14 : *
15 : * This library is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : * Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "replace.h"
25 : #include "smb_strtox.h"
26 :
27 : /**
28 : * Convert a string to an unsigned long integer
29 : *
30 : * @param nptr pointer to string which is to be converted
31 : * @param endptr [optional] reference to remainder of the string
32 : * @param base base of the numbering scheme
33 : * @param err error occured during conversion
34 : * @flags controlling conversion feature
35 : * @result result of the conversion as provided by strtoul
36 : *
37 : * The following flags are supported
38 : * SMB_STR_STANDARD # raise error if negative or non-numeric
39 : * SMB_STR_ALLOW_NEGATIVE # allow strings with a leading "-"
40 : * SMB_STR_FULL_STR_CONV # entire string must be converted
41 : * SMB_STR_ALLOW_NO_CONVERSION # allow empty strings or non-numeric
42 : * SMB_STR_GLIBC_STANDARD # act exactly as the standard glibc strtoul
43 : *
44 : * The following errors are detected
45 : * - wrong base
46 : * - value overflow
47 : * - string with a leading "-" indicating a negative number
48 : * - no conversion due to empty string or not representing a number
49 : */
50 : unsigned long int
51 511277672 : smb_strtoul(const char *nptr, char **endptr, int base, int *err, int flags)
52 : {
53 : unsigned long int val;
54 511277672 : int saved_errno = errno;
55 511277672 : char *needle = NULL;
56 511277672 : char *tmp_endptr = NULL;
57 :
58 511277672 : errno = 0;
59 511277672 : *err = 0;
60 :
61 511277672 : val = strtoul(nptr, &tmp_endptr, base);
62 :
63 511277672 : if (endptr != NULL) {
64 439168326 : *endptr = tmp_endptr;
65 : }
66 :
67 511277672 : if (errno != 0) {
68 0 : *err = errno;
69 0 : errno = saved_errno;
70 0 : return val;
71 : }
72 :
73 511277672 : if ((flags & SMB_STR_ALLOW_NO_CONVERSION) == 0) {
74 : /* got an invalid number-string resulting in no conversion */
75 511277672 : if (nptr == tmp_endptr) {
76 1626 : *err = EINVAL;
77 1626 : goto out;
78 : }
79 : }
80 :
81 511276046 : if ((flags & SMB_STR_ALLOW_NEGATIVE ) == 0) {
82 : /* did we convert a negative "number" ? */
83 511276046 : needle = strchr(nptr, '-');
84 511276046 : if (needle != NULL && needle < tmp_endptr) {
85 2 : *err = EINVAL;
86 2 : goto out;
87 : }
88 : }
89 :
90 511276044 : if ((flags & SMB_STR_FULL_STR_CONV) != 0) {
91 : /* did we convert the entire string ? */
92 479510 : if (tmp_endptr[0] != '\0') {
93 5 : *err = EINVAL;
94 5 : goto out;
95 : }
96 : }
97 :
98 914323048 : out:
99 511277672 : errno = saved_errno;
100 511277672 : return val;
101 : }
102 :
103 : /**
104 : * Convert a string to an unsigned long long integer
105 : *
106 : * @param nptr pointer to string which is to be converted
107 : * @param endptr [optional] reference to remainder of the string
108 : * @param base base of the numbering scheme
109 : * @param err error occured during conversion
110 : * @flags controlling conversion feature
111 : * @result result of the conversion as provided by strtoull
112 : *
113 : * The following flags are supported
114 : * SMB_STR_STANDARD # raise error if negative or non-numeric
115 : * SMB_STR_ALLOW_NEGATIVE # allow strings with a leading "-"
116 : * SMB_STR_FULL_STR_CONV # entire string must be converted
117 : * SMB_STR_ALLOW_NO_CONVERSION # allow empty strings or non-numeric
118 : * SMB_STR_GLIBC_STANDARD # act exactly as the standard glibc strtoul
119 : *
120 : * The following errors are detected
121 : * - wrong base
122 : * - value overflow
123 : * - string with a leading "-" indicating a negative number
124 : * - no conversion due to empty string or not representing a number
125 : */
126 : unsigned long long int
127 46637223 : smb_strtoull(const char *nptr, char **endptr, int base, int *err, int flags)
128 : {
129 : unsigned long long int val;
130 46637223 : int saved_errno = errno;
131 46637223 : char *needle = NULL;
132 46637223 : char *tmp_endptr = NULL;
133 :
134 46637223 : errno = 0;
135 46637223 : *err = 0;
136 :
137 46637223 : val = strtoull(nptr, &tmp_endptr, base);
138 :
139 46637223 : if (endptr != NULL) {
140 45351539 : *endptr = tmp_endptr;
141 : }
142 :
143 46637223 : if (errno != 0) {
144 0 : *err = errno;
145 0 : errno = saved_errno;
146 0 : return val;
147 : }
148 :
149 46637223 : if ((flags & SMB_STR_ALLOW_NO_CONVERSION) == 0) {
150 : /* got an invalid number-string resulting in no conversion */
151 46602522 : if (nptr == tmp_endptr) {
152 6 : *err = EINVAL;
153 6 : goto out;
154 : }
155 : }
156 :
157 46637217 : if ((flags & SMB_STR_ALLOW_NEGATIVE ) == 0) {
158 : /* did we convert a negative "number" ? */
159 46637217 : needle = strchr(nptr, '-');
160 46637217 : if (needle != NULL && needle < tmp_endptr) {
161 0 : *err = EINVAL;
162 0 : goto out;
163 : }
164 : }
165 :
166 46637217 : if ((flags & SMB_STR_FULL_STR_CONV) != 0) {
167 : /* did we convert the entire string ? */
168 1421 : if (tmp_endptr[0] != '\0') {
169 0 : *err = EINVAL;
170 0 : goto out;
171 : }
172 : }
173 :
174 88651914 : out:
175 46637223 : errno = saved_errno;
176 46637223 : return val;
177 : }
|