diff options
| author | Ben Fuhrmannek | 2021-08-31 21:14:57 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-08-31 21:14:57 +0200 |
| commit | 5cdfa697666c0ed347aaa086953b7e9c7f8aa9f9 (patch) | |
| tree | bd513c80149a941105963d8474881989f09bf6cc /src/sp_config_scanner.re | |
| parent | 8f689157b3857f82e0ad0a8b87609e83561d81fb (diff) | |
basic condition suuport for rules files
Diffstat (limited to 'src/sp_config_scanner.re')
| -rw-r--r-- | src/sp_config_scanner.re | 54 |
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 | ||
| 74 | static 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 | |||
| 74 | zend_result sp_config_scan(char *data, zend_result (*process_rule)(sp_parsed_keyword*)) | 89 | zend_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; |
