Browse code

bcomp - adding comma seperated comparison statement evaluations for single subsigs

Mickey Sola authored on 2018/09/28 08:37:04
Showing 2 changed files
... ...
@@ -62,6 +62,7 @@
62 62
 cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, const char *hexsig, const uint32_t *lsigid, unsigned int options) {
63 63
 
64 64
     size_t len = 0;
65
+    uint32_t i = 0;
65 66
     const char *buf_start = NULL;
66 67
     const char *buf_end = NULL;
67 68
     char *buf = NULL;
... ...
@@ -72,6 +73,9 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
72 72
     int64_t ret = CL_SUCCESS;
73 73
     size_t byte_length = 0;
74 74
     int64_t comp_val = 0;
75
+    char *comp_buf = NULL;
76
+    char *comp_start = NULL;
77
+    char *comp_end = NULL;
75 78
     char *hexcpy = NULL;
76 79
 
77 80
     if (!hexsig || !(*hexsig) || !root || !virname) {
... ...
@@ -289,47 +293,108 @@ cl_error_t cli_bcomp_addpatt(struct cli_matcher *root, const char *virname, cons
289 289
 
290 290
     bcomp->byte_len = byte_length;
291 291
 
292
-    /* currently only >, <, and = are supported comparison symbols--this makes parsing very simple */
293
-    buf_start = tokens[2];
294
-    switch (*buf_start) {
295
-        case '<':
296
-        case '>':
297
-        case '=':
298
-            bcomp->comp_symbol = *buf_start;    break;
292
+    /* we can have up to two comparison eval statements, each sperated by a comma, let's parse them in a separate string */
293
+    comp_buf = cli_strdup(tokens[2]);
294
+    if (!comp_buf) {
295
+        cli_errmsg("cli_bcomp_addpatt: Unable to allocate memory for comparison buffer\n");
296
+        cli_bcomp_freemeta(root, bcomp);
297
+        return CL_EMEM;
298
+    }
299
+    /* use different buffer start and end markers so we can keep track of what we need to free later */
300
+    buf_start = comp_buf;
301
+    comp_start = strchr(comp_buf, ',');
302
+    comp_end = strrchr(comp_buf, ',');
299 303
 
300
-        default:
301
-            cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte comparison symbol was invalid (>, <, = are supported operators)\n", tokens[0], tokens[1], tokens[2]);
302
-            free(buf);
304
+    /* check to see if we have exactly one comma, then set our count and tokenize our string apropriately */
305
+    if (comp_start && comp_end) {
306
+        if (comp_end == comp_start) {
307
+            comp_start[0] = '\0';
308
+            bcomp->comp_count = 2;
309
+
310
+        } else {
311
+            cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), too many commas found in comparison string\n", tokens[0], tokens[1], tokens[2]);
303 312
             cli_bcomp_freemeta(root, bcomp);
304
-            return CL_EMALFDB;
313
+            free(buf);
314
+            free((void*)buf_start);
315
+            return CL_EPARSE;
316
+        }
317
+    } else {
318
+        comp_start = comp_buf;
319
+        bcomp->comp_count = 1;
305 320
     }
306 321
 
307
-
308
-    /* no more tokens after this, so we take advantage of strtoll and check if the buf_end is null terminated or not */
309
-    buf_start++;
310
-    buf_end = NULL;
311
-    comp_val = strtoll(buf_start, (char **) &buf_end, 0);
312
-    if (*buf_end) {
313
-        cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), comparison value contained invalid input\n", tokens[0], tokens[1], tokens[2]);
322
+    /* allocate comp struct list space with the root structure's mempool instance */
323
+    bcomp->comps = (struct cli_bcomp_comp **) mpool_calloc(root->mempool, bcomp->comp_count, sizeof(struct cli_bcomp_comp *));
324
+    if(!bcomp->comps) {
325
+        cli_errmsg("cli_bcomp_addpatt: unable to allocate memory for comp struct pointers\n");
314 326
         free(buf);
327
+        free((void*)buf_start);
315 328
         cli_bcomp_freemeta(root, bcomp);
316
-        return CL_EMALFDB;
329
+        return CL_EMEM;
317 330
     }
318 331
 
319
-    bcomp->comp_value = comp_val;
332
+    /* loop through our new list, allocate, and parse out the needed comparison evaluation bits for this subsig */
333
+    for (i = 0; i < bcomp->comp_count; i++) {
334
+
335
+        bcomp->comps[i] = (struct cli_bcomp_comp*) mpool_calloc(root->mempool, 1, sizeof(struct cli_bcomp_comp));
336
+        if(!bcomp->virname) {
337
+            cli_errmsg("cli_bcomp_addpatt: unable to allocate memory for comp struct\n");
338
+            free(buf);
339
+            free((void*)buf_start);
340
+            cli_bcomp_freemeta(root, bcomp);
341
+            return CL_EMEM;
342
+        }
343
+
344
+        /* currently only >, <, and = are supported comparison symbols--this makes parsing very simple */
345
+        switch (*comp_buf) {
346
+            case '<':
347
+            case '>':
348
+            case '=':
349
+                bcomp->comps[i]->comp_symbol = *comp_buf;    break;
350
+
351
+            default:
352
+                cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), byte comparison symbol was invalid (>, <, = are supported operators) %s\n", tokens[0], tokens[1], tokens[2], comp_buf);
353
+                free(buf);
354
+                free((void*)buf_start);
355
+                cli_bcomp_freemeta(root, bcomp);
356
+                return CL_EMALFDB;
357
+        }
358
+
359
+        /* grab the comparison value itself */
360
+        comp_end = NULL;
361
+        comp_buf++;
362
+        comp_val = strtoll(comp_buf, (char **) &comp_end, 0);
363
+        if (*comp_end) {
364
+            cli_errmsg("cli_bcomp_addpatt: while parsing (%s#%s#%s), comparison value contained invalid input\n", tokens[0], tokens[1], tokens[2]);
365
+            free(buf);
366
+            free((void*)buf_start);
367
+            cli_bcomp_freemeta(root, bcomp);
368
+            return CL_EMALFDB;
369
+        }
370
+
371
+        bcomp->comps[i]->comp_value = comp_val;
372
+
373
+        /* a bit of tricksy pointer stuffs which handles all count cases, taking advantage of where strtoll drops endptr */
374
+        if (comp_end == comp_start) {
375
+            comp_buf = comp_start;
376
+            comp_buf++;
377
+        }
320 378
 
321
-    /* manually verify successful pattern parsing */
322
-    bcm_dbgmsg("Matcher Byte Compare: (%s%ld#%c%c%s%zu#%c%ld)\n",
323
-                    bcomp->offset ==  0 ? "" : 
324
-                    (bcomp->offset < 0 ? "<<" : ">>"),
325
-                    bcomp->offset,
326
-                    bcomp->options & CLI_BCOMP_HEX ? 'h' : (bcomp->options & CLI_BCOMP_DEC ? 'd' : 'i'),
327
-                    bcomp->options & CLI_BCOMP_LE ? 'l' : 'b',
328
-                    bcomp->options & CLI_BCOMP_EXACT ? "e" : "",
329
-                    bcomp->byte_len,
330
-                    bcomp->comp_symbol,
331
-                    bcomp->comp_value);
379
+        /* manually verify successful pattern parsing */
380
+        bcm_dbgmsg("Matcher Byte Compare: (%s%ld#%c%c%s%zu#%c%ld)\n",
381
+                bcomp->offset ==  0 ? "" :
382
+                (bcomp->offset < 0 ? "<<" : ">>"),
383
+                bcomp->offset,
384
+                bcomp->options & CLI_BCOMP_HEX ? 'h' : (bcomp->options & CLI_BCOMP_DEC ? 'd' : 'i'),
385
+                bcomp->options & CLI_BCOMP_LE ? 'l' : 'b',
386
+                bcomp->options & CLI_BCOMP_EXACT ? "e" : "",
387
+                bcomp->byte_len,
388
+                bcomp->comps[i]->comp_symbol,
389
+                bcomp->comps[i]->comp_value);
390
+    }
332 391
 
392
+    free((void*)buf_start);
393
+    buf_start = NULL;
333 394
     /* add byte compare info to the root after reallocation */
334 395
     bcomp_count = root->bcomp_metas+1;
335 396
 
... ...
@@ -468,6 +533,8 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
468 468
 
469 469
     uint32_t byte_len = 0;
470 470
     uint32_t length = 0;
471
+    uint32_t i = 0;
472
+    cl_error_t ret = 0;
471 473
     uint16_t opt = 0;
472 474
     const unsigned char *buffer = NULL;
473 475
     unsigned char *conversion_buf = NULL;
... ...
@@ -623,37 +690,51 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
623 623
     }
624 624
 
625 625
     /* do the actual comparison */
626
-    switch (bm->comp_symbol) {
626
+    ret = CL_CLEAN;
627
+    for (i = 0; i < bm->comp_count; i++) {
628
+        if (bm->comps && bm->comps[i]) {
629
+            switch (bm->comps[i]->comp_symbol) {
630
+
631
+                case '>':
632
+                    if (value > bm->comps[i]->comp_value) {
633
+                        bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) greater than comparison value (%ld)\n", value, bm->comps[i]->comp_value);
634
+                        ret = CL_VIRUS;
635
+                    } else {
636
+                        ret = CL_CLEAN;
637
+                    }
638
+                    break;
627 639
 
628
-        case '>':
629
-            if (value > bm->comp_value) {
630
-                bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) greater than comparison value (%ld)\n", value, bm->comp_value);
631
-                return CL_VIRUS;
632
-            }
633
-            break;
640
+                case '<':
641
+                    if (value < bm->comps[i]->comp_value) {
642
+                        bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) less than comparison value (%ld)\n", value, bm->comps[i]->comp_value);
643
+                        ret = CL_VIRUS;
644
+                    } else {
645
+                        ret = CL_CLEAN;
646
+                    }
647
+                    break;
634 648
 
635
-        case '<':
636
-            if (value < bm->comp_value) {
637
-                bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) less than comparison value (%ld)\n", value, bm->comp_value);
638
-                return CL_VIRUS;
639
-            }
640
-            break;
649
+                case '=':
650
+                    if (value == bm->comps[i]->comp_value) {
651
+                        bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) equal to comparison value (%ld)\n", value, bm->comps[i]->comp_value);
652
+                        ret = CL_VIRUS;
653
+                    } else {
654
+                        ret = CL_CLEAN;
655
+                    }
656
+                    break;
641 657
 
642
-        case '=':
643
-            if (value == bm->comp_value) {
644
-                bcm_dbgmsg("cli_bcomp_compare_check: extracted value (%ld) equal to comparison value (%ld)\n", value, bm->comp_value);
645
-                return CL_VIRUS;
658
+                default:
659
+                    bcm_dbgmsg("cli_bcomp_compare_check: comparison symbol (%c) invalid\n", bm->comps[i]->comp_symbol);
660
+                    return CL_ENULLARG;
646 661
             }
647
-            break;
648 662
 
649
-        default:
650
-            bcm_dbgmsg("cli_bcomp_compare_check: comparison symbol (%c) invalid\n", bm->comp_symbol);
651
-            return CL_ENULLARG;
663
+            if (CL_CLEAN == ret) {
664
+                /* comparison was not successful */
665
+                bcm_dbgmsg("cli_bcomp_compare_check: extracted value was not %c %ld\n", bm->comps[i]->comp_symbol, bm->comps[i]->comp_value);
666
+                return CL_CLEAN;
667
+            }
668
+        }
652 669
     }
653
-
654
-    /* comparison was not successful */
655
-    bcm_dbgmsg("cli_bcomp_compare_check: extracted value was not %c %ld\n", bm->comp_symbol, bm->comp_value);
656
-    return CL_CLEAN;
670
+    return ret;
657 671
 }
658 672
 
659 673
 /**
... ...
@@ -665,6 +746,8 @@ cl_error_t cli_bcomp_compare_check(fmap_t *map, int offset, struct cli_bcomp_met
665 665
  */
666 666
 void cli_bcomp_freemeta(struct cli_matcher *root, struct cli_bcomp_meta *bm) {
667 667
 
668
+    int i = 0;
669
+
668 670
     if(!root || !bm) {
669 671
         return;
670 672
     }
... ...
@@ -673,7 +756,20 @@ void cli_bcomp_freemeta(struct cli_matcher *root, struct cli_bcomp_meta *bm) {
673 673
         mpool_free(root->mempool, bm->virname);
674 674
         bm->virname = NULL;
675 675
     }
676
-    
676
+
677
+    /* can never have more than 2 */
678
+    if (bm->comps) {
679
+        for (i = 0; i < 2; i++) {
680
+            if (bm->comps[i]) {
681
+                mpool_free(root->mempool, bm->comps[i]);
682
+                bm->comps[i] = NULL;
683
+            }
684
+        }
685
+
686
+        mpool_free(root->mempool, bm->comps);
687
+        bm->comps = NULL;
688
+    }
689
+
677 690
     mpool_free(root->mempool, bm);
678 691
     bm = NULL;
679 692
 
... ...
@@ -45,11 +45,17 @@
45 45
 
46 46
 struct cli_bcomp_meta {
47 47
     char *virname;
48
-    uint16_t ref_subsigid; /* identifies the dependent subsig from which we will do comparisons from */
48
+    uint16_t ref_subsigid; /* identifies the dependent subsig from which we will do comparisons */
49 49
     uint32_t lsigid[3];
50 50
     ssize_t offset; /* offset from the referenced subsig, handled at match-time */
51 51
     uint16_t options; /* bitmask */
52 52
     size_t byte_len;
53
+    struct cli_bcomp_comp **comps;
54
+    uint32_t comp_count;
55
+};
56
+
57
+/* each byte compare subsig can perform multiple comparisons on the same extracted byte sequence */
58
+struct cli_bcomp_comp {
53 59
     char comp_symbol; /* <, >, = are supported */
54 60
     int64_t comp_value;
55 61
 };