Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata8/src/util-byte.c
Line
Count
Source
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
0
{
43
0
    size_t n = nbytes + 1;
44
0
    size_t nulls = 0;
45
46
0
    size_t u;
47
0
    for (u = 0; u < nbytes; u++) {
48
0
        if (bytes[u] == '\0')
49
0
            nulls++;
50
0
    }
51
0
    n += nulls;
52
53
0
    char *string = SCCalloc(1, n);
54
0
    if (string == NULL)
55
0
        return NULL;
56
57
0
    if (nulls == 0) {
58
        /* no nulls */
59
0
        memcpy(string, bytes, nbytes);
60
0
    } else {
61
        /* nulls present */
62
0
        char *dst = string;
63
0
        for (u = 0; u < nbytes; u++) {
64
0
            if (bytes[u] == '\0') {
65
0
                *dst++ = '\\';
66
0
                *dst++ = '0';
67
0
            } else {
68
0
                *dst++ = bytes[u];
69
0
            }
70
0
        }
71
0
    }
72
0
    return string;
73
0
}
74
75
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
76
145k
{
77
145k
    uint64_t i64;
78
145k
    int ret;
79
80
    /* Uint64 is limited to 8 bytes */
81
145k
    if (len > 8) {
82
        /** \todo Need standard return values */
83
0
        return -1;
84
0
    }
85
86
145k
    ret = ByteExtract(&i64, e, len, bytes);
87
145k
    if (ret <= 0) {
88
12.1k
        return ret;
89
12.1k
    }
90
91
133k
    *res = (uint64_t)i64;
92
93
133k
    return ret;
94
145k
}
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)
100
0
{
101
0
    uint64_t i64;
102
0
    int ret;
103
104
    /* Uint32 is limited to 4 bytes */
105
0
    if (len > 4) {
106
        /** \todo Need standard return values */
107
0
        return -1;
108
0
    }
109
110
0
    ret = ByteExtract(&i64, e, len, bytes);
111
0
    if (ret <= 0) {
112
0
        return ret;
113
0
    }
114
115
0
    *res = (uint32_t)i64;
116
117
0
    return ret;
118
0
}
119
120
int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
121
0
{
122
0
    uint64_t i64;
123
0
    int ret;
124
125
    /* Uint16 is limited to 2 bytes */
126
0
    if (len > 2) {
127
        /** \todo Need standard return values */
128
0
        return -1;
129
0
    }
130
131
0
    ret = ByteExtract(&i64, e, len, bytes);
132
0
    if (ret <= 0) {
133
0
        return ret;
134
0
    }
135
136
0
    *res = (uint16_t)i64;
137
138
0
    return ret;
139
0
}
140
141
int ByteExtractString(uint64_t *res, int base, size_t len, const char *str, bool strict)
142
9.57M
{
143
9.57M
    const char *ptr = str;
144
9.57M
    char *endptr = NULL;
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
9.57M
    char strbuf[24];
154
155
9.57M
    if (len > 23) {
156
34.6k
        SCLogDebug("len too large (23 max)");
157
34.6k
        return -1;
158
34.6k
    }
159
160
9.53M
    if (len) {
161
        /* Extract out the string so it can be null terminated */
162
3.86M
        memcpy(strbuf, str, len);
163
3.86M
        strbuf[len] = '\0';
164
3.86M
        ptr = strbuf;
165
3.86M
    }
166
167
9.53M
    errno = 0;
168
9.53M
    *res = strtoull(ptr, &endptr, base);
169
170
9.53M
    if (errno == ERANGE) {
171
8.17k
        SCLogDebug("numeric value out of range");
172
8.17k
        return -1;
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
9.52M
    } else if (endptr == ptr && *res == 0) {
176
92.5k
        SCLogDebug("no numeric value");
177
92.5k
        return -1;
178
9.43M
    } else if (endptr == ptr) {
179
0
        SCLogDebug("invalid numeric value");
180
0
        return -1;
181
0
    }
182
9.43M
    else if (strict && *endptr != '\0') {
183
14.9k
        SCLogError("Extra characters following numeric value");
184
14.9k
        return -1;
185
14.9k
    }
186
187
9.42M
    return (int)(endptr - ptr);
188
9.53M
}
189
190
int ByteExtractStringUint64(uint64_t *res, int base, size_t len, const char *str)
191
473k
{
192
473k
    return ByteExtractString(res, base, len, str, false);
193
473k
}
194
195
int ByteExtractStringUint32(uint32_t *res, int base, size_t len, const char *str)
196
3.67M
{
197
3.67M
    uint64_t i64;
198
199
3.67M
    int ret = ByteExtractString(&i64, base, len, str, false);
200
3.67M
    if (ret <= 0) {
201
46.2k
        return ret;
202
46.2k
    }
203
3.63M
    if (i64 > UINT32_MAX) {
204
22.2k
        return -1;
205
22.2k
    }
206
207
3.60M
    *res = (uint32_t)i64;
208
209
3.60M
    if ((uint64_t)(*res) != i64) {
210
0
        SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
211
0
                i64, (uintmax_t)UINT_MAX);
212
0
        return -1;
213
0
    }
214
215
3.60M
    return ret;
216
3.60M
}
217
218
int ByteExtractStringUint16(uint16_t *res, int base, size_t len, const char *str)
219
0
{
220
0
    uint64_t i64;
221
222
0
    int ret = ByteExtractString(&i64, base, len, str, false);
223
0
    if (ret <= 0) {
224
0
        return ret;
225
0
    }
226
0
    if (i64 > UINT16_MAX) {
227
0
        return -1;
228
0
    }
229
230
0
    *res = (uint16_t)i64;
231
232
0
    if ((uint64_t)(*res) != i64) {
233
0
        SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
234
0
                i64, (uintmax_t)USHRT_MAX);
235
0
        return -1;
236
0
    }
237
238
0
    return ret;
239
0
}
240
241
int ByteExtractStringUint8(uint8_t *res, int base, size_t len, const char *str)
242
724
{
243
724
    uint64_t i64;
244
245
724
    int ret = ByteExtractString(&i64, base, len, str, false);
246
724
    if (ret <= 0) {
247
109
        return ret;
248
109
    }
249
615
    if (i64 > UINT8_MAX) {
250
8
        return -1;
251
8
    }
252
253
607
    *res = (uint8_t)i64;
254
255
607
    if ((uint64_t)(*res) != i64) {
256
0
        SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
257
0
                i64, (uintmax_t)UCHAR_MAX);
258
0
        return -1;
259
0
    }
260
261
607
    return ret;
262
607
}
263
264
int StringParseUint64(uint64_t *res, int base, size_t len, const char *str)
265
0
{
266
0
    return ByteExtractString(res, base, len, str, true);
267
0
}
268
269
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
270
713k
{
271
713k
    uint64_t i64;
272
273
713k
    int ret = ByteExtractString(&i64, base, len, str, true);
274
713k
    if (ret <= 0) {
275
4.14k
        return ret;
276
4.14k
    }
277
709k
    if (i64 > UINT32_MAX) {
278
498
        return -1;
279
498
    }
280
281
709k
    *res = (uint32_t)i64;
282
283
709k
    if ((uint64_t)(*res) != i64) {
284
0
        SCLogError("Numeric value out of range "
285
0
                   "(%" PRIu64 " > %" PRIuMAX ")",
286
0
                i64, (uintmax_t)UINT_MAX);
287
0
        return -1;
288
0
    }
289
290
709k
    return ret;
291
709k
}
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
4.36M
{
298
4.36M
    uint64_t i64;
299
300
4.36M
    int ret = ByteExtractString(&i64, base, len, str, true);
301
4.36M
    if (ret <= 0) {
302
70.8k
        return ret;
303
70.8k
    }
304
4.29M
    if (i64 > UINT16_MAX) {
305
3.58k
        return -1;
306
3.58k
    }
307
308
4.29M
    *res = (uint16_t)i64;
309
310
4.29M
    if ((uint64_t)(*res) != i64) {
311
0
        SCLogError("Numeric value out of range "
312
0
                   "(%" PRIu64 " > %" PRIuMAX ")",
313
0
                i64, (uintmax_t)USHRT_MAX);
314
0
        return -1;
315
0
    }
316
317
4.29M
    return ret;
318
4.29M
}
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
22.3k
{
325
22.3k
    uint64_t i64;
326
327
22.3k
    int ret = ByteExtractString(&i64, base, len, str, true);
328
22.3k
    if (ret <= 0) {
329
3.72k
        return ret;
330
3.72k
    }
331
18.6k
    if (i64 > UINT8_MAX) {
332
1.43k
        return -1;
333
1.43k
    }
334
335
17.1k
    *res = (uint8_t)i64;
336
337
17.1k
    if ((uint64_t)(*res) != i64) {
338
0
        SCLogError("Numeric value out of range "
339
0
                   "(%" PRIu64 " > %" PRIuMAX ")",
340
0
                i64, (uintmax_t)UCHAR_MAX);
341
0
        return -1;
342
0
    }
343
344
17.1k
    return ret;
345
17.1k
}
346
347
int StringParseU64RangeCheck(
348
        uint64_t *res, int base, size_t len, const char *str, uint64_t min, uint64_t max)
349
0
{
350
0
    uint64_t u64;
351
352
0
    int ret = ByteExtractString(&u64, base, len, str, true);
353
0
    if (ret <= 0) {
354
0
        return ret;
355
0
    }
356
357
0
    *res = u64;
358
359
0
    if (*res < min || *res > max) {
360
0
        return -1;
361
0
    }
362
363
0
    return ret;
364
0
}
365
366
int StringParseU32RangeCheck(
367
        uint32_t *res, int base, size_t len, const char *str, uint32_t min, uint32_t max)
368
0
{
369
0
    uint64_t u64;
370
371
0
    int ret = ByteExtractString(&u64, base, len, str, true);
372
0
    if (ret <= 0) {
373
0
        return ret;
374
0
    }
375
0
    if (u64 > UINT32_MAX) {
376
0
        return -1;
377
0
    }
378
379
0
    *res = (uint32_t)u64;
380
381
0
    if (*res < min || *res > max) {
382
0
        return -1;
383
0
    }
384
385
0
    if ((uint64_t)(*res) != u64) {
386
0
        SCLogError("Numeric value out of range "
387
0
                   "(%" PRIu64 " > %" PRIuMAX ")",
388
0
                u64, (uintmax_t)UINT_MAX);
389
0
        return -1;
390
0
    }
391
392
0
    return ret;
393
0
}
394
395
int StringParseU16RangeCheck(
396
        uint16_t *res, int base, size_t len, const char *str, uint16_t min, uint16_t max)
397
253
{
398
253
    uint64_t u64;
399
400
253
    int ret = ByteExtractString(&u64, base, len, str, true);
401
253
    if (ret <= 0) {
402
36
        return ret;
403
36
    }
404
217
    if (u64 > UINT16_MAX) {
405
40
        return -1;
406
40
    }
407
408
177
    *res = (uint16_t)u64;
409
410
177
    if (*res < min || *res > max) {
411
2
        return -1;
412
2
    }
413
414
175
    if ((uint64_t)(*res) != u64) {
415
0
        SCLogError("Numeric value out of range "
416
0
                   "(%" PRIu64 " > %" PRIuMAX ")",
417
0
                u64, (uintmax_t)USHRT_MAX);
418
0
        return -1;
419
0
    }
420
421
175
    return ret;
422
175
}
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
318k
{
430
318k
    uint64_t u64;
431
432
318k
    int ret = ByteExtractString(&u64, base, len, str, true);
433
318k
    if (ret <= 0) {
434
5.50k
        return ret;
435
5.50k
    }
436
313k
    if (u64 > UINT8_MAX) {
437
310
        return -1;
438
310
    }
439
440
313k
    *res = (uint8_t)u64;
441
442
313k
    if (*res < min || *res > max) {
443
237
        return -1;
444
237
    }
445
446
312k
    if ((uint64_t)(*res) != u64) {
447
0
        SCLogError("Numeric value out of range "
448
0
                   "(%" PRIu64 " > %" PRIuMAX ")",
449
0
                u64, (uintmax_t)UCHAR_MAX);
450
0
        return -1;
451
0
    }
452
453
312k
    return ret;
454
312k
}
455
456
int ByteExtractStringSigned(int64_t *res, int base, size_t len, const char *str, bool strict)
457
1.04M
{
458
1.04M
    const char *ptr = str;
459
1.04M
    char *endptr;
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
1.04M
    char strbuf[24];
469
470
1.04M
    if (len > 23) {
471
756
        SCLogError("len too large (23 max)");
472
756
        return -1;
473
756
    }
474
475
1.04M
    if (len) {
476
        /* Extract out the string so it can be null terminated */
477
46.1k
        memcpy(strbuf, str, len);
478
46.1k
        strbuf[len] = '\0';
479
46.1k
        ptr = strbuf;
480
46.1k
    }
481
482
1.04M
    errno = 0;
483
1.04M
    *res = strtoll(ptr, &endptr, base);
484
485
1.04M
    if (errno == ERANGE) {
486
2.94k
        SCLogError("Numeric value out of range");
487
2.94k
        return -1;
488
1.04M
    } else if (endptr == str) {
489
8.26k
        SCLogError("Invalid numeric value");
490
8.26k
        return -1;
491
8.26k
    }
492
1.03M
    else if (strict && len && *endptr != '\0') {
493
2.18k
        SCLogError("Extra characters following numeric value");
494
2.18k
        return -1;
495
2.18k
    }
496
497
    //fprintf(stderr, "ByteExtractStringSigned: Extracted base %d: 0x%" PRIx64 "\n", base, *res);
498
499
1.03M
    return (int)(endptr - ptr);
500
1.04M
}
501
502
int ByteExtractStringInt64(int64_t *res, int base, size_t len, const char *str)
503
0
{
504
0
    return ByteExtractStringSigned(res, base, len, str, false);
505
0
}
506
507
int ByteExtractStringInt32(int32_t *res, int base, size_t len, const char *str)
508
0
{
509
0
    int64_t i64;
510
0
    int ret;
511
512
0
    ret = ByteExtractStringSigned(&i64, base, len, str, false);
513
0
    if (ret <= 0) {
514
0
        return ret;
515
0
    }
516
0
    if (i64 < INT32_MIN || i64 > INT32_MAX) {
517
0
        return -1;
518
0
    }
519
520
0
    *res = (int32_t)i64;
521
522
0
    if ((int64_t)(*res) != i64) {
523
0
        SCLogError("Numeric value out of range "
524
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
525
0
                i64, (intmax_t)INT_MAX);
526
0
        return -1;
527
0
    }
528
529
0
    return ret;
530
0
}
531
532
int ByteExtractStringInt16(int16_t *res, int base, size_t len, const char *str)
533
0
{
534
0
    int64_t i64;
535
0
    int ret;
536
537
0
    ret = ByteExtractStringSigned(&i64, base, len, str, false);
538
0
    if (ret <= 0) {
539
0
        return ret;
540
0
    }
541
0
    if (i64 < INT16_MIN || i64 > INT16_MAX) {
542
0
        return -1;
543
0
    }
544
545
0
    *res = (int16_t)i64;
546
547
0
    if ((int64_t)(*res) != i64) {
548
0
        SCLogError("Numeric value out of range "
549
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
550
0
                i64, (intmax_t)SHRT_MAX);
551
0
        return -1;
552
0
    }
553
554
0
    return ret;
555
0
}
556
557
int ByteExtractStringInt8(int8_t *res, int base, size_t len, const char *str)
558
0
{
559
0
    int64_t i64;
560
0
    int ret;
561
562
0
    ret = ByteExtractStringSigned(&i64, base, len, str, false);
563
0
    if (ret <= 0) {
564
0
        return ret;
565
0
    }
566
0
    if (i64 < INT8_MIN || i64 > INT8_MAX) {
567
0
        return -1;
568
0
    }
569
570
0
    *res = (int8_t)i64;
571
572
0
    if ((int64_t)(*res) != i64) {
573
0
        SCLogError("Numeric value out of range "
574
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
575
0
                i64, (intmax_t)CHAR_MAX);
576
0
        return -1;
577
0
    }
578
579
0
    return ret;
580
0
}
581
582
int StringParseInt64(int64_t *res, int base, size_t len, const char *str)
583
49
{
584
49
    return ByteExtractStringSigned(res, base, len, str, true);
585
49
}
586
587
int StringParseInt32(int32_t *res, int base, size_t len, const char *str)
588
447k
{
589
447k
    int64_t i64;
590
447k
    int ret;
591
592
447k
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
593
447k
    if (ret <= 0) {
594
1.47k
        return ret;
595
1.47k
    }
596
445k
    if (i64 < INT32_MIN || i64 > INT32_MAX) {
597
661
        return -1;
598
661
    }
599
600
445k
    *res = (int32_t)i64;
601
602
445k
    if ((int64_t)(*res) != i64) {
603
0
        SCLogError("Numeric value out of range "
604
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
605
0
                i64, (intmax_t)INT_MAX);
606
0
        return -1;
607
0
    }
608
609
445k
    return ret;
610
445k
}
611
612
int StringParseInt16(int16_t *res, int base, size_t len, const char *str)
613
0
{
614
0
    int64_t i64;
615
0
    int ret;
616
617
0
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
618
0
    if (ret <= 0) {
619
0
        return ret;
620
0
    }
621
0
    if (i64 < INT16_MIN || i64 > INT16_MAX) {
622
0
        return -1;
623
0
    }
624
625
0
    *res = (int16_t)i64;
626
627
0
    if ((int64_t)(*res) != i64) {
628
0
        SCLogError("Numeric value out of range "
629
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
630
0
                i64, (intmax_t)SHRT_MAX);
631
0
        return -1;
632
0
    }
633
634
0
    return ret;
635
0
}
636
637
int StringParseInt8(int8_t *res, int base, size_t len, const char *str)
638
0
{
639
0
    int64_t i64;
640
0
    int ret;
641
642
0
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
643
0
    if (ret <= 0) {
644
0
        return ret;
645
0
    }
646
0
    if (i64 < INT8_MIN || i64 > INT8_MAX) {
647
0
        return -1;
648
0
    }
649
650
0
    *res = (int8_t)i64;
651
652
0
    if ((int64_t)(*res) != i64) {
653
0
        SCLogError("Numeric value out of range "
654
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
655
0
                i64, (intmax_t)CHAR_MAX);
656
0
        return -1;
657
0
    }
658
659
0
    return ret;
660
0
}
661
662
int StringParseI64RangeCheck(
663
        int64_t *res, int base, size_t len, const char *str, int64_t min, int64_t max)
664
0
{
665
0
    int64_t i64;
666
0
    int ret;
667
668
0
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
669
0
    if (ret <= 0) {
670
0
        return ret;
671
0
    }
672
673
0
    *res = i64;
674
0
    if (*res < min || *res > max) {
675
0
        return -1;
676
0
    }
677
678
0
    return ret;
679
0
}
680
681
int StringParseI32RangeCheck(
682
        int32_t *res, int base, size_t len, const char *str, int32_t min, int32_t max)
683
600k
{
684
600k
    int64_t i64;
685
600k
    int ret;
686
687
600k
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
688
600k
    if (ret <= 0) {
689
12.6k
        return ret;
690
12.6k
    }
691
588k
    if (i64 < INT32_MIN || i64 > INT32_MAX) {
692
1.03k
        return -1;
693
1.03k
    }
694
695
587k
    *res = (int32_t)i64;
696
697
587k
    if (*res < min || *res > max) {
698
3.84k
        return -1;
699
3.84k
    }
700
701
583k
    if ((int64_t)(*res) != i64) {
702
0
        SCLogError("Numeric value out of range "
703
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
704
0
                i64, (intmax_t)INT_MAX);
705
0
        return -1;
706
0
    }
707
708
583k
    return ret;
709
583k
}
710
711
int StringParseI16RangeCheck(
712
        int16_t *res, int base, size_t len, const char *str, int16_t min, int16_t max)
713
0
{
714
0
    int64_t i64;
715
0
    int ret;
716
717
0
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
718
0
    if (ret <= 0) {
719
0
        return ret;
720
0
    }
721
0
    if (i64 < INT16_MIN || i64 > INT16_MAX) {
722
0
        return -1;
723
0
    }
724
725
0
    *res = (int16_t)i64;
726
727
0
    if (*res < min || *res > max) {
728
0
        return -1;
729
0
    }
730
731
0
    if ((int64_t)(*res) != i64) {
732
0
        SCLogError("Numeric value out of range "
733
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
734
0
                i64, (intmax_t)SHRT_MAX);
735
0
        return -1;
736
0
    }
737
738
0
    return ret;
739
0
}
740
741
int StringParseI8RangeCheck(
742
        int8_t *res, int base, size_t len, const char *str, int8_t min, int8_t max)
743
0
{
744
0
    int64_t i64;
745
0
    int ret;
746
747
0
    ret = ByteExtractStringSigned(&i64, base, len, str, true);
748
0
    if (ret <= 0) {
749
0
        return ret;
750
0
    }
751
0
    if (i64 < INT8_MIN || i64 > INT8_MAX) {
752
0
        return -1;
753
0
    }
754
755
0
    *res = (int8_t)i64;
756
757
0
    if (*res < min || *res > max) {
758
0
        return -1;
759
0
    }
760
761
0
    if ((int64_t)(*res) != i64) {
762
0
        SCLogError("Numeric value out of range "
763
0
                   "(%" PRIi64 " > %" PRIiMAX ")\n",
764
0
                i64, (intmax_t)CHAR_MAX);
765
0
        return -1;
766
0
    }
767
768
0
    return ret;
769
0
}
770
771
int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs)
772
6
{
773
6
    if (ins < 2)
774
0
        return -1;
775
6
    if (ins % 2 != 0)
776
0
        return -1;
777
6
    if (outs != ins / 2)
778
0
        return -1;
779
780
6
    uint8_t hash[outs];
781
6
    memset(hash, 0, outs);
782
6
    size_t i, x;
783
134
    for (x = 0, i = 0; i < ins; i += 2, x++) {
784
128
        char buf[3] = { 0, 0, 0 };
785
128
        buf[0] = in[i];
786
128
        buf[1] = in[i + 1];
787
788
128
        long value = strtol(buf, NULL, 16);
789
128
        if (value >= 0 && value <= 255)
790
128
            hash[x] = (uint8_t)value;
791
0
        else {
792
0
            SCLogError("hash byte out of range %ld", value);
793
0
            return -1;
794
0
        }
795
128
    }
796
797
6
    memcpy(out, hash, outs);
798
6
    return 0;
799
6
}
800
801
/* UNITTESTS */
802
#ifdef UNITTESTS
803
804
static int ByteTest01 (void)
805
{
806
    uint16_t val = 0x0102;
807
    uint16_t i16 = 0xbfbf;
808
    uint8_t bytes[2] = { 0x02, 0x01 };
809
    int ret = ByteExtractUint16(&i16, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
810
811
    if ((ret == 2) && (i16 == val)) {
812
        return 1;
813
    }
814
815
    return 0;
816
}
817
818
static int ByteTest02 (void)
819
{
820
    uint16_t val = 0x0102;
821
    uint16_t i16 = 0xbfbf;
822
    uint8_t bytes[2] = { 0x01, 0x02 };
823
    int ret = ByteExtractUint16(&i16, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
824
825
    if ((ret == 2) && (i16 == val)) {
826
        return 1;
827
    }
828
829
    return 0;
830
}
831
832
static int ByteTest03 (void)
833
{
834
    uint32_t val = 0x01020304;
835
    uint32_t i32 = 0xbfbfbfbf;
836
    uint8_t bytes[4] = { 0x04, 0x03, 0x02, 0x01 };
837
    int ret = ByteExtractUint32(&i32, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
838
839
    if ((ret == 4) && (i32 == val)) {
840
        return 1;
841
    }
842
843
    return 0;
844
}
845
846
static int ByteTest04 (void)
847
{
848
    uint32_t val = 0x01020304;
849
    uint32_t i32 = 0xbfbfbfbf;
850
    uint8_t bytes[4] = { 0x01, 0x02, 0x03, 0x04 };
851
    int ret = ByteExtractUint32(&i32, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
852
853
    if ((ret == 4) && (i32 == val)) {
854
        return 1;
855
    }
856
857
    return 0;
858
}
859
860
static int ByteTest05 (void)
861
{
862
    uint64_t val = 0x0102030405060708ULL;
863
    uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
864
    uint8_t bytes[8] = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
865
    int ret = ByteExtractUint64(&i64, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
866
867
    if ((ret == 8) && (i64 == val)) {
868
        return 1;
869
    }
870
871
    return 0;
872
}
873
874
static int ByteTest06 (void)
875
{
876
    uint64_t val = 0x0102030405060708ULL;
877
    uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
878
    uint8_t bytes[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
879
    int ret = ByteExtractUint64(&i64, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
880
881
    if ((ret == 8) && (i64 == val)) {
882
        return 1;
883
    }
884
885
    return 0;
886
}
887
888
static int ByteTest07 (void)
889
{
890
    const char str[] = "1234567890";
891
    uint64_t val = 1234567890;
892
    uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
893
    int ret = ByteExtractStringUint64(&i64, 10, sizeof(str) - 1, str);
894
895
    if ((ret == 10) && (i64 == val)) {
896
        return 1;
897
    }
898
899
    return 0;
900
}
901
902
static int ByteTest08 (void)
903
{
904
    const char str[] = "1234567890";
905
    uint32_t val = 1234567890;
906
    uint32_t i32 = 0xbfbfbfbf;
907
    int ret = ByteExtractStringUint32(&i32, 10, sizeof(str) - 1, str);
908
909
    if ((ret == 10) && (i32 == val)) {
910
        return 1;
911
    }
912
913
    return 0;
914
}
915
916
static int ByteTest09 (void)
917
{
918
    const char str[] = "12345";
919
    uint16_t val = 12345;
920
    uint16_t i16 = 0xbfbf;
921
    int ret = ByteExtractStringUint16(&i16, 10, sizeof(str) - 1, str);
922
923
    if ((ret == 5) && (i16 == val)) {
924
        return 1;
925
    }
926
927
    return 0;
928
}
929
930
static int ByteTest10 (void)
931
{
932
    const char str[] = "123";
933
    uint8_t val = 123;
934
    uint8_t i8 = 0xbf;
935
    int ret = ByteExtractStringUint8(&i8, 10, sizeof(str) - 1, str);
936
937
    if ((ret == 3) && (i8 == val)) {
938
        return 1;
939
    }
940
941
    return 0;
942
}
943
944
static int ByteTest11 (void)
945
{
946
    const char str[] = "-1234567890";
947
    int64_t val = -1234567890;
948
    int64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
949
    int ret = ByteExtractStringInt64(&i64, 10, sizeof(str) - 1, str);
950
951
    if ((ret == 11) && (i64 == val)) {
952
        return 1;
953
    }
954
955
    return 0;
956
}
957
958
static int ByteTest12 (void)
959
{
960
    const char str[] = "-1234567890";
961
    int32_t val = -1234567890;
962
    int32_t i32 = 0xbfbfbfbf;
963
    int ret = ByteExtractStringInt32(&i32, 10, sizeof(str) - 1, str);
964
965
    if ((ret == 11) && (i32 == val)) {
966
        return 1;
967
    }
968
969
    return 0;
970
}
971
972
static int ByteTest13 (void)
973
{
974
    const char str[] = "-12345";
975
    int16_t val = -12345;
976
    int16_t i16 = 0xbfbf;
977
    int ret = ByteExtractStringInt16(&i16, 10, sizeof(str) - 1, str);
978
979
    if ((ret == 6) && (i16 == val)) {
980
        return 1;
981
    }
982
983
    return 0;
984
}
985
986
static int ByteTest14 (void)
987
{
988
    const char str[] = "-123";
989
    int8_t val = -123;
990
    int8_t i8 = 0xbf;
991
    int ret = ByteExtractStringInt8(&i8, 10, sizeof(str) - 1, str);
992
993
    if ((ret == 4) && (i8 == val)) {
994
        return 1;
995
    }
996
997
    return 0;
998
}
999
1000
/** \test max u32 value */
1001
static int ByteTest15 (void)
1002
{
1003
    const char str[] = "4294967295";
1004
    uint32_t val = 4294967295UL;
1005
    uint32_t u32 = 0xffffffff;
1006
1007
    int ret = ByteExtractStringUint32(&u32, 10, sizeof(str) - 1, str);
1008
    if ((ret == 10) && (u32 == val)) {
1009
        return 1;
1010
    }
1011
1012
    return 0;
1013
}
1014
1015
/** \test max u32 value + 1 */
1016
static int ByteTest16 (void)
1017
{
1018
    const char str[] = "4294967296";
1019
    uint32_t u32 = 0;
1020
1021
    int ret = ByteExtractStringUint32(&u32, 10, sizeof(str) - 1, str);
1022
    if (ret != 0) {
1023
        return 1;
1024
    }
1025
1026
    return 0;
1027
}
1028
1029
void ByteRegisterTests(void)
1030
{
1031
    UtRegisterTest("ByteTest01", ByteTest01);
1032
    UtRegisterTest("ByteTest02", ByteTest02);
1033
    UtRegisterTest("ByteTest03", ByteTest03);
1034
    UtRegisterTest("ByteTest04", ByteTest04);
1035
    UtRegisterTest("ByteTest05", ByteTest05);
1036
    UtRegisterTest("ByteTest06", ByteTest06);
1037
    UtRegisterTest("ByteTest07", ByteTest07);
1038
    UtRegisterTest("ByteTest08", ByteTest08);
1039
    UtRegisterTest("ByteTest09", ByteTest09);
1040
    UtRegisterTest("ByteTest10", ByteTest10);
1041
    UtRegisterTest("ByteTest11", ByteTest11);
1042
    UtRegisterTest("ByteTest12", ByteTest12);
1043
    UtRegisterTest("ByteTest13", ByteTest13);
1044
    UtRegisterTest("ByteTest14", ByteTest14);
1045
    UtRegisterTest("ByteTest15", ByteTest15);
1046
    UtRegisterTest("ByteTest16", ByteTest16);
1047
}
1048
#endif /* UNITTESTS */
1049