summaryrefslogtreecommitdiff
path: root/src/sp_config_scanner.re
diff options
context:
space:
mode:
authorBen Fuhrmannek2021-08-31 21:14:57 +0200
committerBen Fuhrmannek2021-08-31 21:14:57 +0200
commit5cdfa697666c0ed347aaa086953b7e9c7f8aa9f9 (patch)
treebd513c80149a941105963d8474881989f09bf6cc /src/sp_config_scanner.re
parent8f689157b3857f82e0ad0a8b87609e83561d81fb (diff)
basic condition suuport for rules files
Diffstat (limited to 'src/sp_config_scanner.re')
-rw-r--r--src/sp_config_scanner.re54
1 files changed, 52 insertions, 2 deletions
diff --git a/src/sp_config_scanner.re b/src/sp_config_scanner.re
index 33362fc..b36423b 100644
--- a/src/sp_config_scanner.re
+++ b/src/sp_config_scanner.re
@@ -71,6 +71,21 @@ static void str_dtor(zval *zv) {
71 zend_string_release_ex(Z_STR_P(zv), 1); 71 zend_string_release_ex(Z_STR_P(zv), 1);
72} 72}
73 73
74static int apply_op(int v1, char op, int v2, int neg) {
75 if (neg) { v2 = !v2; }
76 switch (op) {
77 case 0: return v2;
78 case '&': return (v1 && v2);
79 case '|': return (v1 || v2);
80 case '<': return (v1 < v2);
81 case '>': return (v1 > v2);
82 case '=': return (v1 == v2);
83 }
84 return 0;
85}
86
87#define APPLY_OP(v2) cond_res = apply_op(cond_res, cond_op, v2, cond_neg); cond_op = cond_neg = 0;
88
74zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_keyword*)) 89zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_keyword*))
75{ 90{
76 const char *YYCURSOR = data; 91 const char *YYCURSOR = data;
@@ -86,6 +101,10 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key
86 HashTable vars; 101 HashTable vars;
87 zend_hash_init(&vars, 10, NULL, str_dtor, 1); 102 zend_hash_init(&vars, 10, NULL, str_dtor, 1);
88 103
104 int cond_res = 1;
105 char cond_op = 0;
106 int cond_neg = 0;
107
89 int cond = yycinit; 108 int cond = yycinit;
90 long lineno = 1; 109 long lineno = 1;
91 110
@@ -101,7 +120,6 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key
101 end = "\x00"; 120 end = "\x00";
102 nl = "\r"?"\n"; 121 nl = "\r"?"\n";
103 ws = [ \t]; 122 ws = [ \t];
104 wsnl = [ \t\r\n];
105 keyword = [a-zA-Z_][a-zA-Z0-9_]*; 123 keyword = [a-zA-Z_][a-zA-Z0-9_]*;
106 string = "\"" ("\\\"" | [^"\r\n])* "\""; 124 string = "\"" ("\\\"" | [^"\r\n])* "\"";
107 125
@@ -111,7 +129,7 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key
111 <init> nl { lineno++; goto yyc_init; } 129 <init> nl { lineno++; goto yyc_init; }
112 <init> "sp" { kw_i = 0; goto yyc_rule; } 130 <init> "sp" { kw_i = 0; goto yyc_rule; }
113 <init> end { ret = SUCCESS; goto out; } 131 <init> end { ret = SUCCESS; goto out; }
114 <init> "set" wsnl+ @t1 keyword @t2 wsnl+ @t3 string @t4 ";"? { 132 <init> "set" ws+ @t1 keyword @t2 ws+ @t3 string @t4 ws* ";"? {
115 char *key = (char*)t1; 133 char *key = (char*)t1;
116 int keylen = t2-t1; 134 int keylen = t2-t1;
117 zend_string *tmp = zend_hash_str_find_ptr(&vars, key, keylen); 135 zend_string *tmp = zend_hash_str_find_ptr(&vars, key, keylen);
@@ -122,11 +140,42 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key
122 zend_hash_str_add_ptr(&vars, key, keylen, tmp); 140 zend_hash_str_add_ptr(&vars, key, keylen, tmp);
123 goto yyc_init; 141 goto yyc_init;
124 } 142 }
143 <init> "@condition" ws+ { goto yyc_cond; }
144 <init> "@end_condition" ws* ";" { cond_res = 1; goto yyc_init; }
125 145
146 <cond> ws+ { goto yyc_cond; }
147 <cond> nl { lineno++; goto yyc_cond; }
148 <cond> @t1 keyword @t2 "(" @t3 string? @t4 ")" {
149 if (t4-t3 >= 2 && strlen("extension_loaded") == t2-t1 && strncmp("extension_loaded", t1, t2-t1) == 0) {
150 int is_loaded = (zend_hash_str_find_ptr(&module_registry, t3+1, t4-t3-2) != NULL);
151 APPLY_OP(is_loaded);
152 } else {
153 cs_error_log("unknown function in condition on line %d", lineno);
154 goto out;
155 }
156 goto yyc_cond_op;
157 }
158 <cond> @t1 keyword @t2 {
159 zend_string *tmp = zend_hash_str_find_ptr(&vars, t1, t2-t1);
160 if (!tmp) {
161 cs_error_log("unknown variable in condition on line %d", lineno);
162 goto out;
163 }
164 APPLY_OP(atoi(ZSTR_VAL(tmp)));
165 goto yyc_cond_op;
166 }
167 <cond> @t1 [0-9]+ @t2 { APPLY_OP(atoi(t1)); goto yyc_cond_op; }
168 <cond> @t1 "!" { cond_neg = (cond_neg + 1) % 2; goto yyc_cond; }
169 <cond_op> ws+ { goto yyc_cond_op; }
170 <cond_op> nl { lineno++; goto yyc_cond_op; }
171 <cond_op> @t1 ( "&&" | "||" | "<" | ">" | "==" ) { cond_op = *t1; goto yyc_cond; }
172 <cond_op> ";" { goto yyc_init; }
173 <cond, cond_op> * { cs_error_log("Syntax error in condition on line %d", lineno); return false; }
126 174
127 <rule> ws+ { goto yyc_rule; } 175 <rule> ws+ { goto yyc_rule; }
128 <rule> nl / ( nl | ws )* "." { lineno++; goto yyc_rule; } 176 <rule> nl / ( nl | ws )* "." { lineno++; goto yyc_rule; }
129 <rule> "." @t1 keyword @t2 ( "(" @t3 ( string? | keyword ) @t4 ")" )? { 177 <rule> "." @t1 keyword @t2 ( "(" @t3 ( string? | keyword ) @t4 ")" )? {
178 if (!cond_res) { goto yyc_rule; }
130 if (kw_i == max_keywords) { 179 if (kw_i == max_keywords) {
131 cs_error_log("Too many keywords in rule (more than %d) on line %d", max_keywords, lineno); 180 cs_error_log("Too many keywords in rule (more than %d) on line %d", max_keywords, lineno);
132 goto out; 181 goto out;
@@ -157,6 +206,7 @@ zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_key
157 } 206 }
158 <rule> ";" { 207 <rule> ";" {
159 end_of_rule: 208 end_of_rule:
209 if (!cond_res) { goto yyc_init; }
160 parsed_rule[kw_i++] = (sp_parsed_keyword){0, 0, 0, 0, 0, 0}; 210 parsed_rule[kw_i++] = (sp_parsed_keyword){0, 0, 0, 0, 0, 0};
161 if (process_rule && process_rule(parsed_rule) != SUCCESS) { 211 if (process_rule && process_rule(parsed_rule) != SUCCESS) {
162 goto out; 212 goto out;