Browse code

matcher-ac: wildcard support for variable alternates (needs optimization)

Kevin Lin authored on 2015/05/18 22:59:04
Showing 2 changed files
... ...
@@ -862,11 +862,44 @@ int cli_ac_chklsig(const char *expr, const char *end, uint32_t *lsigcnt, unsigne
862 862
 
863 863
 static int ac_findmatch_branch(const unsigned char *buffer, uint32_t offset, uint32_t length, uint32_t fileoffset, const struct cli_ac_patt *pattern, uint32_t pattoffset, uint16_t specialcnt, uint32_t *end);
864 864
 
865
+/* call only by ac_findmatch_special! Does not handle recursive specials */
866
+#define AC_MATCH_CHAR2(p,b)                                                             \
867
+    switch(wc = p & CLI_MATCH_METADATA) {                                               \
868
+    case CLI_MATCH_CHAR:                                                                \
869
+        if((unsigned char) p != b)                                                      \
870
+            match = 0;                                                                  \
871
+        break;                                                                          \
872
+                                                                                        \
873
+    case CLI_MATCH_NOCASE:                                                              \
874
+        if((unsigned char)(p & 0xff) != cli_nocase(b))                                  \
875
+            match = 0;                                                                  \
876
+        break;                                                                          \
877
+                                                                                        \
878
+    case CLI_MATCH_IGNORE:                                                              \
879
+        break;                                                                          \
880
+                                                                                        \
881
+    case CLI_MATCH_NIBBLE_HIGH:                                                         \
882
+        if((unsigned char) (p & 0x00f0) != (b & 0xf0))                                  \
883
+            match = 0;                                                                  \
884
+        break;                                                                          \
885
+                                                                                        \
886
+    case CLI_MATCH_NIBBLE_LOW:                                                          \
887
+        if((unsigned char) (p & 0x000f) != (b & 0x0f))                                  \
888
+            match = 0;                                                                  \
889
+        break;                                                                          \
890
+                                                                                        \
891
+    default:                                                                            \
892
+        cli_errmsg("ac_findmatch: Unknown metatype 0x%x\n", wc);                        \
893
+        match = 0;                                                                      \
894
+    }
895
+
896
+
865 897
 /* special handler */
866 898
 inline static int ac_findmatch_special(const unsigned char *buffer, uint32_t offset, uint32_t fileoffset, uint32_t length, const struct cli_ac_patt *pattern, uint32_t pattoffset, uint16_t specialcnt, uint32_t *end)
867 899
 {
868 900
     int match, cmp;
869 901
     uint16_t j, b = buffer[offset];
902
+    uint16_t wc;
870 903
     struct cli_ac_special *special = pattern->special_table[specialcnt];
871 904
     struct cli_alt_node *alt = NULL;
872 905
 
... ...
@@ -905,14 +938,18 @@ inline static int ac_findmatch_special(const unsigned char *buffer, uint32_t off
905 905
             }
906 906
 
907 907
             /* note that generic alternates CANNOT be negated */
908
-            /* generic alternates are sorted alphabetically   */
909
-            cmp = memcmp(&buffer[offset], alt->str, alt->len);
910
-            if (!cmp) {
908
+            match = 1;
909
+            for (j = 0; j < alt->len; j++) {
910
+                AC_MATCH_CHAR2(alt->str[j],buffer[offset+j]);
911
+                if (!match)
912
+                    break;
913
+            }
914
+            if (match) {
915
+                /* TODO - if match is unique, we can pass it directly back */
911 916
                 match = ac_findmatch_branch(buffer, offset+alt->len, fileoffset, length, pattern, pattoffset+1, specialcnt+1, end);
912 917
                 if (match)
913 918
                     return -1; /* alerts caller that match has been resolved in child callee */
914
-            } else if (cmp < 0)
915
-                break;
919
+            }
916 920
 
917 921
             alt = alt->next;
918 922
         }
... ...
@@ -943,16 +980,6 @@ inline static int ac_findmatch_special(const unsigned char *buffer, uint32_t off
943 943
     return match;
944 944
 }
945 945
 
946
-/* using verifier for nocase instead of preprocessing pattern
947
-    case CLI_MATCH_CHAR:                                                                \
948
-        if((unsigned char) p != b)                                                      \
949
-            if(!(o & ACPATT_OPTION_NOCASE))                                             \
950
-                match = 0;                                                              \
951
-            else if((unsigned char)(p & 0xff) != cli_nocase(b))                         \
952
-                match = 0;                                                              \
953
-        break;                                                                          \
954
-*/
955
-
956 946
 /* call only by ac_findmatch_branch! */
957 947
 #define AC_MATCH_CHAR(p,b)                                                              \
958 948
     switch(wc = p & CLI_MATCH_METADATA) {                                               \
... ...
@@ -989,7 +1016,7 @@ inline static int ac_findmatch_special(const unsigned char *buffer, uint32_t off
989 989
         break;                                                                          \
990 990
                                                                                         \
991 991
     default:                                                                            \
992
-        cli_errmsg("ac_findmatch: Unknown wildcard 0x%x\n", wc);                        \
992
+        cli_errmsg("ac_findmatch: Unknown metatype 0x%x\n", wc);                        \
993 993
         match = 0;                                                                      \
994 994
     }
995 995
 
... ...
@@ -1901,6 +1928,8 @@ inline static int ac_analyze_expr(char *hexstr, int *fixed_len, int *sub_len)
1901 1901
             len = 0;
1902 1902
             numexpr++;
1903 1903
         } else {
1904
+            if (hexstr[i] == '?')
1905
+                flen = 0;
1904 1906
             len++;
1905 1907
         }
1906 1908
         //cli_altnmsg("%c, %d\n", hexstr[i], len);
... ...
@@ -1920,7 +1949,7 @@ inline static int ac_analyze_expr(char *hexstr, int *fixed_len, int *sub_len)
1920 1920
 inline static int ac_addspecial_add_alt_node(const char *subexpr, struct cli_ac_special *special, struct cli_matcher *root)
1921 1921
 {
1922 1922
     struct cli_alt_node *newnode, **prev, *ins;
1923
-    char *c;
1923
+    uint16_t *s;
1924 1924
     int cmp;
1925 1925
 
1926 1926
     newnode = (struct cli_alt_node *)mpool_calloc(root->mempool, 1, sizeof(struct cli_alt_node));
... ...
@@ -1929,29 +1958,30 @@ inline static int ac_addspecial_add_alt_node(const char *subexpr, struct cli_ac_
1929 1929
         return CL_EMEM;
1930 1930
     }
1931 1931
 
1932
-    c = (char *)cli_mpool_hex2str(root->mempool, subexpr);
1933
-    if (!c) {
1932
+    s = cli_mpool_hex2ui(root->mempool, subexpr);
1933
+    if (!s) {
1934 1934
         free(newnode);
1935 1935
         return CL_EMALFDB;
1936 1936
     }
1937 1937
 
1938
-    newnode->str = c;
1938
+    newnode->str = s;
1939 1939
     newnode->len = strlen(subexpr)/2;
1940 1940
 
1941 1941
     /* search for location to insert node (alphabetically through memcmp) */
1942 1942
     prev = &((special->alt).v_str);
1943 1943
     ins = (special->alt).v_str;
1944 1944
     while (ins) {
1945
+        /*
1945 1946
         if (ins->len == newnode->len) {
1946
-            cmp = memcmp(newnode->str, ins->str, ins->len); /* TODO - change when uint16_t is used */
1947
-            if (cmp == 0) { /* duplicate */
1947
+            cmp = memcmp(newnode->str, ins->str, ins->len); // TODO - change when uint16_t is used
1948
+            if (cmp == 0) { // duplicate
1948 1949
                 free(newnode);
1949 1950
                 return CL_SUCCESS;
1950 1951
             } else if (cmp < 0) {
1951 1952
                 break;
1952 1953
             }
1953 1954
         }
1954
-
1955
+        */
1955 1956
         prev = &(ins->next);
1956 1957
         ins = ins->next;
1957 1958
     }
... ...
@@ -68,8 +68,8 @@ struct cli_ac_data {
68 68
 };
69 69
 
70 70
 struct cli_alt_node {
71
-    //uint16_t *str;
72
-    unsigned char *str;
71
+    uint16_t *str;
72
+    //unsigned char *str;
73 73
     uint16_t len;
74 74
     struct cli_alt_node *next;
75 75
 };