/src/wireshark/wsutil/strtoi.c
Line | Count | Source |
1 | | /* strtoi.c |
2 | | * Utilities to convert strings to integers |
3 | | * |
4 | | * Copyright 2016, Dario Lombardo |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <errno.h> |
16 | | |
17 | | #include <glib.h> |
18 | | |
19 | | #include <jtckdint.h> |
20 | | #include "strtoi.h" |
21 | | #include <wsutil/ws_assert.h> |
22 | | |
23 | | bool ws_strtoi64(const char* str, const char** endptr, int64_t* cint) |
24 | 767 | { |
25 | 767 | char* end; |
26 | 767 | int64_t val; |
27 | | |
28 | 767 | ws_assert(cint); |
29 | | |
30 | 767 | if (!str) { |
31 | 0 | errno = EINVAL; |
32 | 0 | return false; |
33 | 0 | } |
34 | | |
35 | 767 | errno = 0; |
36 | 767 | val = g_ascii_strtoll(str, &end, 10); |
37 | 767 | if ((val == 0 && end == str) || (endptr == NULL && *end != '\0')) { |
38 | 351 | *cint = 0; |
39 | 351 | if (endptr != NULL) |
40 | 1 | *endptr = end; |
41 | 351 | errno = EINVAL; |
42 | 351 | return false; |
43 | 351 | } |
44 | 416 | if ((val == INT64_MAX || val == INT64_MIN) && errno == ERANGE) { |
45 | | /* |
46 | | * Return the value, so our caller knows whether to |
47 | | * report the value as "too small" or "too large". |
48 | | */ |
49 | 51 | *cint = val; |
50 | 51 | if (endptr != NULL) |
51 | 0 | *endptr = end; |
52 | | /* errno is already set */ |
53 | 51 | return false; |
54 | 51 | } |
55 | 365 | if (endptr != NULL) |
56 | 0 | *endptr = end; |
57 | 365 | *cint = val; |
58 | 365 | return true; |
59 | 416 | } |
60 | | |
61 | | #define DEFINE_WS_STRTOI_BITS(bits) \ |
62 | 766 | bool ws_strtoi##bits(const char* str, const char** endptr, int##bits##_t* cint) \ |
63 | 766 | { \ |
64 | 766 | int64_t val = 0; \ |
65 | 766 | if (!ws_strtoi64(str, endptr, &val)) { \ |
66 | 401 | /* \ |
67 | 401 | * For ERANGE, return either INT##bits##_MIN or \ |
68 | 401 | * INT##bits##_MAX so our caller knows whether \ |
69 | 401 | * to report the value as "too small" or "too \ |
70 | 401 | * large". \ |
71 | 401 | * \ |
72 | 401 | * For other errors, return 0, for parallelism \ |
73 | 401 | * with ws_strtoi64(). \ |
74 | 401 | */ \ |
75 | 401 | if (errno == ERANGE) { \ |
76 | 51 | if (val < 0) \ |
77 | 51 | *cint = INT##bits##_MIN; \ |
78 | 51 | else \ |
79 | 51 | *cint = INT##bits##_MAX; \ |
80 | 51 | } else \ |
81 | 401 | *cint = 0; \ |
82 | 401 | return false; \ |
83 | 401 | } \ |
84 | 766 | if (val < INT##bits##_MIN) { \ |
85 | 62 | /* \ |
86 | 62 | * Return INT##bits##_MIN so our caller knows whether to \ |
87 | 62 | * report the value as "too small" or "too large". \ |
88 | 62 | */ \ |
89 | 62 | *cint = INT##bits##_MIN; \ |
90 | 62 | errno = ERANGE; \ |
91 | 62 | return false; \ |
92 | 62 | } \ |
93 | 365 | if (val > INT##bits##_MAX) { \ |
94 | 169 | /* \ |
95 | 169 | * Return INT##bits##_MAX so our caller knows whether to \ |
96 | 169 | * report the value as "too small" or "too large". \ |
97 | 169 | */ \ |
98 | 169 | *cint = INT##bits##_MAX; \ |
99 | 169 | errno = ERANGE; \ |
100 | 169 | return false; \ |
101 | 169 | } \ |
102 | 303 | *cint = (int##bits##_t)val; \ |
103 | 134 | return true; \ |
104 | 303 | } |
105 | | |
106 | 766 | DEFINE_WS_STRTOI_BITS(32) |
107 | 0 | DEFINE_WS_STRTOI_BITS(16) |
108 | 0 | DEFINE_WS_STRTOI_BITS(8) |
109 | | |
110 | | bool ws_strtoi(const char* str, const char** endptr, int* cint) |
111 | 0 | { |
112 | 0 | int64_t val = 0; |
113 | 0 | if (!ws_strtoi64(str, endptr, &val)) { |
114 | | /* |
115 | | * For ERANGE, return either INT_MIN or |
116 | | * INT_MAX so our caller knows whether |
117 | | * to report the value as "too small" or "too |
118 | | * large". |
119 | | * |
120 | | * For other errors, return 0, for parallelism |
121 | | * with ws_strtoi64(). |
122 | | */ |
123 | 0 | if (errno == ERANGE) { |
124 | 0 | if (val < 0) |
125 | 0 | *cint = INT_MIN; |
126 | 0 | else |
127 | 0 | *cint = INT_MAX; |
128 | 0 | } else |
129 | 0 | *cint = 0; |
130 | 0 | return false; |
131 | 0 | } |
132 | 0 | if (val < INT_MIN) { |
133 | | /* |
134 | | * Return INT_MIN so our caller knows whether to |
135 | | * report the value as "too small" or "too large". |
136 | | */ |
137 | 0 | *cint = INT_MIN; |
138 | 0 | errno = ERANGE; |
139 | 0 | return false; |
140 | 0 | } |
141 | 0 | if (val > INT_MAX) { |
142 | | /* |
143 | | * Return INT_MAX so our caller knows whether to |
144 | | * report the value as "too small" or "too large". |
145 | | */ |
146 | 0 | *cint = INT_MAX; |
147 | 0 | errno = ERANGE; |
148 | 0 | return false; |
149 | 0 | } |
150 | 0 | *cint = (int)val; |
151 | 0 | return true; |
152 | 0 | } |
153 | | |
154 | | bool ws_basestrtou64(const char* str, const char** endptr, uint64_t* cint, int base) |
155 | 12.3k | { |
156 | 12.3k | char* end; |
157 | 12.3k | uint64_t val; |
158 | | |
159 | 12.3k | ws_assert(cint); |
160 | | |
161 | 12.3k | if (!str) { |
162 | 0 | errno = EINVAL; |
163 | 0 | return false; |
164 | 0 | } |
165 | | |
166 | 12.3k | if (str[0] == '-' || str[0] == '+') { |
167 | | /* |
168 | | * Unsigned numbers don't have a sign. |
169 | | */ |
170 | 10 | *cint = 0; |
171 | 10 | if (endptr != NULL) |
172 | 0 | *endptr = str; |
173 | 10 | errno = EINVAL; |
174 | 10 | return false; |
175 | 10 | } |
176 | 12.3k | errno = 0; |
177 | 12.3k | val = g_ascii_strtoull(str, &end, base); |
178 | 12.3k | if ((val == 0 && end == str) || (endptr == NULL && *end != '\0')) { |
179 | 685 | *cint = 0; |
180 | 685 | if (endptr != NULL) |
181 | 0 | *endptr = end; |
182 | 685 | errno = EINVAL; |
183 | 685 | return false; |
184 | 685 | } |
185 | 11.6k | if (val == UINT64_MAX && errno == ERANGE) { |
186 | | /* |
187 | | * Return the value, because ws_strtoi64() does. |
188 | | */ |
189 | 8 | *cint = val; |
190 | 8 | if (endptr != NULL) |
191 | 0 | *endptr = end; |
192 | | /* errno is already set */ |
193 | 8 | return false; |
194 | 8 | } |
195 | 11.6k | if (endptr != NULL) |
196 | 10.9k | *endptr = end; |
197 | 11.6k | *cint = val; |
198 | 11.6k | return true; |
199 | 11.6k | } |
200 | | |
201 | | bool ws_strtou64(const char* str, const char** endptr, uint64_t* cint) |
202 | 14 | { |
203 | 14 | return ws_basestrtou64(str, endptr, cint, 10); |
204 | 14 | } |
205 | | |
206 | | bool ws_hexstrtou64(const char* str, const char** endptr, uint64_t* cint) |
207 | 0 | { |
208 | 0 | return ws_basestrtou64(str, endptr, cint, 16); |
209 | 0 | } |
210 | | |
211 | | #define DEFINE_WS_STRTOU_BITS(bits) \ |
212 | 12.3k | bool ws_basestrtou##bits(const char* str, const char** endptr, uint##bits##_t* cint, int base) \ |
213 | 12.3k | { \ |
214 | 12.3k | uint64_t val; \ |
215 | 12.3k | if (!ws_basestrtou64(str, endptr, &val, base)) { \ |
216 | 689 | /* \ |
217 | 689 | * For ERANGE, return UINT##bits##_MAX for parallelism \ |
218 | 689 | * with ws_strtoi##bits(). \ |
219 | 689 | * \ |
220 | 689 | * For other errors, return 0, for parallelism \ |
221 | 689 | * with ws_basestrtou64(). \ |
222 | 689 | */ \ |
223 | 689 | if (errno == ERANGE) \ |
224 | 689 | *cint = UINT##bits##_MAX; \ |
225 | 689 | else \ |
226 | 689 | *cint = 0; \ |
227 | 689 | return false; \ |
228 | 689 | } \ |
229 | 12.3k | if (val > UINT##bits##_MAX) { \ |
230 | 25 | /* \ |
231 | 25 | * Return UINT##bits##_MAX for parallelism with \ |
232 | 25 | * ws_strtoi##bits(). \ |
233 | 25 | */ \ |
234 | 25 | *cint = UINT##bits##_MAX; \ |
235 | 25 | errno = ERANGE; \ |
236 | 25 | return false; \ |
237 | 25 | } \ |
238 | 11.6k | *cint = (uint##bits##_t)val; \ |
239 | 11.6k | return true; \ |
240 | 11.6k | } \ |
241 | | \ |
242 | 726 | bool ws_strtou##bits(const char* str, const char** endptr, uint##bits##_t* cint) \ |
243 | 726 | { \ |
244 | 726 | return ws_basestrtou##bits(str, endptr, cint, 10); \ |
245 | 726 | } \ Line | Count | Source | 242 | 464 | bool ws_strtou##bits(const char* str, const char** endptr, uint##bits##_t* cint) \ | 243 | 464 | { \ | 244 | 464 | return ws_basestrtou##bits(str, endptr, cint, 10); \ | 245 | 464 | } \ |
Line | Count | Source | 242 | 251 | bool ws_strtou##bits(const char* str, const char** endptr, uint##bits##_t* cint) \ | 243 | 251 | { \ | 244 | 251 | return ws_basestrtou##bits(str, endptr, cint, 10); \ | 245 | 251 | } \ |
Line | Count | Source | 242 | 11 | bool ws_strtou##bits(const char* str, const char** endptr, uint##bits##_t* cint) \ | 243 | 11 | { \ | 244 | 11 | return ws_basestrtou##bits(str, endptr, cint, 10); \ | 245 | 11 | } \ |
|
246 | | \ |
247 | 619 | bool ws_hexstrtou##bits(const char* str, const char** endptr, uint##bits##_t* cint) \ |
248 | 619 | { \ |
249 | 619 | return ws_basestrtou##bits(str, endptr, cint, 16); \ |
250 | 619 | } Line | Count | Source | 247 | 619 | bool ws_hexstrtou##bits(const char* str, const char** endptr, uint##bits##_t* cint) \ | 248 | 619 | { \ | 249 | 619 | return ws_basestrtou##bits(str, endptr, cint, 16); \ | 250 | 619 | } |
Unexecuted instantiation: ws_hexstrtou16 Unexecuted instantiation: ws_hexstrtou8 |
251 | | |
252 | 12.0k | DEFINE_WS_STRTOU_BITS(32) |
253 | 251 | DEFINE_WS_STRTOU_BITS(16) |
254 | 11 | DEFINE_WS_STRTOU_BITS(8) |
255 | | |
256 | | bool ws_basestrtou(const char* str, const char** endptr, unsigned* cint, int base) |
257 | 0 | { |
258 | 0 | uint64_t val; |
259 | 0 | if (!ws_basestrtou64(str, endptr, &val, base)) { |
260 | | /* |
261 | | * For ERANGE, return UINT_MAX for parallelism |
262 | | * with ws_strtoi(). |
263 | | * |
264 | | * For other errors, return 0, for parallelism |
265 | | * with ws_basestrtou64(). |
266 | | */ |
267 | 0 | if (errno == ERANGE) |
268 | 0 | *cint = UINT_MAX; |
269 | 0 | else |
270 | 0 | *cint = 0; |
271 | 0 | return false; |
272 | 0 | } |
273 | 0 | if (val > UINT_MAX) { |
274 | | /* |
275 | | * Return UINT_MAX for parallelism with |
276 | | * ws_strtoi(). |
277 | | */ |
278 | 0 | *cint = UINT_MAX; |
279 | 0 | errno = ERANGE; |
280 | 0 | return false; |
281 | 0 | } |
282 | 0 | *cint = (unsigned)val; |
283 | 0 | return true; |
284 | 0 | } |
285 | | |
286 | | bool ws_strtou(const char* str, const char** endptr, unsigned* cint) |
287 | 0 | { |
288 | 0 | return ws_basestrtou(str, endptr, cint, 10); |
289 | 0 | } |
290 | | |
291 | | bool ws_hexstrtou(const char* str, const char** endptr, unsigned* cint) |
292 | 0 | { |
293 | 0 | return ws_basestrtou(str, endptr, cint, 16); |
294 | 0 | } |
295 | | |
296 | | static int |
297 | | ws_parse_long_long(const uint8_t *buf, size_t len, const uint8_t **endptr, uint64_t *cint, int base) |
298 | 20.8k | { |
299 | | /* This code is derived from the g_parse_long_long code from GLib |
300 | | * which itself is derived from the strtol(3) code from GNU libc |
301 | | * (and, thus, GNUlib), both released under the GNU Lesser General |
302 | | * Public License v 2.1, opting to apply the terms of the ordinarly |
303 | | * GNU General Public License, version 2, as allowed under section |
304 | | * 3 of that license. |
305 | | * |
306 | | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
307 | | * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02 |
308 | | * Free Software Foundation, Inc. |
309 | | */ |
310 | | |
311 | 20.8k | const uint8_t *save; |
312 | 20.8k | const uint8_t *hex_x = NULL; |
313 | 20.8k | uint64_t val, cutoff, cutlim; |
314 | 20.8k | unsigned char c; |
315 | 20.8k | bool overflow = false; |
316 | | |
317 | 20.8k | if (*buf == '0') { |
318 | 5.43k | if ((len > 1) && (base == 0 || base == 16) && g_ascii_toupper(buf[1]) == 'X') { |
319 | 18 | hex_x = &buf[1]; |
320 | 18 | buf += 2; |
321 | 18 | len -= 2; |
322 | 18 | base = 16; |
323 | 5.42k | } else if (base == 0) { |
324 | 0 | base = 8; |
325 | 0 | } |
326 | 15.4k | } else if (base == 0) { |
327 | 0 | base = 10; |
328 | 0 | } |
329 | | |
330 | 20.8k | save = buf; |
331 | 20.8k | cutoff = UINT64_MAX / base; |
332 | 20.8k | cutlim = UINT64_MAX % base; |
333 | | |
334 | 20.8k | val = 0; |
335 | 64.4k | for (; len; --len) { |
336 | 49.4k | c = *buf; |
337 | 49.4k | if (c >= '0' && c <= '9') { |
338 | 42.1k | c -= '0'; |
339 | 42.1k | } else if (g_ascii_isalpha(c)) { |
340 | 3.69k | c = g_ascii_toupper(c) - 'A' + 10; |
341 | 3.69k | } else { |
342 | 3.60k | break; |
343 | 3.60k | } |
344 | 45.8k | if (c >= base) { |
345 | 2.18k | break; |
346 | 2.18k | } |
347 | 43.6k | buf++; |
348 | | /* Check for overflow */ |
349 | 43.6k | if (val > cutoff || (val == cutoff && c > cutlim)) { |
350 | 156 | overflow = true; |
351 | 156 | if (endptr == NULL) { |
352 | | /* If we don't care about the end, just stop */ |
353 | 77 | *cint = UINT64_MAX; |
354 | 77 | return ERANGE; |
355 | 77 | } |
356 | 43.4k | } else { |
357 | 43.4k | val *= base; |
358 | 43.4k | val += c; |
359 | 43.4k | } |
360 | 43.6k | } |
361 | | |
362 | 20.8k | if (buf == save) { |
363 | | /* no conversion. We call that failure, except for the |
364 | | * corner case of base 0 or 16 and starting with "0x", |
365 | | * which converts to 0 and first invalid is the "x". */ |
366 | 4.44k | *cint = 0; |
367 | 4.44k | if (endptr != NULL) { |
368 | 943 | if (hex_x) { |
369 | 0 | *endptr = hex_x; |
370 | 0 | return 0; |
371 | 0 | } |
372 | 943 | *endptr = buf; |
373 | 943 | } |
374 | 4.44k | return EINVAL; |
375 | 4.44k | } |
376 | | |
377 | 16.3k | if (len && endptr == NULL) { |
378 | 1.35k | *cint = 0; |
379 | 1.35k | return EINVAL; |
380 | 1.35k | } |
381 | | |
382 | 15.0k | if (endptr != NULL) { |
383 | | /* This can point one past the end if fully converted; that is legal |
384 | | * in C, but cannot be dereferenced. The caller should have enough |
385 | | * information to know not to dereference it in that case. */ |
386 | 20 | *endptr = buf; |
387 | 20 | } |
388 | | |
389 | 15.0k | if (G_UNLIKELY(overflow)) { |
390 | 2 | *cint = UINT64_MAX; |
391 | 2 | return ERANGE; |
392 | 2 | } |
393 | | |
394 | 15.0k | *cint = val; |
395 | 15.0k | return 0; |
396 | 15.0k | } |
397 | | |
398 | | bool ws_basebuftou64(const uint8_t* buf, size_t len, const uint8_t** endptr, uint64_t* cint, int base) |
399 | 22.8k | { |
400 | | /* This code is derived from the g_parse_long_long code from GLib |
401 | | * which itself is derived from the strtol(3) code from GNU libc |
402 | | * (and, thus, GNUlib), both released under the GNU Lesser General |
403 | | * Public License v 2.1, opting to apply the terms of the ordinarly |
404 | | * GNU General Public License, version 2, as allowed under section |
405 | | * 3 of that license. |
406 | | * |
407 | | * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald |
408 | | * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02 |
409 | | * Free Software Foundation, Inc. |
410 | | */ |
411 | 22.8k | const uint8_t *end = buf; |
412 | 22.8k | int err; |
413 | | |
414 | 22.8k | ws_assert(cint); |
415 | | |
416 | 22.8k | if (!buf) { |
417 | 0 | #ifdef WS_ASSERT_ENABLED |
418 | 0 | ws_warn_badarg("!buf"); |
419 | 0 | #endif |
420 | 0 | errno = EINVAL; |
421 | 0 | return false; |
422 | 0 | } |
423 | | |
424 | 22.8k | if (buf[0] == '\0' || buf[0] == '-' || buf[0] == '+') { |
425 | | /* |
426 | | * Unsigned numbers don't have a sign. |
427 | | */ |
428 | 1.72k | *cint = 0; |
429 | 1.72k | if (endptr != NULL) |
430 | 57 | *endptr = buf; |
431 | 1.72k | errno = EINVAL; |
432 | 1.72k | return false; |
433 | 1.72k | } |
434 | | |
435 | 21.1k | if (len == 0 || base == 1 || base > 36) { |
436 | 0 | *cint = 0; |
437 | 0 | if (endptr != NULL) |
438 | 0 | *endptr = buf; |
439 | 0 | errno = EINVAL; |
440 | 0 | return false; |
441 | 0 | } |
442 | | |
443 | | /* Skip white space (we could not) */ |
444 | 21.1k | while (g_ascii_isspace(*end)) { |
445 | 653 | ++end; |
446 | 653 | if (--len == 0) { |
447 | 247 | *cint = 0; |
448 | 247 | if (endptr != NULL) |
449 | 0 | *endptr = buf; |
450 | 247 | errno = EINVAL; |
451 | 247 | return false; |
452 | 247 | } |
453 | 653 | } |
454 | | |
455 | 20.8k | err = ws_parse_long_long(end, len, endptr, cint, base); |
456 | 20.8k | errno = err; |
457 | 20.8k | return !err; |
458 | 21.1k | } |
459 | | |
460 | | bool ws_buftou64(const uint8_t* buf, size_t len, const uint8_t** endptr, uint64_t* cint) |
461 | 0 | { |
462 | 0 | return ws_basebuftou64(buf, len, endptr, cint, 10); |
463 | 0 | } |
464 | | |
465 | | bool ws_hexbuftou64(const uint8_t* buf, size_t len, const uint8_t** endptr, uint64_t* cint) |
466 | 0 | { |
467 | 0 | return ws_basebuftou64(buf, len, endptr, cint, 16); |
468 | 0 | } |
469 | | |
470 | | #define DEFINE_WS_BUFTOU_BITS(bits) \ |
471 | 22.8k | bool ws_basebuftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint, int base) \ |
472 | 22.8k | { \ |
473 | 22.8k | uint64_t val; \ |
474 | 22.8k | if (!ws_basebuftou64(buf, len, endptr, &val, base)) { \ |
475 | 7.84k | /* \ |
476 | 7.84k | * For ERANGE, return UINT##bits##_MAX for parallelism \ |
477 | 7.84k | * with ws_strtoi##bits(). \ |
478 | 7.84k | * \ |
479 | 7.84k | * For other errors, return 0, for parallelism \ |
480 | 7.84k | * with ws_basestrtou64(). \ |
481 | 7.84k | */ \ |
482 | 7.84k | if (errno == ERANGE) \ |
483 | 7.84k | *cint = UINT##bits##_MAX; \ |
484 | 7.84k | else \ |
485 | 7.84k | *cint = 0; \ |
486 | 7.84k | return false; \ |
487 | 7.84k | } \ |
488 | 22.8k | if (val > UINT##bits##_MAX) { \ |
489 | 60 | /* \ |
490 | 60 | * Return UINT##bits##_MAX for parallelism with \ |
491 | 60 | * ws_strtoi##bits(). \ |
492 | 60 | */ \ |
493 | 60 | *cint = UINT##bits##_MAX; \ |
494 | 60 | errno = ERANGE; \ |
495 | 60 | return false; \ |
496 | 60 | } \ |
497 | 15.0k | *cint = (uint##bits##_t)val; \ |
498 | 14.9k | return true; \ |
499 | 15.0k | } \ |
500 | | \ |
501 | 14.6k | bool ws_buftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ |
502 | 14.6k | { \ |
503 | 14.6k | return ws_basebuftou##bits(buf, len, endptr, cint, 10); \ |
504 | 14.6k | } \ Line | Count | Source | 501 | 105 | bool ws_buftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ | 502 | 105 | { \ | 503 | 105 | return ws_basebuftou##bits(buf, len, endptr, cint, 10); \ | 504 | 105 | } \ |
Line | Count | Source | 501 | 14.4k | bool ws_buftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ | 502 | 14.4k | { \ | 503 | 14.4k | return ws_basebuftou##bits(buf, len, endptr, cint, 10); \ | 504 | 14.4k | } \ |
Line | Count | Source | 501 | 51 | bool ws_buftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ | 502 | 51 | { \ | 503 | 51 | return ws_basebuftou##bits(buf, len, endptr, cint, 10); \ | 504 | 51 | } \ |
|
505 | | \ |
506 | 8.21k | bool ws_hexbuftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ |
507 | 8.21k | { \ |
508 | 8.21k | return ws_basebuftou##bits(buf, len, endptr, cint, 16); \ |
509 | 8.21k | } Line | Count | Source | 506 | 412 | bool ws_hexbuftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ | 507 | 412 | { \ | 508 | 412 | return ws_basebuftou##bits(buf, len, endptr, cint, 16); \ | 509 | 412 | } |
Line | Count | Source | 506 | 1 | bool ws_hexbuftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ | 507 | 1 | { \ | 508 | 1 | return ws_basebuftou##bits(buf, len, endptr, cint, 16); \ | 509 | 1 | } |
Line | Count | Source | 506 | 7.80k | bool ws_hexbuftou##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, uint##bits##_t* cint) \ | 507 | 7.80k | { \ | 508 | 7.80k | return ws_basebuftou##bits(buf, len, endptr, cint, 16); \ | 509 | 7.80k | } |
|
510 | | |
511 | 517 | DEFINE_WS_BUFTOU_BITS(32) |
512 | 14.4k | DEFINE_WS_BUFTOU_BITS(16) |
513 | 7.85k | DEFINE_WS_BUFTOU_BITS(8) |
514 | | |
515 | | bool ws_basebuftoi64(const uint8_t* buf, size_t len, const uint8_t** endptr, int64_t* cint, int base) |
516 | 0 | { |
517 | 0 | const uint8_t *end = buf; |
518 | 0 | uint64_t val; |
519 | 0 | bool negative = false; |
520 | 0 | int err; |
521 | |
|
522 | 0 | ws_assert(cint); |
523 | |
|
524 | 0 | if (!buf) { |
525 | 0 | #ifdef WS_ASSERT_ENABLED |
526 | 0 | ws_warn_badarg("!buf"); |
527 | 0 | #endif |
528 | 0 | errno = EINVAL; |
529 | 0 | return false; |
530 | 0 | } |
531 | | |
532 | 0 | if (buf[0] == '\0') { |
533 | 0 | *cint = 0; |
534 | 0 | if (endptr != NULL) |
535 | 0 | *endptr = buf; |
536 | 0 | errno = EINVAL; |
537 | 0 | return false; |
538 | 0 | } |
539 | | |
540 | 0 | if (len == 0 || base == 1 || base > 36) { |
541 | 0 | *cint = 0; |
542 | 0 | if (endptr != NULL) |
543 | 0 | *endptr = buf; |
544 | 0 | errno = EINVAL; |
545 | 0 | return false; |
546 | 0 | } |
547 | | |
548 | | /* Skip white space (we could not) */ |
549 | 0 | while (g_ascii_isspace(*end)) { |
550 | 0 | ++end; |
551 | 0 | if (--len == 0) { |
552 | 0 | *cint = 0; |
553 | 0 | if (endptr != NULL) |
554 | 0 | *endptr = buf; |
555 | 0 | errno = EINVAL; |
556 | 0 | return false; |
557 | 0 | } |
558 | 0 | } |
559 | | |
560 | 0 | if (*end == '+') { |
561 | 0 | ++end; |
562 | 0 | --len; |
563 | 0 | } else if (*end == '-') { |
564 | 0 | negative = true; |
565 | 0 | ++end; |
566 | 0 | --len; |
567 | 0 | } |
568 | |
|
569 | 0 | err = ws_parse_long_long(end, len, endptr, &val, base); |
570 | 0 | if (err == EINVAL) { |
571 | 0 | *cint = 0; |
572 | 0 | errno = EINVAL; |
573 | 0 | return false; |
574 | 0 | } |
575 | | |
576 | 0 | if (negative) { |
577 | 0 | if (ckd_mul(cint, val, -1)) { |
578 | 0 | *cint = INT64_MIN; |
579 | 0 | errno = ERANGE; |
580 | 0 | return false; |
581 | 0 | } |
582 | 0 | } else { |
583 | 0 | if (ckd_mul(cint, val, 1)) { |
584 | 0 | *cint = INT64_MAX; |
585 | 0 | errno = ERANGE; |
586 | 0 | return false; |
587 | 0 | } |
588 | 0 | } |
589 | | |
590 | 0 | return true; |
591 | 0 | } |
592 | | |
593 | | bool ws_buftoi64(const uint8_t* buf, size_t len, const uint8_t** endptr, int64_t* cint) |
594 | 0 | { |
595 | 0 | return ws_basebuftoi64(buf, len, endptr, cint, 10); |
596 | 0 | } |
597 | | |
598 | | bool ws_hexbuftoi64(const uint8_t* buf, size_t len, const uint8_t** endptr, int64_t* cint) |
599 | 0 | { |
600 | 0 | return ws_basebuftoi64(buf, len, endptr, cint, 16); |
601 | 0 | } |
602 | | |
603 | | #define DEFINE_WS_BUFTOI_BITS(bits) \ |
604 | 0 | bool ws_basebuftoi##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, int##bits##_t* cint, int base) \ |
605 | 0 | { \ |
606 | 0 | int64_t val = 0; \ |
607 | 0 | if (!ws_basebuftoi64(buf, len, endptr, &val, base)) { \ |
608 | 0 | /* \ |
609 | 0 | * For ERANGE, return either INT##bits##_MIN or \ |
610 | 0 | * INT##bits##_MAX so our caller knows whether \ |
611 | 0 | * to report the value as "too small" or "too \ |
612 | 0 | * large". \ |
613 | 0 | * \ |
614 | 0 | * For other errors, return 0, for parallelism \ |
615 | 0 | * with ws_strtoi64(). \ |
616 | 0 | */ \ |
617 | 0 | if (errno == ERANGE) { \ |
618 | 0 | if (val < 0) \ |
619 | 0 | *cint = INT##bits##_MIN; \ |
620 | 0 | else \ |
621 | 0 | *cint = INT##bits##_MAX; \ |
622 | 0 | } else \ |
623 | 0 | *cint = 0; \ |
624 | 0 | return false; \ |
625 | 0 | } \ |
626 | 0 | if (val < INT##bits##_MIN) { \ |
627 | 0 | /* \ |
628 | 0 | * Return INT##bits##_MIN so our caller knows whether to \ |
629 | 0 | * report the value as "too small" or "too large". \ |
630 | 0 | */ \ |
631 | 0 | *cint = INT##bits##_MIN; \ |
632 | 0 | errno = ERANGE; \ |
633 | 0 | return false; \ |
634 | 0 | } \ |
635 | 0 | if (val > INT##bits##_MAX) { \ |
636 | 0 | /* \ |
637 | 0 | * Return INT##bits##_MAX so our caller knows whether to \ |
638 | 0 | * report the value as "too small" or "too large". \ |
639 | 0 | */ \ |
640 | 0 | *cint = INT##bits##_MAX; \ |
641 | 0 | errno = ERANGE; \ |
642 | 0 | return false; \ |
643 | 0 | } \ |
644 | 0 | *cint = (int##bits##_t)val; \ |
645 | 0 | return true; \ |
646 | 0 | } \ |
647 | | \ |
648 | 0 | bool ws_buftoi##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, int##bits##_t* cint) \ |
649 | 0 | { \ |
650 | 0 | return ws_basebuftoi##bits(buf, len, endptr, cint, 10); \ |
651 | 0 | } \ Unexecuted instantiation: ws_buftoi32 Unexecuted instantiation: ws_buftoi16 Unexecuted instantiation: ws_buftoi8 |
652 | | \ |
653 | 0 | bool ws_hexbuftoi##bits(const uint8_t* buf, size_t len, const uint8_t** endptr, int##bits##_t* cint) \ |
654 | 0 | { \ |
655 | 0 | return ws_basebuftoi##bits(buf, len, endptr, cint, 16); \ |
656 | 0 | } Unexecuted instantiation: ws_hexbuftoi32 Unexecuted instantiation: ws_hexbuftoi16 Unexecuted instantiation: ws_hexbuftoi8 |
657 | | |
658 | 0 | DEFINE_WS_BUFTOI_BITS(32) |
659 | 0 | DEFINE_WS_BUFTOI_BITS(16) |
660 | | DEFINE_WS_BUFTOI_BITS(8) |
661 | | |
662 | | /* |
663 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
664 | | * |
665 | | * Local variables: |
666 | | * c-basic-offset: 4 |
667 | | * tab-width: 8 |
668 | | * indent-tabs-mode: t |
669 | | * End: |
670 | | * |
671 | | * vi: set shiftwidth=4 tabstop=8 noexpandtab: |
672 | | * :indentSize=4:tabSize=8:noTabs=false: |
673 | | */ |