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