• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 22712336922

05 Mar 2026 09:55AM UTC coverage: 66.796% (-12.5%) from 79.283%
22712336922

Pull #14946

github

web-flow
Merge 91559149c into 7e97dfd52
Pull Request #14946: Stack 8001 v15

14 of 19 new or added lines in 7 files covered. (73.68%)

11298 existing lines in 298 files now uncovered.

155282 of 232473 relevant lines covered (66.8%)

5923441.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.35
/src/util-byte.c
1
/* Copyright (C) 2007-2010 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17

18
/**
19
 * \file
20
 *
21
 * \author Brian Rectanus <brectanu@gmail.com>
22
 *
23
 * Byte utility functions
24
 */
25

26
#include "suricata-common.h"
27
#include "util-byte.h"
28
#include "util-unittest.h"
29
#include "util-debug.h"
30
#include "util-validate.h"
31

32
/** \brief Turn byte array into string.
33
 *
34
 *  All non-printables are copied over, except for '\0', which is
35
 *  turned into literal \0 in the string.
36
 *
37
 *  \param bytes byte array
38
 *  \param nbytes number of bytes
39
 *  \return string nul-terminated string or NULL on error
40
 */
41
char *BytesToString(const uint8_t *bytes, size_t nbytes)
42
{
×
43
    size_t n = nbytes + 1;
×
44
    size_t nulls = 0;
×
45

46
    size_t u;
×
47
    for (u = 0; u < nbytes; u++) {
×
48
        if (bytes[u] == '\0')
×
49
            nulls++;
×
50
    }
×
51
    n += nulls;
×
52

53
    char *string = SCCalloc(1, n);
×
54
    if (string == NULL)
×
55
        return NULL;
×
56

57
    if (nulls == 0) {
×
58
        /* no nulls */
59
        memcpy(string, bytes, nbytes);
×
60
    } else {
×
61
        /* nulls present */
62
        char *dst = string;
×
63
        for (u = 0; u < nbytes; u++) {
×
64
            if (bytes[u] == '\0') {
×
65
                *dst++ = '\\';
×
66
                *dst++ = '0';
×
67
            } else {
×
68
                *dst++ = bytes[u];
×
69
            }
×
70
        }
×
71
    }
×
72
    return string;
×
73
}
×
74

75
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
76
{
26,700✔
77
    uint64_t i64;
26,700✔
78
    int ret;
26,700✔
79

80
    /* Uint64 is limited to 8 bytes */
81
    if (len > 8) {
26,700✔
82
        /** \todo Need standard return values */
83
        return -1;
×
84
    }
×
85

86
    ret = ByteExtract(&i64, e, len, bytes);
26,700✔
87
    if (ret <= 0) {
26,700✔
88
        return ret;
2,553✔
89
    }
2,553✔
90

91
    *res = (uint64_t)i64;
24,147✔
92

93
    return ret;
24,147✔
94
}
26,700✔
95

96
/**
97
 * \retval Greater than 0 if successful, 0 or negative on failure.
98
 */
99
int ByteExtractUint32(uint32_t *res, int e, uint16_t len, const uint8_t *bytes)
UNCOV
100
{
×
UNCOV
101
    uint64_t i64;
×
UNCOV
102
    int ret;
×
103

104
    /* Uint32 is limited to 4 bytes */
UNCOV
105
    if (len > 4) {
×
106
        /** \todo Need standard return values */
107
        return -1;
×
108
    }
×
109

UNCOV
110
    ret = ByteExtract(&i64, e, len, bytes);
×
UNCOV
111
    if (ret <= 0) {
×
112
        return ret;
×
113
    }
×
114

UNCOV
115
    *res = (uint32_t)i64;
×
116

UNCOV
117
    return ret;
×
UNCOV
118
}
×
119

120
int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
UNCOV
121
{
×
UNCOV
122
    uint64_t i64;
×
UNCOV
123
    int ret;
×
124

125
    /* Uint16 is limited to 2 bytes */
UNCOV
126
    if (len > 2) {
×
127
        /** \todo Need standard return values */
128
        return -1;
×
129
    }
×
130

UNCOV
131
    ret = ByteExtract(&i64, e, len, bytes);
×
UNCOV
132
    if (ret <= 0) {
×
133
        return ret;
×
134
    }
×
135

UNCOV
136
    *res = (uint16_t)i64;
×
137

UNCOV
138
    return ret;
×
UNCOV
139
}
×
140

141
int ByteExtractString(uint64_t *res, int base, size_t len, const char *str, bool strict)
142
{
5,436,806✔
143
    const char *ptr = str;
5,436,806✔
144
    char *endptr = NULL;
5,436,806✔
145

146
    /* 23 - This is the largest string (octal, with a zero prefix) that
147
     *      will not overflow uint64_t.  The only way this length
148
     *      could be over 23 and still not overflow is if it were zero
149
     *      prefixed and we only support 1 byte of zero prefix for octal.
150
     *
151
     * "01777777777777777777777" = 0xffffffffffffffff
152
     */
153
    char strbuf[24];
5,436,806✔
154

155
    if (len > 23) {
5,436,806✔
156
        SCLogDebug("len too large (23 max)");
31,401✔
157
        return -1;
31,401✔
158
    }
31,401✔
159

160
    if (len) {
5,405,405✔
161
        /* Extract out the string so it can be null terminated */
162
        memcpy(strbuf, str, len);
3,028,929✔
163
        strbuf[len] = '\0';
3,028,929✔
164
        ptr = strbuf;
3,028,929✔
165
    }
3,028,929✔
166

167
    errno = 0;
5,405,405✔
168
    *res = strtoull(ptr, &endptr, base);
5,405,405✔
169

170
    if (errno == ERANGE) {
5,405,405✔
171
        SCLogDebug("numeric value out of range");
4,963✔
172
        return -1;
4,963✔
173
        /* If there is no numeric value in the given string then strtoull(), makes
174
        endptr equals to ptr and return 0 as result */
175
    } else if (endptr == ptr && *res == 0) {
5,400,442✔
176
        SCLogDebug("no numeric value");
83,993✔
177
        return -1;
83,993✔
178
    } else if (endptr == ptr) {
5,316,449✔
179
        SCLogDebug("invalid numeric value");
×
180
        return -1;
×
181
    }
×
182
    else if (strict && *endptr != '\0') {
5,316,449✔
183
        SCLogError("Extra characters following numeric value");
14,748✔
184
        return -1;
14,748✔
185
    }
14,748✔
186

187
    return (int)(endptr - ptr);
5,301,701✔
188
}
5,405,405✔
189

190
int ByteExtractStringUint64(uint64_t *res, int base, size_t len, const char *str)
191
{
38,777✔
192
    return ByteExtractString(res, base, len, str, false);
38,777✔
193
}
38,777✔
194

195
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
196
{
2,914,292✔
197
    uint64_t i64;
2,914,292✔
198

199
    int ret = ByteExtractString(&i64, base, len, str, false);
2,914,292✔
200
    if (ret <= 0) {
2,914,292✔
201
        return ret;
42,121✔
202
    }
42,121✔
203
    if (i64 > UINT32_MAX) {
2,872,171✔
204
        return -1;
20,083✔
205
    }
20,083✔
206

207
    *res = (uint32_t)i64;
2,852,088✔
208

209
    if ((uint64_t)(*res) != i64) {
2,852,088✔
210
        SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
×
211
                i64, (uintmax_t)UINT_MAX);
×
212
        return -1;
×
213
    }
×
214

215
    return ret;
2,852,088✔
216
}
2,852,088✔
217

218
int ByteExtractStringUint16(uint16_t *res, int base, size_t len, const char *str)
UNCOV
219
{
×
UNCOV
220
    uint64_t i64;
×
221

UNCOV
222
    int ret = ByteExtractString(&i64, base, len, str, false);
×
UNCOV
223
    if (ret <= 0) {
×
224
        return ret;
×
225
    }
×
UNCOV
226
    if (i64 > UINT16_MAX) {
×
227
        return -1;
×
228
    }
×
229

UNCOV
230
    *res = (uint16_t)i64;
×
231

UNCOV
232
    if ((uint64_t)(*res) != i64) {
×
233
        SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
×
234
                i64, (uintmax_t)USHRT_MAX);
×
235
        return -1;
×
236
    }
×
237

UNCOV
238
    return ret;
×
UNCOV
239
}
×
240

241
int ByteExtractStringUint8(uint8_t *res, int base, size_t len, const char *str)
242
{
407✔
243
    uint64_t i64;
407✔
244

245
    int ret = ByteExtractString(&i64, base, len, str, false);
407✔
246
    if (ret <= 0) {
407✔
247
        return ret;
×
248
    }
×
249
    if (i64 > UINT8_MAX) {
407✔
250
        return -1;
86✔
251
    }
86✔
252

253
    *res = (uint8_t)i64;
321✔
254

255
    if ((uint64_t)(*res) != i64) {
321✔
256
        SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
×
257
                i64, (uintmax_t)UCHAR_MAX);
×
258
        return -1;
×
259
    }
×
260

261
    return ret;
321✔
262
}
321✔
263

264
int StringParseUint64(uint64_t *res, int base, size_t len, const char *str)
265
{
×
266
    return ByteExtractString(res, base, len, str, true);
×
267
}
×
268

269
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
270
{
259,782✔
271
    uint64_t i64;
259,782✔
272

273
    int ret = ByteExtractString(&i64, base, len, str, true);
259,782✔
274
    if (ret <= 0) {
259,782✔
275
        return ret;
3,205✔
276
    }
3,205✔
277
    if (i64 > UINT32_MAX) {
256,577✔
278
        return -1;
132✔
279
    }
132✔
280

281
    *res = (uint32_t)i64;
256,445✔
282

283
    if ((uint64_t)(*res) != i64) {
256,445✔
284
        SCLogError("Numeric value out of range "
×
285
                   "(%" PRIu64 " > %" PRIuMAX ")",
×
286
                i64, (uintmax_t)UINT_MAX);
×
287
        return -1;
×
288
    }
×
289

290
    return ret;
256,445✔
291
}
256,445✔
292

293
/**
294
 * \retval Greater than 0 if successful, 0 or negative on failure.
295
 */
296
int StringParseUint16(uint16_t *res, int base, size_t len, const char *str)
297
{
1,718,473✔
298
    uint64_t i64;
1,718,473✔
299

300
    int ret = ByteExtractString(&i64, base, len, str, true);
1,718,473✔
301
    if (ret <= 0) {
1,718,473✔
302
        return ret;
73,192✔
303
    }
73,192✔
304
    if (i64 > UINT16_MAX) {
1,645,281✔
305
        return -1;
3,574✔
306
    }
3,574✔
307

308
    *res = (uint16_t)i64;
1,641,707✔
309

310
    if ((uint64_t)(*res) != i64) {
1,641,707✔
311
        SCLogError("Numeric value out of range "
×
312
                   "(%" PRIu64 " > %" PRIuMAX ")",
×
313
                i64, (uintmax_t)USHRT_MAX);
×
314
        return -1;
×
315
    }
×
316

317
    return ret;
1,641,707✔
318
}
1,641,707✔
319

320
/**
321
 * \retval Greater than 0 if successful, 0 or negative on failure.
322
 */
323
int StringParseUint8(uint8_t *res, int base, size_t len, const char *str)
324
{
18,235✔
325
    uint64_t i64;
18,235✔
326

327
    int ret = ByteExtractString(&i64, base, len, str, true);
18,235✔
328
    if (ret <= 0) {
18,235✔
329
        return ret;
2,038✔
330
    }
2,038✔
331
    if (i64 > UINT8_MAX) {
16,197✔
332
        return -1;
509✔
333
    }
509✔
334

335
    *res = (uint8_t)i64;
15,688✔
336

337
    if ((uint64_t)(*res) != i64) {
15,688✔
338
        SCLogError("Numeric value out of range "
×
339
                   "(%" PRIu64 " > %" PRIuMAX ")",
×
340
                i64, (uintmax_t)UCHAR_MAX);
×
341
        return -1;
×
342
    }
×
343

344
    return ret;
15,688✔
345
}
15,688✔
346

347
int StringParseU64RangeCheck(
348
        uint64_t *res, int base, size_t len, const char *str, uint64_t min, uint64_t max)
349
{
×
350
    uint64_t u64;
×
351

352
    int ret = ByteExtractString(&u64, base, len, str, true);
×
353
    if (ret <= 0) {
×
354
        return ret;
×
355
    }
×
356

357
    *res = u64;
×
358

359
    if (*res < min || *res > max) {
×
360
        return -1;
×
361
    }
×
362

363
    return ret;
×
364
}
×
365

366
int StringParseU32RangeCheck(
367
        uint32_t *res, int base, size_t len, const char *str, uint32_t min, uint32_t max)
368
{
1✔
369
    uint64_t u64;
1✔
370

371
    int ret = ByteExtractString(&u64, base, len, str, true);
1✔
372
    if (ret <= 0) {
1✔
373
        return ret;
×
374
    }
×
375
    if (u64 > UINT32_MAX) {
1✔
376
        return -1;
×
377
    }
×
378

379
    *res = (uint32_t)u64;
1✔
380

381
    if (*res < min || *res > max) {
1✔
382
        return -1;
×
383
    }
×
384

385
    if ((uint64_t)(*res) != u64) {
1✔
386
        SCLogError("Numeric value out of range "
×
387
                   "(%" PRIu64 " > %" PRIuMAX ")",
×
388
                u64, (uintmax_t)UINT_MAX);
×
389
        return -1;
×
390
    }
×
391

392
    return ret;
1✔
393
}
1✔
394

395
int StringParseU16RangeCheck(
396
        uint16_t *res, int base, size_t len, const char *str, uint16_t min, uint16_t max)
397
{
309✔
398
    uint64_t u64;
309✔
399

400
    int ret = ByteExtractString(&u64, base, len, str, true);
309✔
401
    if (ret <= 0) {
309✔
402
        return ret;
50✔
403
    }
50✔
404
    if (u64 > UINT16_MAX) {
259✔
405
        return -1;
23✔
406
    }
23✔
407

408
    *res = (uint16_t)u64;
236✔
409

410
    if (*res < min || *res > max) {
236✔
411
        return -1;
1✔
412
    }
1✔
413

414
    if ((uint64_t)(*res) != u64) {
235✔
415
        SCLogError("Numeric value out of range "
×
416
                   "(%" PRIu64 " > %" PRIuMAX ")",
×
417
                u64, (uintmax_t)USHRT_MAX);
×
418
        return -1;
×
419
    }
×
420

421
    return ret;
235✔
422
}
235✔
423

424
/**
425
 * \retval Greater than 0 if successful, 0 or negative on failure.
426
 */
427
int StringParseU8RangeCheck(
428
        uint8_t *res, int base, size_t len, const char *str, uint8_t min, uint8_t max)
429
{
486,529✔
430
    uint64_t u64;
486,529✔
431

432
    int ret = ByteExtractString(&u64, base, len, str, true);
486,529✔
433
    if (ret <= 0) {
486,529✔
434
        return ret;
4,152✔
435
    }
4,152✔
436
    if (u64 > UINT8_MAX) {
482,377✔
437
        return -1;
×
438
    }
×
439

440
    *res = (uint8_t)u64;
482,377✔
441

442
    if (*res < min || *res > max) {
482,377✔
UNCOV
443
        return -1;
×
UNCOV
444
    }
×
445

446
    if ((uint64_t)(*res) != u64) {
482,377✔
447
        SCLogError("Numeric value out of range "
×
448
                   "(%" PRIu64 " > %" PRIuMAX ")",
×
449
                u64, (uintmax_t)UCHAR_MAX);
×
450
        return -1;
×
451
    }
×
452

453
    return ret;
482,377✔
454
}
482,377✔
455

456
int ByteExtractStringSigned(int64_t *res, int base, size_t len, const char *str, bool strict)
457
{
485,358✔
458
    const char *ptr = str;
485,358✔
459
    char *endptr;
485,358✔
460

461
    /* 23 - This is the largest string (octal, with a zero prefix) that
462
     *      will not overflow int64_t.  The only way this length
463
     *      could be over 23 and still not overflow is if it were zero
464
     *      prefixed and we only support 1 byte of zero prefix for octal.
465
     *
466
     * "-0777777777777777777777" = 0xffffffffffffffff
467
     */
468
    char strbuf[24];
485,358✔
469

470
    if (len > 23) {
485,358✔
471
        SCLogError("len too large (23 max)");
878✔
472
        return -1;
878✔
473
    }
878✔
474

475
    if (len) {
484,480✔
476
        /* Extract out the string so it can be null terminated */
477
        memcpy(strbuf, str, len);
31,723✔
478
        strbuf[len] = '\0';
31,723✔
479
        ptr = strbuf;
31,723✔
480
    }
31,723✔
481

482
    errno = 0;
484,480✔
483
    *res = strtoll(ptr, &endptr, base);
484,480✔
484

485
    if (errno == ERANGE) {
484,480✔
486
        SCLogError("Numeric value out of range");
963✔
487
        return -1;
963✔
488
    } else if (endptr == str) {
483,517✔
489
        SCLogError("Invalid numeric value");
5,778✔
490
        return -1;
5,778✔
491
    }
5,778✔
492
    else if (strict && len && *endptr != '\0') {
477,739✔
493
        SCLogError("Extra characters following numeric value");
1,686✔
494
        return -1;
1,686✔
495
    }
1,686✔
496

497
    //fprintf(stderr, "ByteExtractStringSigned: Extracted base %d: 0x%" PRIx64 "\n", base, *res);
498

499
    return (int)(endptr - ptr);
476,053✔
500
}
484,480✔
501

502
int ByteExtractStringInt64(int64_t *res, int base, size_t len, const char *str)
UNCOV
503
{
×
UNCOV
504
    return ByteExtractStringSigned(res, base, len, str, false);
×
UNCOV
505
}
×
506

507
int ByteExtractStringInt32(int32_t *res, int base, size_t len, const char *str)
UNCOV
508
{
×
UNCOV
509
    int64_t i64;
×
UNCOV
510
    int ret;
×
511

UNCOV
512
    ret = ByteExtractStringSigned(&i64, base, len, str, false);
×
UNCOV
513
    if (ret <= 0) {
×
514
        return ret;
×
515
    }
×
UNCOV
516
    if (i64 < INT32_MIN || i64 > INT32_MAX) {
×
517
        return -1;
×
518
    }
×
519

UNCOV
520
    *res = (int32_t)i64;
×
521

UNCOV
522
    if ((int64_t)(*res) != i64) {
×
523
        SCLogError("Numeric value out of range "
×
524
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
525
                i64, (intmax_t)INT_MAX);
×
526
        return -1;
×
527
    }
×
528

UNCOV
529
    return ret;
×
UNCOV
530
}
×
531

532
int ByteExtractStringInt16(int16_t *res, int base, size_t len, const char *str)
UNCOV
533
{
×
UNCOV
534
    int64_t i64;
×
UNCOV
535
    int ret;
×
536

UNCOV
537
    ret = ByteExtractStringSigned(&i64, base, len, str, false);
×
UNCOV
538
    if (ret <= 0) {
×
539
        return ret;
×
540
    }
×
UNCOV
541
    if (i64 < INT16_MIN || i64 > INT16_MAX) {
×
542
        return -1;
×
543
    }
×
544

UNCOV
545
    *res = (int16_t)i64;
×
546

UNCOV
547
    if ((int64_t)(*res) != i64) {
×
548
        SCLogError("Numeric value out of range "
×
549
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
550
                i64, (intmax_t)SHRT_MAX);
×
551
        return -1;
×
552
    }
×
553

UNCOV
554
    return ret;
×
UNCOV
555
}
×
556

557
int ByteExtractStringInt8(int8_t *res, int base, size_t len, const char *str)
UNCOV
558
{
×
UNCOV
559
    int64_t i64;
×
UNCOV
560
    int ret;
×
561

UNCOV
562
    ret = ByteExtractStringSigned(&i64, base, len, str, false);
×
UNCOV
563
    if (ret <= 0) {
×
564
        return ret;
×
565
    }
×
UNCOV
566
    if (i64 < INT8_MIN || i64 > INT8_MAX) {
×
567
        return -1;
×
568
    }
×
569

UNCOV
570
    *res = (int8_t)i64;
×
571

UNCOV
572
    if ((int64_t)(*res) != i64) {
×
573
        SCLogError("Numeric value out of range "
×
574
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
575
                i64, (intmax_t)CHAR_MAX);
×
576
        return -1;
×
577
    }
×
578

UNCOV
579
    return ret;
×
UNCOV
580
}
×
581

582
int StringParseInt64(int64_t *res, int base, size_t len, const char *str)
583
{
43✔
584
    return ByteExtractStringSigned(res, base, len, str, true);
43✔
585
}
43✔
586

587
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
588
{
30,042✔
589
    int64_t i64;
30,042✔
590
    int ret;
30,042✔
591

592
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
30,042✔
593
    if (ret <= 0) {
30,042✔
594
        return ret;
685✔
595
    }
685✔
596
    if (i64 < INT32_MIN || i64 > INT32_MAX) {
29,357✔
597
        return -1;
700✔
598
    }
700✔
599

600
    *res = (int32_t)i64;
28,657✔
601

602
    if ((int64_t)(*res) != i64) {
28,657✔
603
        SCLogError("Numeric value out of range "
×
604
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
605
                i64, (intmax_t)INT_MAX);
×
606
        return -1;
×
607
    }
×
608

609
    return ret;
28,657✔
610
}
28,657✔
611

612
int StringParseInt16(int16_t *res, int base, size_t len, const char *str)
613
{
×
614
    int64_t i64;
×
615
    int ret;
×
616

617
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
×
618
    if (ret <= 0) {
×
619
        return ret;
×
620
    }
×
621
    if (i64 < INT16_MIN || i64 > INT16_MAX) {
×
622
        return -1;
×
623
    }
×
624

625
    *res = (int16_t)i64;
×
626

627
    if ((int64_t)(*res) != i64) {
×
628
        SCLogError("Numeric value out of range "
×
629
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
630
                i64, (intmax_t)SHRT_MAX);
×
631
        return -1;
×
632
    }
×
633

634
    return ret;
×
635
}
×
636

637
int StringParseInt8(int8_t *res, int base, size_t len, const char *str)
638
{
×
639
    int64_t i64;
×
640
    int ret;
×
641

642
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
×
643
    if (ret <= 0) {
×
644
        return ret;
×
645
    }
×
646
    if (i64 < INT8_MIN || i64 > INT8_MAX) {
×
647
        return -1;
×
648
    }
×
649

650
    *res = (int8_t)i64;
×
651

652
    if ((int64_t)(*res) != i64) {
×
653
        SCLogError("Numeric value out of range "
×
654
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
655
                i64, (intmax_t)CHAR_MAX);
×
656
        return -1;
×
657
    }
×
658

659
    return ret;
×
660
}
×
661

662
int StringParseI64RangeCheck(
663
        int64_t *res, int base, size_t len, const char *str, int64_t min, int64_t max)
664
{
×
665
    int64_t i64;
×
666
    int ret;
×
667

668
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
×
669
    if (ret <= 0) {
×
670
        return ret;
×
671
    }
×
672

673
    *res = i64;
×
674
    if (*res < min || *res > max) {
×
675
        return -1;
×
676
    }
×
677

678
    return ret;
×
679
}
×
680

681
int StringParseI32RangeCheck(
682
        int32_t *res, int base, size_t len, const char *str, int32_t min, int32_t max)
683
{
455,273✔
684
    int64_t i64;
455,273✔
685
    int ret;
455,273✔
686

687
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
455,273✔
688
    if (ret <= 0) {
455,273✔
689
        return ret;
8,618✔
690
    }
8,618✔
691
    if (i64 < INT32_MIN || i64 > INT32_MAX) {
446,655✔
692
        return -1;
436✔
693
    }
436✔
694

695
    *res = (int32_t)i64;
446,219✔
696

697
    if (*res < min || *res > max) {
446,219✔
698
        return -1;
2,004✔
699
    }
2,004✔
700

701
    if ((int64_t)(*res) != i64) {
444,215✔
702
        SCLogError("Numeric value out of range "
×
703
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
704
                i64, (intmax_t)INT_MAX);
×
705
        return -1;
×
706
    }
×
707

708
    return ret;
444,215✔
709
}
444,215✔
710

711
int StringParseI16RangeCheck(
712
        int16_t *res, int base, size_t len, const char *str, int16_t min, int16_t max)
713
{
×
714
    int64_t i64;
×
715
    int ret;
×
716

717
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
×
718
    if (ret <= 0) {
×
719
        return ret;
×
720
    }
×
721
    if (i64 < INT16_MIN || i64 > INT16_MAX) {
×
722
        return -1;
×
723
    }
×
724

725
    *res = (int16_t)i64;
×
726

727
    if (*res < min || *res > max) {
×
728
        return -1;
×
729
    }
×
730

731
    if ((int64_t)(*res) != i64) {
×
732
        SCLogError("Numeric value out of range "
×
733
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
734
                i64, (intmax_t)SHRT_MAX);
×
735
        return -1;
×
736
    }
×
737

738
    return ret;
×
739
}
×
740

741
int StringParseI8RangeCheck(
742
        int8_t *res, int base, size_t len, const char *str, int8_t min, int8_t max)
743
{
×
744
    int64_t i64;
×
745
    int ret;
×
746

747
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
×
748
    if (ret <= 0) {
×
749
        return ret;
×
750
    }
×
751
    if (i64 < INT8_MIN || i64 > INT8_MAX) {
×
752
        return -1;
×
753
    }
×
754

755
    *res = (int8_t)i64;
×
756

757
    if (*res < min || *res > max) {
×
758
        return -1;
×
759
    }
×
760

761
    if ((int64_t)(*res) != i64) {
×
762
        SCLogError("Numeric value out of range "
×
763
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
×
764
                i64, (intmax_t)CHAR_MAX);
×
765
        return -1;
×
766
    }
×
767

768
    return ret;
×
769
}
×
770

771
int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs)
772
{
2✔
773
    if (ins < 2)
2✔
774
        return -1;
×
775
    if (ins % 2 != 0)
2✔
776
        return -1;
×
777
    if (outs != ins / 2)
2✔
778
        return -1;
×
779

780
    size_t i, x;
2✔
781
    for (x = 0, i = 0; i < ins; i += 2, x++) {
50✔
782
        char buf[3] = { 0, 0, 0 };
48✔
783
        buf[0] = in[i];
48✔
784
        buf[1] = in[i + 1];
48✔
785

786
        long value = strtol(buf, NULL, 16);
48✔
787
        if (value >= 0 && value <= 255)
48✔
788
            out[x] = (uint8_t)value;
48✔
789
        else {
×
790
            SCLogError("hash byte out of range %ld", value);
×
791
            return -1;
×
792
        }
×
793
    }
48✔
794

795
    return 0;
2✔
796
}
2✔
797

798
/* UNITTESTS */
799
#ifdef UNITTESTS
800

801
static int ByteTest01 (void)
802
{
803
    uint16_t val = 0x0102;
804
    uint16_t i16 = 0xbfbf;
805
    uint8_t bytes[2] = { 0x02, 0x01 };
806
    int ret = ByteExtractUint16(&i16, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
807

808
    if ((ret == 2) && (i16 == val)) {
809
        return 1;
810
    }
811

812
    return 0;
813
}
814

815
static int ByteTest02 (void)
816
{
817
    uint16_t val = 0x0102;
818
    uint16_t i16 = 0xbfbf;
819
    uint8_t bytes[2] = { 0x01, 0x02 };
820
    int ret = ByteExtractUint16(&i16, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
821

822
    if ((ret == 2) && (i16 == val)) {
823
        return 1;
824
    }
825

826
    return 0;
827
}
828

829
static int ByteTest03 (void)
830
{
831
    uint32_t val = 0x01020304;
832
    uint32_t i32 = 0xbfbfbfbf;
833
    uint8_t bytes[4] = { 0x04, 0x03, 0x02, 0x01 };
834
    int ret = ByteExtractUint32(&i32, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
835

836
    if ((ret == 4) && (i32 == val)) {
837
        return 1;
838
    }
839

840
    return 0;
841
}
842

843
static int ByteTest04 (void)
844
{
845
    uint32_t val = 0x01020304;
846
    uint32_t i32 = 0xbfbfbfbf;
847
    uint8_t bytes[4] = { 0x01, 0x02, 0x03, 0x04 };
848
    int ret = ByteExtractUint32(&i32, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
849

850
    if ((ret == 4) && (i32 == val)) {
851
        return 1;
852
    }
853

854
    return 0;
855
}
856

857
static int ByteTest05 (void)
858
{
859
    uint64_t val = 0x0102030405060708ULL;
860
    uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
861
    uint8_t bytes[8] = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
862
    int ret = ByteExtractUint64(&i64, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
863

864
    if ((ret == 8) && (i64 == val)) {
865
        return 1;
866
    }
867

868
    return 0;
869
}
870

871
static int ByteTest06 (void)
872
{
873
    uint64_t val = 0x0102030405060708ULL;
874
    uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
875
    uint8_t bytes[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
876
    int ret = ByteExtractUint64(&i64, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
877

878
    if ((ret == 8) && (i64 == val)) {
879
        return 1;
880
    }
881

882
    return 0;
883
}
884

885
static int ByteTest07 (void)
886
{
887
    const char str[] = "1234567890";
888
    uint64_t val = 1234567890;
889
    uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
890
    int ret = ByteExtractStringUint64(&i64, 10, sizeof(str) - 1, str);
891

892
    if ((ret == 10) && (i64 == val)) {
893
        return 1;
894
    }
895

896
    return 0;
897
}
898

899
static int ByteTest08 (void)
900
{
901
    const char str[] = "1234567890";
902
    uint32_t val = 1234567890;
903
    uint32_t i32 = 0xbfbfbfbf;
904
    int ret = ByteExtractStringUint32(&i32, 10, sizeof(str) - 1, str);
905

906
    if ((ret == 10) && (i32 == val)) {
907
        return 1;
908
    }
909

910
    return 0;
911
}
912

913
static int ByteTest09 (void)
914
{
915
    const char str[] = "12345";
916
    uint16_t val = 12345;
917
    uint16_t i16 = 0xbfbf;
918
    int ret = ByteExtractStringUint16(&i16, 10, sizeof(str) - 1, str);
919

920
    if ((ret == 5) && (i16 == val)) {
921
        return 1;
922
    }
923

924
    return 0;
925
}
926

927
static int ByteTest10 (void)
928
{
929
    const char str[] = "123";
930
    uint8_t val = 123;
931
    uint8_t i8 = 0xbf;
932
    int ret = ByteExtractStringUint8(&i8, 10, sizeof(str) - 1, str);
933

934
    if ((ret == 3) && (i8 == val)) {
935
        return 1;
936
    }
937

938
    return 0;
939
}
940

941
static int ByteTest11 (void)
942
{
943
    const char str[] = "-1234567890";
944
    int64_t val = -1234567890;
945
    int64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
946
    int ret = ByteExtractStringInt64(&i64, 10, sizeof(str) - 1, str);
947

948
    if ((ret == 11) && (i64 == val)) {
949
        return 1;
950
    }
951

952
    return 0;
953
}
954

955
static int ByteTest12 (void)
956
{
957
    const char str[] = "-1234567890";
958
    int32_t val = -1234567890;
959
    int32_t i32 = 0xbfbfbfbf;
960
    int ret = ByteExtractStringInt32(&i32, 10, sizeof(str) - 1, str);
961

962
    if ((ret == 11) && (i32 == val)) {
963
        return 1;
964
    }
965

966
    return 0;
967
}
968

969
static int ByteTest13 (void)
970
{
971
    const char str[] = "-12345";
972
    int16_t val = -12345;
973
    int16_t i16 = 0xbfbf;
974
    int ret = ByteExtractStringInt16(&i16, 10, sizeof(str) - 1, str);
975

976
    if ((ret == 6) && (i16 == val)) {
977
        return 1;
978
    }
979

980
    return 0;
981
}
982

983
static int ByteTest14 (void)
984
{
985
    const char str[] = "-123";
986
    int8_t val = -123;
987
    int8_t i8 = 0xbf;
988
    int ret = ByteExtractStringInt8(&i8, 10, sizeof(str) - 1, str);
989

990
    if ((ret == 4) && (i8 == val)) {
991
        return 1;
992
    }
993

994
    return 0;
995
}
996

997
/** \test max u32 value */
998
static int ByteTest15 (void)
999
{
1000
    const char str[] = "4294967295";
1001
    uint32_t val = 4294967295UL;
1002
    uint32_t u32 = 0xffffffff;
1003

1004
    int ret = ByteExtractStringUint32(&u32, 10, sizeof(str) - 1, str);
1005
    if ((ret == 10) && (u32 == val)) {
1006
        return 1;
1007
    }
1008

1009
    return 0;
1010
}
1011

1012
/** \test max u32 value + 1 */
1013
static int ByteTest16 (void)
1014
{
1015
    const char str[] = "4294967296";
1016
    uint32_t u32 = 0;
1017

1018
    int ret = ByteExtractStringUint32(&u32, 10, sizeof(str) - 1, str);
1019
    if (ret != 0) {
1020
        return 1;
1021
    }
1022

1023
    return 0;
1024
}
1025

1026
void ByteRegisterTests(void)
1027
{
1028
    UtRegisterTest("ByteTest01", ByteTest01);
1029
    UtRegisterTest("ByteTest02", ByteTest02);
1030
    UtRegisterTest("ByteTest03", ByteTest03);
1031
    UtRegisterTest("ByteTest04", ByteTest04);
1032
    UtRegisterTest("ByteTest05", ByteTest05);
1033
    UtRegisterTest("ByteTest06", ByteTest06);
1034
    UtRegisterTest("ByteTest07", ByteTest07);
1035
    UtRegisterTest("ByteTest08", ByteTest08);
1036
    UtRegisterTest("ByteTest09", ByteTest09);
1037
    UtRegisterTest("ByteTest10", ByteTest10);
1038
    UtRegisterTest("ByteTest11", ByteTest11);
1039
    UtRegisterTest("ByteTest12", ByteTest12);
1040
    UtRegisterTest("ByteTest13", ByteTest13);
1041
    UtRegisterTest("ByteTest14", ByteTest14);
1042
    UtRegisterTest("ByteTest15", ByteTest15);
1043
    UtRegisterTest("ByteTest16", ByteTest16);
1044
}
1045
#endif /* UNITTESTS */
1046

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc