suricata
util-byte.c
Go to the documentation of this file.
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 /** \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  */
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 
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 
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 
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 
185 int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str)
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  /* This will interfere with some rules that do not know the length
227  * in advance and instead are just using the max.
228  */
229 #if 0
230  else if (len && *endptr != '\0') {
231  fprintf(stderr, "ByteExtractString: Extra characters following numeric value\n");
232  return -1;
233  }
234 #endif
235 
236  return (endptr - ptr);
237 }
238 
239 int ByteExtractStringUint64(uint64_t *res, int base, uint16_t len, const char *str)
240 {
241  return ByteExtractString(res, base, len, str);
242 }
243 
244 int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
245 {
246  uint64_t i64;
247 
248  int ret = ByteExtractString(&i64, base, len, str);
249  if (ret <= 0) {
250  return ret;
251  }
252 
253  *res = (uint32_t)i64;
254 
255  if ((uint64_t)(*res) != i64) {
256  SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
257  i64, (uintmax_t)UINT_MAX);
258  return -1;
259  }
260 
261  return ret;
262 }
263 
264 int ByteExtractStringUint16(uint16_t *res, int base, uint16_t len, const char *str)
265 {
266  uint64_t i64;
267 
268  int ret = ByteExtractString(&i64, base, len, str);
269  if (ret <= 0) {
270  return ret;
271  }
272 
273  *res = (uint16_t)i64;
274 
275  if ((uint64_t)(*res) != i64) {
276  SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
277  i64, (uintmax_t)USHRT_MAX);
278  return -1;
279  }
280 
281  return ret;
282 }
283 
284 int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str)
285 {
286  uint64_t i64;
287 
288  int ret = ByteExtractString(&i64, base, len, str);
289  if (ret <= 0) {
290  return ret;
291  }
292 
293  *res = (uint8_t)i64;
294 
295  if ((uint64_t)(*res) != i64) {
296  SCLogDebug("Numeric value out of range (%" PRIu64 " > %" PRIuMAX ")",
297  i64, (uintmax_t)UCHAR_MAX);
298  return -1;
299  }
300 
301  return ret;
302 }
303 
304 int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str)
305 {
306  const char *ptr = str;
307  char *endptr;
308 
309  /* 23 - This is the largest string (octal, with a zero prefix) that
310  * will not overflow int64_t. The only way this length
311  * could be over 23 and still not overflow is if it were zero
312  * prefixed and we only support 1 byte of zero prefix for octal.
313  *
314  * "-0777777777777777777777" = 0xffffffffffffffff
315  */
316  char strbuf[24];
317 
318  if (len > 23) {
319  SCLogError(SC_ERR_ARG_LEN_LONG, "len too large (23 max)");
320  return -1;
321  }
322 
323  if (len) {
324  /* Extract out the string so it can be null terminated */
325  memcpy(strbuf, str, len);
326  strbuf[len] = '\0';
327  ptr = strbuf;
328  }
329 
330  errno = 0;
331  *res = strtoll(ptr, &endptr, base);
332 
333  if (errno == ERANGE) {
334  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range");
335  return -1;
336  } else if (endptr == str) {
337  SCLogError(SC_ERR_INVALID_NUMERIC_VALUE, "Invalid numeric value");
338  return -1;
339  }
340  /* This will interfere with some rules that do not know the length
341  * in advance and instead are just using the max.
342  */
343 #if 0
344  else if (len && *endptr != '\0') {
345  fprintf(stderr, "ByteExtractStringSigned: Extra characters following numeric value\n");
346  return -1;
347  }
348 #endif
349 
350  //fprintf(stderr, "ByteExtractStringSigned: Extracted base %d: 0x%" PRIx64 "\n", base, *res);
351 
352  return (endptr - ptr);
353 }
354 
355 int ByteExtractStringInt64(int64_t *res, int base, uint16_t len, const char *str)
356 {
357  return ByteExtractStringSigned(res, base, len, str);
358 }
359 
360 int ByteExtractStringInt32(int32_t *res, int base, uint16_t len, const char *str)
361 {
362  int64_t i64;
363  int ret;
364 
365  ret = ByteExtractStringSigned(&i64, base, len, str);
366  if (ret <= 0) {
367  return ret;
368  }
369 
370  *res = (int32_t)i64;
371 
372  if ((int64_t)(*res) != i64) {
373  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
374  "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)INT_MAX);
375  return -1;
376  }
377 
378  return ret;
379 }
380 
381 int ByteExtractStringInt16(int16_t *res, int base, uint16_t len, const char *str)
382 {
383  int64_t i64;
384  int ret;
385 
386  ret = ByteExtractStringSigned(&i64, base, len, str);
387  if (ret <= 0) {
388  return ret;
389  }
390 
391  *res = (int16_t)i64;
392 
393  if ((int64_t)(*res) != i64) {
394  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
395  "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)SHRT_MAX);
396  return -1;
397  }
398 
399  return ret;
400 }
401 
402 int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str)
403 {
404  int64_t i64;
405  int ret;
406 
407  ret = ByteExtractStringSigned(&i64, base, len, str);
408  if (ret <= 0) {
409  return ret;
410  }
411 
412  *res = (int8_t)i64;
413 
414  if ((int64_t)(*res) != i64) {
415  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
416  "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)CHAR_MAX);
417  return -1;
418  }
419 
420  return ret;
421 }
422 
423 /* UNITTESTS */
424 #ifdef UNITTESTS
425 
426 static int ByteTest01 (void)
427 {
428  uint16_t val = 0x0102;
429  uint16_t i16 = 0xbfbf;
430  uint8_t bytes[2] = { 0x02, 0x01 };
431  int ret = ByteExtractUint16(&i16, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
432 
433  if ((ret == 2) && (i16 == val)) {
434  return 1;
435  }
436 
437  return 0;
438 }
439 
440 static int ByteTest02 (void)
441 {
442  uint16_t val = 0x0102;
443  uint16_t i16 = 0xbfbf;
444  uint8_t bytes[2] = { 0x01, 0x02 };
445  int ret = ByteExtractUint16(&i16, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
446 
447  if ((ret == 2) && (i16 == val)) {
448  return 1;
449  }
450 
451  return 0;
452 }
453 
454 static int ByteTest03 (void)
455 {
456  uint32_t val = 0x01020304;
457  uint32_t i32 = 0xbfbfbfbf;
458  uint8_t bytes[4] = { 0x04, 0x03, 0x02, 0x01 };
459  int ret = ByteExtractUint32(&i32, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
460 
461  if ((ret == 4) && (i32 == val)) {
462  return 1;
463  }
464 
465  return 0;
466 }
467 
468 static int ByteTest04 (void)
469 {
470  uint32_t val = 0x01020304;
471  uint32_t i32 = 0xbfbfbfbf;
472  uint8_t bytes[4] = { 0x01, 0x02, 0x03, 0x04 };
473  int ret = ByteExtractUint32(&i32, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
474 
475  if ((ret == 4) && (i32 == val)) {
476  return 1;
477  }
478 
479  return 0;
480 }
481 
482 static int ByteTest05 (void)
483 {
484  uint64_t val = 0x0102030405060708ULL;
485  uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
486  uint8_t bytes[8] = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
487  int ret = ByteExtractUint64(&i64, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
488 
489  if ((ret == 8) && (i64 == val)) {
490  return 1;
491  }
492 
493  return 0;
494 }
495 
496 static int ByteTest06 (void)
497 {
498  uint64_t val = 0x0102030405060708ULL;
499  uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
500  uint8_t bytes[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
501  int ret = ByteExtractUint64(&i64, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
502 
503  if ((ret == 8) && (i64 == val)) {
504  return 1;
505  }
506 
507  return 0;
508 }
509 
510 static int ByteTest07 (void)
511 {
512  const char *str = "1234567890";
513  uint64_t val = 1234567890;
514  uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
515  int ret = ByteExtractStringUint64(&i64, 10, strlen(str), str);
516 
517  if ((ret == 10) && (i64 == val)) {
518  return 1;
519  }
520 
521  return 0;
522 }
523 
524 static int ByteTest08 (void)
525 {
526  const char *str = "1234567890";
527  uint32_t val = 1234567890;
528  uint32_t i32 = 0xbfbfbfbf;
529  int ret = ByteExtractStringUint32(&i32, 10, strlen(str), str);
530 
531  if ((ret == 10) && (i32 == val)) {
532  return 1;
533  }
534 
535  return 0;
536 }
537 
538 static int ByteTest09 (void)
539 {
540  const char *str = "12345";
541  uint16_t val = 12345;
542  uint16_t i16 = 0xbfbf;
543  int ret = ByteExtractStringUint16(&i16, 10, strlen(str), str);
544 
545  if ((ret == 5) && (i16 == val)) {
546  return 1;
547  }
548 
549  return 0;
550 }
551 
552 static int ByteTest10 (void)
553 {
554  const char *str = "123";
555  uint8_t val = 123;
556  uint8_t i8 = 0xbf;
557  int ret = ByteExtractStringUint8(&i8, 10, strlen(str), str);
558 
559  if ((ret == 3) && (i8 == val)) {
560  return 1;
561  }
562 
563  return 0;
564 }
565 
566 static int ByteTest11 (void)
567 {
568  const char *str = "-1234567890";
569  int64_t val = -1234567890;
570  int64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
571  int ret = ByteExtractStringInt64(&i64, 10, strlen(str), str);
572 
573  if ((ret == 11) && (i64 == val)) {
574  return 1;
575  }
576 
577  return 0;
578 }
579 
580 static int ByteTest12 (void)
581 {
582  const char *str = "-1234567890";
583  int32_t val = -1234567890;
584  int32_t i32 = 0xbfbfbfbf;
585  int ret = ByteExtractStringInt32(&i32, 10, strlen(str), str);
586 
587  if ((ret == 11) && (i32 == val)) {
588  return 1;
589  }
590 
591  return 0;
592 }
593 
594 static int ByteTest13 (void)
595 {
596  const char *str = "-12345";
597  int16_t val = -12345;
598  int16_t i16 = 0xbfbf;
599  int ret = ByteExtractStringInt16(&i16, 10, strlen(str), str);
600 
601  if ((ret == 6) && (i16 == val)) {
602  return 1;
603  }
604 
605  return 0;
606 }
607 
608 static int ByteTest14 (void)
609 {
610  const char *str = "-123";
611  int8_t val = -123;
612  int8_t i8 = 0xbf;
613  int ret = ByteExtractStringInt8(&i8, 10, strlen(str), str);
614 
615  if ((ret == 4) && (i8 == val)) {
616  return 1;
617  }
618 
619  return 0;
620 }
621 
622 /** \test max u32 value */
623 static int ByteTest15 (void)
624 {
625  const char *str = "4294967295";
626  uint32_t val = 4294967295UL;
627  uint32_t u32 = 0xffffffff;
628 
629  int ret = ByteExtractStringUint32(&u32, 10, strlen(str), str);
630  if ((ret == 10) && (u32 == val)) {
631  return 1;
632  }
633 
634  return 0;
635 }
636 
637 /** \test max u32 value + 1 */
638 static int ByteTest16 (void)
639 {
640  const char *str = "4294967296";
641  uint32_t u32 = 0;
642 
643  int ret = ByteExtractStringUint32(&u32, 10, strlen(str), str);
644  if (ret != 0) {
645  return 1;
646  }
647 
648  return 0;
649 }
650 
652 {
653  UtRegisterTest("ByteTest01", ByteTest01);
654  UtRegisterTest("ByteTest02", ByteTest02);
655  UtRegisterTest("ByteTest03", ByteTest03);
656  UtRegisterTest("ByteTest04", ByteTest04);
657  UtRegisterTest("ByteTest05", ByteTest05);
658  UtRegisterTest("ByteTest06", ByteTest06);
659  UtRegisterTest("ByteTest07", ByteTest07);
660  UtRegisterTest("ByteTest08", ByteTest08);
661  UtRegisterTest("ByteTest09", ByteTest09);
662  UtRegisterTest("ByteTest10", ByteTest10);
663  UtRegisterTest("ByteTest11", ByteTest11);
664  UtRegisterTest("ByteTest12", ByteTest12);
665  UtRegisterTest("ByteTest13", ByteTest13);
666  UtRegisterTest("ByteTest14", ByteTest14);
667  UtRegisterTest("ByteTest15", ByteTest15);
668  UtRegisterTest("ByteTest16", ByteTest16);
669 }
670 #endif /* UNITTESTS */
671 
#define SCLogDebug(...)
Definition: util-debug.h:335
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
int ByteExtractStringInt32(int32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:360
int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:244
int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:284
int ByteExtractStringUint16(uint16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:264
int ByteExtractStringUint64(uint64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:239
#define str(s)
uint16_t dst
#define SCCalloc(nm, a)
Definition: util-mem.h:197
int ByteExtractStringInt64(int64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:355
int ByteExtractStringInt16(int16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:381
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:304
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void BytesToStringBuffer(const uint8_t *bytes, size_t nbytes, char *outstr, size_t outlen)
Turn byte array into string.
Definition: util-byte.c:85
#define BYTE_BIG_ENDIAN
Definition: util-byte.h:29
char * BytesToString(const uint8_t *bytes, size_t nbytes)
Turn byte array into string.
Definition: util-byte.c:41
#define BYTE_LITTLE_ENDIAN
Definition: util-byte.h:30
void ByteRegisterTests(void)
Definition: util-byte.c:651
PoolThreadReserved res
int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:185
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:122
int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:164
int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:402
uint8_t len
int ByteExtractUint32(uint32_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:143
#define DEBUG_VALIDATE_BUG_ON(exp)