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