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 
31 /** \brief Turn byte array into string.
32  *
33  * All non-printables are copied over, except for '\0', which is
34  * turned into literal \0 in the string.
35  *
36  * \param bytes byte array
37  * \param nbytes number of bytes
38  * \return string nul-terminated string or NULL on error
39  */
40 char *BytesToString(const uint8_t *bytes, size_t nbytes)
41 {
42  size_t n = nbytes + 1;
43  size_t nulls = 0;
44 
45  size_t u;
46  for (u = 0; u < nbytes; u++) {
47  if (bytes[u] == '\0')
48  nulls++;
49  }
50  n += nulls;
51 
52  char *string = SCCalloc(1, n);
53  if (string == NULL)
54  return NULL;
55 
56  if (nulls == 0) {
57  /* no nulls */
58  memcpy(string, bytes, nbytes);
59  } else {
60  /* nulls present */
61  char *dst = string;
62  for (u = 0; u < nbytes; u++) {
63  if (bytes[u] == '\0') {
64  *dst++ = '\\';
65  *dst++ = '0';
66  } else {
67  *dst++ = bytes[u];
68  }
69  }
70  }
71  return string;
72 }
73 
74 int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
75 {
76  uint64_t i64;
77  int ret;
78 
79  /* Uint64 is limited to 8 bytes */
80  if (len > 8) {
81  /** \todo Need standard return values */
82  return -1;
83  }
84 
85  ret = ByteExtract(&i64, e, len, bytes);
86  if (ret <= 0) {
87  return ret;
88  }
89 
90  *res = (uint64_t)i64;
91 
92  return ret;
93 }
94 
95 int ByteExtractUint32(uint32_t *res, int e, uint16_t len, const uint8_t *bytes)
96 {
97  uint64_t i64;
98  int ret;
99 
100  /* Uint32 is limited to 4 bytes */
101  if (len > 4) {
102  /** \todo Need standard return values */
103  return -1;
104  }
105 
106  ret = ByteExtract(&i64, e, len, bytes);
107  if (ret <= 0) {
108  return ret;
109  }
110 
111  *res = (uint32_t)i64;
112 
113  return ret;
114 }
115 
116 int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
117 {
118  uint64_t i64;
119  int ret;
120 
121  /* Uint16 is limited to 2 bytes */
122  if (len > 2) {
123  /** \todo Need standard return values */
124  return -1;
125  }
126 
127  ret = ByteExtract(&i64, e, len, bytes);
128  if (ret <= 0) {
129  return ret;
130  }
131 
132  *res = (uint16_t)i64;
133 
134  return ret;
135 }
136 
137 int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str)
138 {
139  const char *ptr = str;
140  char *endptr = NULL;
141 
142  /* 23 - This is the largest string (octal, with a zero prefix) that
143  * will not overflow uint64_t. The only way this length
144  * could be over 23 and still not overflow is if it were zero
145  * prefixed and we only support 1 byte of zero prefix for octal.
146  *
147  * "01777777777777777777777" = 0xffffffffffffffff
148  */
149  char strbuf[24];
150 
151  if (len > 23) {
152  SCLogDebug("len too large (23 max)");
153  return -1;
154  }
155 
156  if (len) {
157  /* Extract out the string so it can be null terminated */
158  memcpy(strbuf, str, len);
159  strbuf[len] = '\0';
160  ptr = strbuf;
161  }
162 
163  errno = 0;
164  *res = strtoull(ptr, &endptr, base);
165 
166  if (errno == ERANGE) {
167  SCLogDebug("numeric value out of range");
168  return -1;
169  /* If there is no numeric value in the given string then strtoull(), makes
170  endptr equals to ptr and return 0 as result */
171  } else if (endptr == ptr && *res == 0) {
172  SCLogDebug("no numeric value");
173  return -1;
174  } else if (endptr == ptr) {
175  SCLogDebug("invalid numeric value");
176  return -1;
177  }
178  /* This will interfere with some rules that do not know the length
179  * in advance and instead are just using the max.
180  */
181 #if 0
182  else if (len && *endptr != '\0') {
183  fprintf(stderr, "ByteExtractString: Extra characters following numeric value\n");
184  return -1;
185  }
186 #endif
187 
188  return (endptr - ptr);
189 }
190 
191 int ByteExtractStringUint64(uint64_t *res, int base, uint16_t len, const char *str)
192 {
193  return ByteExtractString(res, base, len, str);
194 }
195 
196 int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
197 {
198  uint64_t i64;
199  int ret;
200 
201  ret = ByteExtractString(&i64, base, len, str);
202  if (ret <= 0) {
203  return ret;
204  }
205 
206  *res = (uint32_t)i64;
207 
208  if ((uint64_t)(*res) != i64) {
209  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
210  "(%" PRIu64 " > %" PRIuMAX ")", i64, (uintmax_t)UINT_MAX);
211  return -1;
212  }
213 
214  return ret;
215 }
216 
217 int ByteExtractStringUint16(uint16_t *res, int base, uint16_t len, const char *str)
218 {
219  uint64_t i64;
220  int ret;
221 
222  ret = ByteExtractString(&i64, base, len, str);
223  if (ret <= 0) {
224  return ret;
225  }
226 
227  *res = (uint16_t)i64;
228 
229  if ((uint64_t)(*res) != i64) {
230  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
231  "(%" PRIu64 " > %" PRIuMAX ")", i64, (uintmax_t)USHRT_MAX);
232  return -1;
233  }
234 
235  return ret;
236 }
237 
238 int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str)
239 {
240  uint64_t i64;
241  int ret;
242 
243  ret = ByteExtractString(&i64, base, len, str);
244  if (ret <= 0) {
245  return ret;
246  }
247 
248  *res = (uint8_t)i64;
249 
250  if ((uint64_t)(*res) != i64) {
251  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
252  "(%" PRIu64 " > %" PRIuMAX ")", i64, (uintmax_t)UCHAR_MAX);
253  return -1;
254  }
255 
256  return ret;
257 }
258 
259 int ByteExtractStringSigned(int64_t *res, int base, uint16_t len, const char *str)
260 {
261  const char *ptr = str;
262  char *endptr;
263 
264  /* 23 - This is the largest string (octal, with a zero prefix) that
265  * will not overflow int64_t. The only way this length
266  * could be over 23 and still not overflow is if it were zero
267  * prefixed and we only support 1 byte of zero prefix for octal.
268  *
269  * "-0777777777777777777777" = 0xffffffffffffffff
270  */
271  char strbuf[24];
272 
273  if (len > 23) {
274  SCLogError(SC_ERR_ARG_LEN_LONG, "len too large (23 max)");
275  return -1;
276  }
277 
278  if (len) {
279  /* Extract out the string so it can be null terminated */
280  memcpy(strbuf, str, len);
281  strbuf[len] = '\0';
282  ptr = strbuf;
283  }
284 
285  errno = 0;
286  *res = strtoll(ptr, &endptr, base);
287 
288  if (errno == ERANGE) {
289  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range");
290  return -1;
291  } else if (endptr == str) {
292  SCLogError(SC_ERR_INVALID_NUMERIC_VALUE, "Invalid numeric value");
293  return -1;
294  }
295  /* This will interfere with some rules that do not know the length
296  * in advance and instead are just using the max.
297  */
298 #if 0
299  else if (len && *endptr != '\0') {
300  fprintf(stderr, "ByteExtractStringSigned: Extra characters following numeric value\n");
301  return -1;
302  }
303 #endif
304 
305  //fprintf(stderr, "ByteExtractStringSigned: Extracted base %d: 0x%" PRIx64 "\n", base, *res);
306 
307  return (endptr - ptr);
308 }
309 
310 int ByteExtractStringInt64(int64_t *res, int base, uint16_t len, const char *str)
311 {
312  return ByteExtractStringSigned(res, base, len, str);
313 }
314 
315 int ByteExtractStringInt32(int32_t *res, int base, uint16_t len, const char *str)
316 {
317  int64_t i64;
318  int ret;
319 
320  ret = ByteExtractStringSigned(&i64, base, len, str);
321  if (ret <= 0) {
322  return ret;
323  }
324 
325  *res = (int32_t)i64;
326 
327  if ((int64_t)(*res) != i64) {
328  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
329  "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)INT_MAX);
330  return -1;
331  }
332 
333  return ret;
334 }
335 
336 int ByteExtractStringInt16(int16_t *res, int base, uint16_t len, const char *str)
337 {
338  int64_t i64;
339  int ret;
340 
341  ret = ByteExtractStringSigned(&i64, base, len, str);
342  if (ret <= 0) {
343  return ret;
344  }
345 
346  *res = (int16_t)i64;
347 
348  if ((int64_t)(*res) != i64) {
349  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
350  "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)SHRT_MAX);
351  return -1;
352  }
353 
354  return ret;
355 }
356 
357 int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str)
358 {
359  int64_t i64;
360  int ret;
361 
362  ret = ByteExtractStringSigned(&i64, base, len, str);
363  if (ret <= 0) {
364  return ret;
365  }
366 
367  *res = (int8_t)i64;
368 
369  if ((int64_t)(*res) != i64) {
370  SCLogError(SC_ERR_NUMERIC_VALUE_ERANGE, "Numeric value out of range "
371  "(%" PRIi64 " > %" PRIiMAX ")\n", i64, (intmax_t)CHAR_MAX);
372  return -1;
373  }
374 
375  return ret;
376 }
377 
378 /* UNITTESTS */
379 #ifdef UNITTESTS
380 
381 static int ByteTest01 (void)
382 {
383  uint16_t val = 0x0102;
384  uint16_t i16 = 0xbfbf;
385  uint8_t bytes[2] = { 0x02, 0x01 };
386  int ret = ByteExtractUint16(&i16, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
387 
388  if ((ret == 2) && (i16 == val)) {
389  return 1;
390  }
391 
392  return 0;
393 }
394 
395 static int ByteTest02 (void)
396 {
397  uint16_t val = 0x0102;
398  uint16_t i16 = 0xbfbf;
399  uint8_t bytes[2] = { 0x01, 0x02 };
400  int ret = ByteExtractUint16(&i16, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
401 
402  if ((ret == 2) && (i16 == val)) {
403  return 1;
404  }
405 
406  return 0;
407 }
408 
409 static int ByteTest03 (void)
410 {
411  uint32_t val = 0x01020304;
412  uint32_t i32 = 0xbfbfbfbf;
413  uint8_t bytes[4] = { 0x04, 0x03, 0x02, 0x01 };
414  int ret = ByteExtractUint32(&i32, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
415 
416  if ((ret == 4) && (i32 == val)) {
417  return 1;
418  }
419 
420  return 0;
421 }
422 
423 static int ByteTest04 (void)
424 {
425  uint32_t val = 0x01020304;
426  uint32_t i32 = 0xbfbfbfbf;
427  uint8_t bytes[4] = { 0x01, 0x02, 0x03, 0x04 };
428  int ret = ByteExtractUint32(&i32, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
429 
430  if ((ret == 4) && (i32 == val)) {
431  return 1;
432  }
433 
434  return 0;
435 }
436 
437 static int ByteTest05 (void)
438 {
439  uint64_t val = 0x0102030405060708ULL;
440  uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
441  uint8_t bytes[8] = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
442  int ret = ByteExtractUint64(&i64, BYTE_LITTLE_ENDIAN, sizeof(bytes), bytes);
443 
444  if ((ret == 8) && (i64 == val)) {
445  return 1;
446  }
447 
448  return 0;
449 }
450 
451 static int ByteTest06 (void)
452 {
453  uint64_t val = 0x0102030405060708ULL;
454  uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
455  uint8_t bytes[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
456  int ret = ByteExtractUint64(&i64, BYTE_BIG_ENDIAN, sizeof(bytes), bytes);
457 
458  if ((ret == 8) && (i64 == val)) {
459  return 1;
460  }
461 
462  return 0;
463 }
464 
465 static int ByteTest07 (void)
466 {
467  const char *str = "1234567890";
468  uint64_t val = 1234567890;
469  uint64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
470  int ret = ByteExtractStringUint64(&i64, 10, strlen(str), str);
471 
472  if ((ret == 10) && (i64 == val)) {
473  return 1;
474  }
475 
476  return 0;
477 }
478 
479 static int ByteTest08 (void)
480 {
481  const char *str = "1234567890";
482  uint32_t val = 1234567890;
483  uint32_t i32 = 0xbfbfbfbf;
484  int ret = ByteExtractStringUint32(&i32, 10, strlen(str), str);
485 
486  if ((ret == 10) && (i32 == val)) {
487  return 1;
488  }
489 
490  return 0;
491 }
492 
493 static int ByteTest09 (void)
494 {
495  const char *str = "12345";
496  uint16_t val = 12345;
497  uint16_t i16 = 0xbfbf;
498  int ret = ByteExtractStringUint16(&i16, 10, strlen(str), str);
499 
500  if ((ret == 5) && (i16 == val)) {
501  return 1;
502  }
503 
504  return 0;
505 }
506 
507 static int ByteTest10 (void)
508 {
509  const char *str = "123";
510  uint8_t val = 123;
511  uint8_t i8 = 0xbf;
512  int ret = ByteExtractStringUint8(&i8, 10, strlen(str), str);
513 
514  if ((ret == 3) && (i8 == val)) {
515  return 1;
516  }
517 
518  return 0;
519 }
520 
521 static int ByteTest11 (void)
522 {
523  const char *str = "-1234567890";
524  int64_t val = -1234567890;
525  int64_t i64 = 0xbfbfbfbfbfbfbfbfULL;
526  int ret = ByteExtractStringInt64(&i64, 10, strlen(str), str);
527 
528  if ((ret == 11) && (i64 == val)) {
529  return 1;
530  }
531 
532  return 0;
533 }
534 
535 static int ByteTest12 (void)
536 {
537  const char *str = "-1234567890";
538  int32_t val = -1234567890;
539  int32_t i32 = 0xbfbfbfbf;
540  int ret = ByteExtractStringInt32(&i32, 10, strlen(str), str);
541 
542  if ((ret == 11) && (i32 == val)) {
543  return 1;
544  }
545 
546  return 0;
547 }
548 
549 static int ByteTest13 (void)
550 {
551  const char *str = "-12345";
552  int16_t val = -12345;
553  int16_t i16 = 0xbfbf;
554  int ret = ByteExtractStringInt16(&i16, 10, strlen(str), str);
555 
556  if ((ret == 6) && (i16 == val)) {
557  return 1;
558  }
559 
560  return 0;
561 }
562 
563 static int ByteTest14 (void)
564 {
565  const char *str = "-123";
566  int8_t val = -123;
567  int8_t i8 = 0xbf;
568  int ret = ByteExtractStringInt8(&i8, 10, strlen(str), str);
569 
570  if ((ret == 4) && (i8 == val)) {
571  return 1;
572  }
573 
574  return 0;
575 }
576 
577 /** \test max u32 value */
578 static int ByteTest15 (void)
579 {
580  const char *str = "4294967295";
581  uint32_t val = 4294967295UL;
582  uint32_t u32 = 0xffffffff;
583 
584  int ret = ByteExtractStringUint32(&u32, 10, strlen(str), str);
585  if ((ret == 10) && (u32 == val)) {
586  return 1;
587  }
588 
589  return 0;
590 }
591 
592 /** \test max u32 value + 1 */
593 static int ByteTest16 (void)
594 {
595  const char *str = "4294967296";
596  uint32_t u32 = 0;
597 
598  int ret = ByteExtractStringUint32(&u32, 10, strlen(str), str);
599  if (ret != 0) {
600  return 1;
601  }
602 
603  return 0;
604 }
605 
607 {
608  UtRegisterTest("ByteTest01", ByteTest01);
609  UtRegisterTest("ByteTest02", ByteTest02);
610  UtRegisterTest("ByteTest03", ByteTest03);
611  UtRegisterTest("ByteTest04", ByteTest04);
612  UtRegisterTest("ByteTest05", ByteTest05);
613  UtRegisterTest("ByteTest06", ByteTest06);
614  UtRegisterTest("ByteTest07", ByteTest07);
615  UtRegisterTest("ByteTest08", ByteTest08);
616  UtRegisterTest("ByteTest09", ByteTest09);
617  UtRegisterTest("ByteTest10", ByteTest10);
618  UtRegisterTest("ByteTest11", ByteTest11);
619  UtRegisterTest("ByteTest12", ByteTest12);
620  UtRegisterTest("ByteTest13", ByteTest13);
621  UtRegisterTest("ByteTest14", ByteTest14);
622  UtRegisterTest("ByteTest15", ByteTest15);
623  UtRegisterTest("ByteTest16", ByteTest16);
624 }
625 #endif /* UNITTESTS */
626 
#define SCLogDebug(...)
Definition: util-debug.h:335
int ByteExtractStringInt32(int32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:315
int ByteExtractStringUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:196
int ByteExtractStringUint8(uint8_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:238
int ByteExtractStringUint16(uint16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:217
int ByteExtractStringUint64(uint64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:191
#define str(s)
uint16_t dst
#define SCCalloc(nm, a)
Definition: util-mem.h:205
int ByteExtractStringInt64(int64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:310
int ByteExtractStringInt16(int16_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:336
#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:259
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#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:40
#define BYTE_LITTLE_ENDIAN
Definition: util-byte.h:30
void ByteRegisterTests(void)
Definition: util-byte.c:606
PoolThreadReserved res
int ByteExtractString(uint64_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:137
int ByteExtractUint64(uint64_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:74
int ByteExtractUint16(uint16_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:116
int ByteExtractStringInt8(int8_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:357
uint8_t len
int ByteExtractUint32(uint32_t *res, int e, uint16_t len, const uint8_t *bytes)
Definition: util-byte.c:95