Browse code

bcomp - fixing case where automatic detection would fail against little endian hex values; removing code for little endian decimal support; fixing some clang warnings; fixes for hexidecimal detection in sli_strnto functions; updating documentation

Mickey Sola authored on 2018/10/16 03:29:35
Showing 3 changed files
... ...
@@ -615,7 +615,7 @@ Byte compare subsignatures can be used to evaluate a numeric value at a given of
615 615
 
616 616
   - `h|d|a|i` where `h` specifies the byte sequence will be in hex, `d` decimal, `a` automatic detection of hex or decimal at runtime, and `i` signifies raw binary data.
617 617
 
618
-  - `l|b` where `l` specifies the byte sequence will be in little endian order and `b` big endian.
618
+  - `l|b` where `l` specifies the byte sequence will be in little endian order and `b` big endian. If decimal `d` is specified, big-endian is implied and using `l` will result in a malformed database error.
619 619
 
620 620
   - `e` specifies that ClamAV will only evaluate the comparison if it can extract the exact number of bytes specified. This option is implicitly declared when using the `i` flag.
621 621
 
... ...
@@ -131,7 +131,7 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
131 131
     /* use the passed hexsig buffer to find the start and ending parens and store the param length (minus starting paren) */
132 132
     buf_start = buf_end;
133 133
     if (buf_start[0] == '(') {
134
-        if (buf_end = strchr(buf_start, ')')) {
134
+        if (( buf_end = strchr(buf_start, ')') )) {
135 135
             len = (size_t) (buf_end - ++buf_start);
136 136
         }
137 137
         else {
... ...
@@ -230,10 +230,12 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
230 230
 
231 231
             case 'd':
232 232
                 /* hex, decimal, auto, and binary options are mutually exclusive parameters */
233
-                if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_BIN || bcomp->options & CLI_BCOMP_AUTO) {
233
+                /* decimal may not be used with little-endian. big-endian is implied. */
234
+                if (bcomp->options & CLI_BCOMP_HEX || bcomp->options & CLI_BCOMP_BIN || bcomp->options & CLI_BCOMP_AUTO || bcomp->options & CLI_BCOMP_LE) {
234 235
                     ret = CL_EMALFDB;
235 236
                 } else {
236 237
                     bcomp->options |= CLI_BCOMP_DEC;
238
+                    bcomp->options |= CLI_BCOMP_BE;
237 239
                 } break;
238 240
 
239 241
             case 'i':
... ...
@@ -255,7 +257,8 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
255 255
 
256 256
             case 'l':
257 257
                 /* little and big endian options are mutually exclusive parameters */
258
-                if (bcomp->options & CLI_BCOMP_BE) {
258
+                /* decimal may not be used with little-endian */
259
+                if (bcomp->options & CLI_BCOMP_BE || bcomp->options & CLI_BCOMP_DEC) {
259 260
                     ret = CL_EMALFDB;
260 261
                 } else {
261 262
                     bcomp->options |= CLI_BCOMP_LE;
... ...
@@ -485,7 +488,7 @@ cl_error_t cli_bcomp_scanbuf(const unsigned char *buffer, size_t buffer_length,
485 485
             }
486 486
 
487 487
             /* ensures the referenced subsig matches as expected, and also ensures mdata has the needed offset */
488
-            if (ret = lsig_sub_matched(root, mdata, lsigid, ref_subsigid, CLI_OFF_NONE, 0)) {
488
+            if (( ret = lsig_sub_matched(root, mdata, lsigid, ref_subsigid, CLI_OFF_NONE, 0) )) {
489 489
                 break;
490 490
             }
491 491
 
... ...
@@ -629,7 +632,17 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le
629 629
     opt_val = opt;
630 630
     if (opt_val & CLI_BCOMP_AUTO) {
631 631
         if (tmp_buffer) {
632
-            if(!strncmp((char*) tmp_buffer, "0x", 2) || !strncmp((char*) tmp_buffer, "0X", 2)) {
632
+            /* tmp_buffer is based on the size of byte_len, so we can check against that safely */
633
+            if ((opt & 0x00F0) & CLI_BCOMP_LE && byte_len >= 3) {
634
+                if(!strncmp((char*) &tmp_buffer[byte_len-2], "0x", 2) || !strncmp((char*) &tmp_buffer[byte_len-2], "0X", 2)) {
635
+                    tmp_buffer[byte_len-2] = '\0';
636
+                    bcm_dbgmsg("cli_bcomp_compare_check: adjusted bytes before comparison %.*s\n", byte_len-2, tmp_buffer);
637
+                    opt |= CLI_BCOMP_HEX;
638
+                } else {
639
+                    opt |= CLI_BCOMP_DEC;
640
+                }
641
+            }
642
+            else if(!strncmp((char*) tmp_buffer, "0x", 2) || !strncmp((char*) tmp_buffer, "0X", 2)) {
633 643
                 opt |= CLI_BCOMP_HEX;
634 644
             } else {
635 645
                 opt |= CLI_BCOMP_DEC;
... ...
@@ -689,28 +702,9 @@ cl_error_t cli_bcomp_compare_check(const unsigned char* buffer, size_t buffer_le
689 689
 
690 690
         /*dl*/
691 691
         case CLI_BCOMP_DEC | CLI_BCOMP_LE:
692
-            value = cli_strntol((char*) buffer, byte_len, (char**) &end_buf, 10);
693
-            if ((((value == LONG_MAX) || (value == LONG_MIN)) && errno == ERANGE) || NULL == end_buf) {
694
-
695
-                if (tmp_buffer) {
696
-                    free(tmp_buffer);
697
-                }
698
-                bcm_dbgmsg("cli_bcomp_compare_check: little endian decimal conversion unsuccessful\n");
699
-                return CL_CLEAN;
700
-            }
701
-            /*dle*/
702
-            if (opt & CLI_BCOMP_EXACT) {
703
-                if (buffer+byte_len != end_buf) {
704
-
705
-                    if (tmp_buffer) {
706
-                        free(tmp_buffer);
707
-                    }
708
-                    bcm_dbgmsg("cli_bcomp_compare_check: couldn't extract the exact number of requested bytes\n");
709
-                    return CL_CLEAN;
710
-                }
711
-            }
712
-
713
-            value = le64_to_host(value);
692
+            /* it may be possible for the auto option to proc this */
693
+            bcm_dbgmsg("cli_bcomp_compare_check: auto detection found ascii decimal for specified little endian byte extraction, which is unsupported\n");
694
+            return CL_CLEAN;
714 695
             break;
715 696
 
716 697
         /*db*/
... ...
@@ -577,7 +577,7 @@ long cli_strntol(const char* nptr, size_t n, char** endptr, register int base)
577 577
     }
578 578
 
579 579
     if (base == 0 || base == 16) {
580
-        if (c == '0' && (*s == 'x' || *s == 'X')) {
580
+        if (c == '0' && (s + 1 < nptr + n) && (*(s+1) == 'x' || *(s+1) == 'X')) {
581 581
             if (s + 2 >= nptr + n) {
582 582
                 goto done;
583 583
             }
... ...
@@ -696,7 +696,7 @@ cli_strntoul(const char* nptr, size_t n, char** endptr, register int base)
696 696
     }
697 697
 
698 698
     if (base == 0 || base == 16) {
699
-        if (c == '0' && (*s == 'x' || *s == 'X')) {
699
+        if (c == '0' && (s + 1 < nptr + n) && (*(s+1) == 'x' || *(s+1) == 'X')) {
700 700
             if (s + 2 >= nptr + n) {
701 701
                 goto done;
702 702
             }