summaryrefslogtreecommitdiff
path: root/src/sp_var_value.c
diff options
context:
space:
mode:
authorxXx-caillou-xXx2017-12-20 18:09:53 +0100
committerjvoisin2017-12-20 18:09:53 +0100
commite7f541396715ee2895abcf73044b91ae9b746201 (patch)
treeba0e9765e7f14f04b92585df1f3fcd1830ab4b00 /src/sp_var_value.c
parent8d6cc4f2b63c3f0dc31fe6cecd34ac023ea1cccb (diff)
Better parsing of the rules
Thanks to this huge commit from @xXx-caillou-xXx, we can now write amazingly flexible rules.
Diffstat (limited to 'src/sp_var_value.c')
-rw-r--r--src/sp_var_value.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/src/sp_var_value.c b/src/sp_var_value.c
new file mode 100644
index 0000000..304ece9
--- /dev/null
+++ b/src/sp_var_value.c
@@ -0,0 +1,226 @@
1#include "php_snuffleupagus.h"
2
3static zval *get_param_var(zend_execute_data *ed, const char *var_name) {
4 unsigned int nb_param = ed->func->common.num_args;
5
6 for (unsigned int i = 0; i < nb_param; i++) {
7 const char *arg_name;
8 if (ZEND_USER_CODE(ed->func->type)) {
9 arg_name = ZSTR_VAL(ed->func->common.arg_info[i].name);
10 } else {
11 arg_name = ed->func->internal_function.arg_info[i].name;
12 }
13 if (0 == strcmp(arg_name, var_name)) {
14 return ZEND_CALL_VAR_NUM(ed, i);
15 }
16 }
17 return NULL;
18}
19
20static zval *get_local_var(zend_execute_data *ed, const char *var_name) {
21 zend_execute_data *orig_execute_data = ed;
22 zend_execute_data *current = ed;
23 zval *value = NULL;
24
25 while (current) {
26 zend_string* key = NULL;
27 EG(current_execute_data) = current;
28 zend_array* symtable = zend_rebuild_symbol_table();
29 ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, key, value) {
30 if (0 == strcmp(var_name, key->val)) {
31 if (Z_TYPE_P(value) == IS_INDIRECT) {
32 value = Z_INDIRECT_P(value);
33 }
34 EG(current_execute_data) = orig_execute_data;
35 return value;
36 }
37 }
38 ZEND_HASH_FOREACH_END();
39 current = current->prev_execute_data;
40 }
41 EG(current_execute_data) = orig_execute_data;
42 return NULL;
43}
44
45static zval *get_constant(const char *value) {
46 zend_string *name = zend_string_init(value, strlen(value), 0);
47 zval *zvalue = zend_get_constant_ex(name, NULL, 0);
48
49 zend_string_release(name);
50 return zvalue;
51}
52
53static zval *get_var_value(zend_execute_data *ed, const char *var_name,
54 bool is_param) {
55 zval *zvalue = NULL;
56
57 if (!var_name) {
58 return NULL;
59 }
60 if (*var_name != VARIABLE_TOKEN) {
61 return get_constant(var_name);
62 } else {
63 var_name++;
64 }
65 if (is_param) {
66 zvalue = get_param_var(ed, var_name);
67 if (!zvalue) {
68 return get_local_var(ed, var_name);
69 }
70 return zvalue;
71 }
72 return get_local_var(ed, var_name);
73}
74
75static void *get_entry_hashtable(const HashTable *ht, const char *entry,
76 size_t entry_len) {
77 zval *zvalue = zend_hash_str_find(ht, entry, entry_len);
78
79 if (!zvalue) {
80 zvalue = zend_hash_index_find(ht, atol(entry));
81 }
82 while (zvalue && (Z_TYPE_P(zvalue) == IS_INDIRECT
83 || Z_TYPE_P(zvalue) == IS_PTR)) {
84 if (Z_TYPE_P(zvalue) == IS_INDIRECT) {
85 zvalue = Z_INDIRECT_P(zvalue);
86 } else {
87 zvalue = Z_PTR_P(zvalue);
88 }
89 }
90 return zvalue;
91}
92
93static zval *get_array_value(zend_execute_data *ed, zval *zvalue,
94 const sp_tree *tree) {
95 zval *idx_value, *ret = NULL;
96 char *idx = NULL;
97
98 idx_value = get_value(ed, tree->idx, false);
99 if (!zvalue || !idx_value) {
100 return NULL;
101 }
102 if (Z_TYPE_P(zvalue) == IS_ARRAY) {
103 idx = sp_convert_to_string(idx_value);
104 ret = get_entry_hashtable(Z_ARRVAL_P(zvalue), idx, strlen(idx));
105 efree(idx);
106 }
107 return ret;
108}
109
110static zval *get_object_property(zend_execute_data *ed, zval *object,
111 const char *property, bool is_param) {
112 char *class_name = object->value.obj->ce->name->val;
113 HashTable *array = Z_OBJPROP_P(object);
114 zval *zvalue = NULL;
115 zval *property_val = get_var_value(ed, property, is_param);
116 size_t len;
117
118 if (property_val) {
119 if (Z_TYPE_P(property_val) != IS_STRING) {
120 return NULL;
121 } else {
122 property = Z_STRVAL_P(property_val);
123 }
124 }
125 zvalue = get_entry_hashtable(array, property, strlen(property));
126 if (!zvalue) {
127 char *protected_property = emalloc(strlen(property) + 4);
128 len = sprintf(protected_property, PROTECTED_PROP_FMT, 0, 0, property);
129 zvalue = get_entry_hashtable(array, protected_property, len);
130 efree(protected_property);
131 }
132 if (!zvalue) {
133 char *private_property = emalloc(strlen(class_name) + 3 + strlen(property));
134 len = sprintf(private_property, PRIVATE_PROP_FMT, 0, class_name, 0, property);
135 zvalue = get_entry_hashtable(array, private_property, len);
136 efree(private_property);
137 }
138 return zvalue;
139}
140
141static zend_class_entry *get_class(const char *value) {
142 zend_string *name;
143 zend_class_entry *ce;
144
145 name = zend_string_init(value, strlen(value), 0);
146 ce = zend_lookup_class(name);
147 zend_string_release(name);
148 return ce;
149}
150
151static zval *get_unknown_type(const char *restrict value, zval *zvalue,
152 zend_class_entry *ce, zend_execute_data *ed,
153 const sp_tree *tree, bool is_param) {
154 if (ce) {
155 zvalue = get_entry_hashtable(&ce->constants_table, value, strlen(value));
156 ce = NULL;
157 } else if (zvalue && Z_TYPE_P(zvalue) == IS_OBJECT && value[0]) {
158 zvalue = get_object_property(ed, zvalue, value, is_param);
159 } else if (!tree->next && !zvalue) {
160 if (tree->type == CONSTANT) {
161 zvalue = get_constant(value);
162 }
163 if (!zvalue) {
164 zvalue = emalloc(sizeof(zval));
165 zvalue->value.str = zend_string_init(value, strlen(value), 0);
166 zvalue->u1.v.type = IS_STRING;
167 }
168 } else {
169 return NULL;
170 }
171 return zvalue;
172}
173
174zval *get_value(zend_execute_data *ed, const sp_tree *tree,
175 bool is_param) {
176 zval *zvalue = NULL;
177 zend_class_entry *ce = NULL;
178
179 while (tree) {
180 switch (tree->type) {
181 case ARRAY:
182 if (ce) {
183 zvalue = get_entry_hashtable(&ce->constants_table, tree->value,
184 strlen(tree->value));
185 ce = NULL;
186 } else if (!zvalue) {
187 zvalue = get_var_value(ed, tree->value, is_param);
188 } else if (Z_TYPE_P(zvalue) == IS_OBJECT) {
189 zvalue = get_object_property(ed, zvalue, tree->value, is_param);
190 }
191 zvalue = get_array_value(ed, zvalue, tree);
192 break;
193 case VAR:
194 if (zvalue && Z_TYPE_P(zvalue) == IS_OBJECT) {
195 zvalue = get_object_property(ed, zvalue, tree->value, is_param);
196 } else {
197 zvalue = get_var_value(ed, tree->value, is_param);
198 }
199 break;
200 case OBJECT:
201 if (!zvalue) {
202 zvalue = get_var_value(ed, tree->value, is_param);
203 } else if (Z_TYPE_P(zvalue) == IS_OBJECT) {
204 if (0 != strlen(tree->value)) {
205 zvalue = get_object_property(ed, zvalue, tree->value, is_param);
206 }
207 } else {
208 return NULL;
209 }
210 break;
211 case CLASS:
212 ce = get_class(tree->value);
213 zvalue = NULL;
214 break;
215 default:
216 zvalue = get_unknown_type(tree->value, zvalue, ce, ed, tree, is_param);
217 ce = NULL;
218 break;
219 }
220 if (!zvalue && !ce) {
221 return NULL;
222 }
223 tree = tree->next;
224 }
225 return zvalue;
226}