Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
} \
ws_strtou32
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
} \
ws_strtou16
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
} \
ws_strtou8
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
}
ws_hexstrtou32
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
} \
ws_buftou32
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
} \
ws_buftou16
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
} \
ws_buftou8
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
}
ws_hexbuftou32
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
}
ws_hexbuftou16
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
}
ws_hexbuftou8
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
 */