summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.m42
-rw-r--r--ex_imp.c307
-rw-r--r--php_suhosin7.h2
-rw-r--r--suhosin7.c2
4 files changed, 312 insertions, 1 deletions
diff --git a/config.m4 b/config.m4
index dddea2a..63b7d18 100644
--- a/config.m4
+++ b/config.m4
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE(suhosin7, whether to enable suhosin support,
5[ --enable-suhosin7 Enable suhosin support]) 5[ --enable-suhosin7 Enable suhosin support])
6 6
7if test "$PHP_SUHOSIN7" != "no"; then 7if test "$PHP_SUHOSIN7" != "no"; then
8 PHP_NEW_EXTENSION(suhosin7, suhosin7.c ifilter.c memory_limit.c aes.c treat_data.c log.c execute.c execute_ih.c execute_rnd.c crypt.c cookiecrypt.c header.c session.c, $ext_shared,, [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) 8 PHP_NEW_EXTENSION(suhosin7, suhosin7.c ifilter.c memory_limit.c aes.c treat_data.c log.c execute.c execute_ih.c execute_rnd.c crypt.c cookiecrypt.c header.c session.c ex_imp.c, $ext_shared,, [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1])
9 PHP_ADD_EXTENSION_DEP(suhosin7, hash) 9 PHP_ADD_EXTENSION_DEP(suhosin7, hash)
10 echo "===== WARNING ============================================" 10 echo "===== WARNING ============================================"
11 echo " Suhosin7 for PHP 7 is in alpha stage at the moment and" 11 echo " Suhosin7 for PHP 7 is in alpha stage at the moment and"
diff --git a/ex_imp.c b/ex_imp.c
new file mode 100644
index 0000000..5531076
--- /dev/null
+++ b/ex_imp.c
@@ -0,0 +1,307 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2016 SektionEins GmbH |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Authors: Stefan Esser <sesser@sektioneins.de> |
17 | Ben Fuhrmannek <ben.fuhrmannek@sektioneins.de> |
18 +----------------------------------------------------------------------+
19*/
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "php.h"
26#include "php_ini.h"
27#include "ext/standard/php_smart_string.h"
28#include "ext/standard/php_var.h"
29#include "php_suhosin7.h"
30
31
32#define EXTR_OVERWRITE 0
33#define EXTR_SKIP 1
34#define EXTR_PREFIX_SAME 2
35#define EXTR_PREFIX_ALL 3
36#define EXTR_PREFIX_INVALID 4
37#define EXTR_PREFIX_IF_EXISTS 5
38#define EXTR_IF_EXISTS 6
39
40#define EXTR_REFS 0x100
41
42
43static zend_always_inline int php_valid_var_name(char *var_name, size_t var_name_len) /* {{{ */
44{
45#if 1
46 /* first 256 bits for first character, and second 256 bits for the next */
47 static const uint32_t charset[16] = {
48 /* 31 0 63 32 95 64 127 96 */
49 0x00000000, 0x00000000, 0x87fffffe, 0x07fffffe,
50 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
51 /* 31 0 63 32 95 64 127 96 */
52 0x00000000, 0x03ff0000, 0x87fffffe, 0x07fffffe,
53 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
54 };
55#endif
56 size_t i;
57 uint32_t ch;
58
59 if (UNEXPECTED(!var_name_len)) {
60 return 0;
61 }
62
63 /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */
64 ch = (uint32_t)((unsigned char *)var_name)[0];
65#if 1
66 if (UNEXPECTED(!(charset[ch >> 5] & (1 << (ch & 0x1f))))) {
67#else
68 if (var_name[0] != '_' &&
69 (ch < 65 /* A */ || /* Z */ ch > 90) &&
70 (ch < 97 /* a */ || /* z */ ch > 122) &&
71 (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255)
72 ) {
73#endif
74 return 0;
75 }
76
77 /* And these as the rest: [a-zA-Z0-9_\x7f-\xff] */
78 if (var_name_len > 1) {
79 i = 1;
80 do {
81 ch = (uint32_t)((unsigned char *)var_name)[i];
82#if 1
83 if (UNEXPECTED(!(charset[8 + (ch >> 5)] & (1 << (ch & 0x1f))))) {
84#else
85 if (var_name[i] != '_' &&
86 (ch < 48 /* 0 */ || /* 9 */ ch > 57) &&
87 (ch < 65 /* A */ || /* Z */ ch > 90) &&
88 (ch < 97 /* a */ || /* z */ ch > 122) &&
89 (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255)
90 ) {
91#endif
92 return 0;
93 }
94 } while (++i < var_name_len);
95 }
96
97 if (suhosin_is_protected_varname(var_name, var_name_len)) {
98 return 0;
99 }
100
101 return 1;
102}
103
104/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]])
105 Imports variables into symbol table from an array */
106PHP_FUNCTION(suhosin_extract)
107{
108 zval *var_array_param, *prefix = NULL;
109 zend_long extract_type = EXTR_OVERWRITE;
110 zval *entry;
111 zend_string *var_name;
112 zend_ulong num_key;
113 int var_exists, count = 0;
114 int extract_refs = 0;
115 zend_array *symbol_table;
116 zval var_array;
117
118#ifndef FAST_ZPP
119 if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array_param, &extract_type, &prefix) == FAILURE) {
120 return;
121 }
122#else
123 ZEND_PARSE_PARAMETERS_START(1, 3)
124 Z_PARAM_ARRAY(var_array_param)
125 Z_PARAM_OPTIONAL
126 Z_PARAM_LONG(extract_type)
127 Z_PARAM_ZVAL_EX(prefix, 0, 1)
128 ZEND_PARSE_PARAMETERS_END();
129#endif
130
131 extract_refs = (extract_type & EXTR_REFS);
132 if (extract_refs) {
133 SEPARATE_ZVAL(var_array_param);
134 }
135 extract_type &= 0xff;
136
137 if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
138 php_error_docref(NULL, E_WARNING, "Invalid extract type");
139 return;
140 }
141
142 if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
143 php_error_docref(NULL, E_WARNING, "specified extract type requires the prefix parameter");
144 return;
145 }
146
147 if (prefix) {
148 convert_to_string(prefix);
149 if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
150 php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier");
151 return;
152 }
153 }
154
155 symbol_table = zend_rebuild_symbol_table();
156#if 0
157 if (!symbol_table) {
158 php_error_docref(NULL, E_WARNING, "failed to build symbol table");
159 return;
160 }
161#endif
162
163 /* The array might be stored in a local variable that will be overwritten. To avoid losing the
164 * reference in that case we work on a copy. */
165 ZVAL_COPY(&var_array, var_array_param);
166
167 ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(var_array), num_key, var_name, entry) {
168 zval final_name;
169
170 ZVAL_NULL(&final_name);
171 var_exists = 0;
172
173 if (var_name) {
174 var_exists = zend_hash_exists_ind(symbol_table, var_name);
175 } else if (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID) {
176 zend_string *str = zend_long_to_str(num_key);
177 php_prefix_varname(&final_name, prefix, ZSTR_VAL(str), ZSTR_LEN(str), 1);
178 zend_string_release(str);
179 } else {
180 continue;
181 }
182
183 switch (extract_type) {
184 case EXTR_IF_EXISTS:
185 if (!var_exists) break;
186 /* break omitted intentionally */
187
188 case EXTR_OVERWRITE:
189 /* GLOBALS protection */
190 if (var_exists && ZSTR_LEN(var_name) == sizeof("GLOBALS")-1 && !strcmp(ZSTR_VAL(var_name), "GLOBALS")) {
191 break;
192 }
193 if (var_exists && ZSTR_LEN(var_name) == sizeof("this")-1 && !strcmp(ZSTR_VAL(var_name), "this") && EG(scope) && ZSTR_LEN(EG(scope)->name) != 0) {
194 break;
195 }
196 ZVAL_STR_COPY(&final_name, var_name);
197 break;
198
199 case EXTR_PREFIX_IF_EXISTS:
200 if (var_exists) {
201 php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
202 }
203 break;
204
205 case EXTR_PREFIX_SAME:
206 if (!var_exists && ZSTR_LEN(var_name) != 0) {
207 ZVAL_STR_COPY(&final_name, var_name);
208 }
209 /* break omitted intentionally */
210
211 case EXTR_PREFIX_ALL:
212 if (Z_TYPE(final_name) == IS_NULL && ZSTR_LEN(var_name) != 0) {
213 php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
214 }
215 break;
216
217 case EXTR_PREFIX_INVALID:
218 if (Z_TYPE(final_name) == IS_NULL) {
219 if (!php_valid_var_name(ZSTR_VAL(var_name), ZSTR_LEN(var_name))) {
220 php_prefix_varname(&final_name, prefix, ZSTR_VAL(var_name), ZSTR_LEN(var_name), 1);
221 } else {
222 ZVAL_STR_COPY(&final_name, var_name);
223 }
224 }
225 break;
226
227 default:
228 if (!var_exists) {
229 ZVAL_STR_COPY(&final_name, var_name);
230 }
231 break;
232 }
233
234 if (Z_TYPE(final_name) == IS_STRING && php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
235 zval *orig_var;
236 if (extract_refs) {
237
238 ZVAL_MAKE_REF(entry);
239 Z_ADDREF_P(entry);
240
241 if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
242 if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
243 orig_var = Z_INDIRECT_P(orig_var);
244 }
245 zval_ptr_dtor(orig_var);
246 ZVAL_COPY_VALUE(orig_var, entry);
247 } else {
248 zend_hash_update(symbol_table, Z_STR(final_name), entry);
249 }
250 } else {
251 ZVAL_DEREF(entry);
252 if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
253 if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
254 if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
255 orig_var = Z_INDIRECT_P(orig_var);
256 }
257 ZVAL_DEREF(orig_var);
258 zval_ptr_dtor(orig_var);
259 ZVAL_COPY_VALUE(orig_var, entry);
260 } else {
261 zend_hash_update(symbol_table, Z_STR(final_name), entry);
262 }
263 }
264 count++;
265 }
266 zval_dtor(&final_name);
267 } ZEND_HASH_FOREACH_END();
268 zval_ptr_dtor(&var_array);
269
270 RETURN_LONG(count);
271}
272/* }}} */
273
274
275
276
277ZEND_BEGIN_ARG_INFO_EX(suhosin_arginfo_extract, 0, 0, 1)
278 ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arg) /* ARRAY_INFO(0, arg, 0) */
279 ZEND_ARG_INFO(0, extract_type)
280 ZEND_ARG_INFO(0, prefix)
281ZEND_END_ARG_INFO()
282
283
284/* {{{ suhosin_ex_imp_functions[]
285 */
286zend_function_entry suhosin_ex_imp_functions[] = {
287 PHP_NAMED_FE(extract, PHP_FN(suhosin_extract), suhosin_arginfo_extract)
288 {NULL, NULL, NULL}
289};
290/* }}} */
291
292void suhosin_hook_ex_imp()
293{
294 /* replace the extract and import_request_variables functions */
295 zend_hash_str_del(CG(function_table), ZEND_STRL("extract"));
296 zend_register_functions(NULL, suhosin_ex_imp_functions, NULL, MODULE_PERSISTENT);
297}
298
299
300/*
301 * Local variables:
302 * tab-width: 4
303 * c-basic-offset: 4
304 * End:
305 * vim600: noet sw=4 ts=4 fdm=marker
306 * vim<600: noet sw=4 ts=4
307 */
diff --git a/php_suhosin7.h b/php_suhosin7.h
index 685de8d..8a58ef6 100644
--- a/php_suhosin7.h
+++ b/php_suhosin7.h
@@ -389,6 +389,8 @@ void suhosin_hook_header_handler();
389void suhosin_unhook_header_handler(); 389void suhosin_unhook_header_handler();
390void suhosin_hook_execute(); 390void suhosin_hook_execute();
391// void suhosin_hook_sha256(); 391// void suhosin_hook_sha256();
392void suhosin_hook_ex_imp();
393
392#ifdef HAVE_PHP_SESSION 394#ifdef HAVE_PHP_SESSION
393void suhosin_hook_session(); 395void suhosin_hook_session();
394#endif 396#endif
diff --git a/suhosin7.c b/suhosin7.c
index 6d6655a..b91de37 100644
--- a/suhosin7.c
+++ b/suhosin7.c
@@ -520,6 +520,8 @@ PHP_MINIT_FUNCTION(suhosin7)
520 suhosin_hook_execute(); 520 suhosin_hook_execute();
521 suhosin_hook_memory_limit(); 521 suhosin_hook_memory_limit();
522 // suhosin_hook_sha256(); 522 // suhosin_hook_sha256();
523 suhosin_hook_ex_imp();
524
523#ifdef HAVE_PHP_SESSION 525#ifdef HAVE_PHP_SESSION
524 suhosin_hook_session(); 526 suhosin_hook_session();
525#endif 527#endif