1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include "php_snuffleupagus.h"
ZEND_API zend_op_array* (*orig_zend_compile_file)(zend_file_handle* file_handle,
int type) = NULL;
#if PHP_VERSION_ID >= 80000
ZEND_API zend_op_array* (*orig_zend_compile_string)(
zend_string* source_string, const char* filename) = NULL;
#else
ZEND_API zend_op_array* (*orig_zend_compile_string)(zval* source_string,
char* filename) = NULL;
#endif
static void modify_opcode(zend_op_array* opline) {
if (NULL != opline) {
for (size_t i = 0; i < opline->last; i++) {
zend_op* orig_opline = &(opline->opcodes[i]);
if (orig_opline->opcode == ZEND_IS_EQUAL) {
orig_opline->opcode = ZEND_IS_IDENTICAL;
zend_vm_set_opcode_handler(orig_opline);
} else if (orig_opline->opcode == ZEND_IS_NOT_EQUAL) {
orig_opline->opcode = ZEND_IS_NOT_IDENTICAL;
zend_vm_set_opcode_handler(orig_opline);
}
}
}
}
#if PHP_VERSION_ID >= 80000
ZEND_API zend_op_array* sp_compile_string(zend_string* source_string,
const char* filename) {
#else
ZEND_API zend_op_array* sp_compile_string(zval* source_string, char* filename) {
#endif
zend_op_array* opline = orig_zend_compile_string(source_string, filename);
modify_opcode(opline);
return opline;
}
ZEND_API zend_op_array* sp_compile_file(zend_file_handle* file_handle,
int type) {
zend_op_array* opline = orig_zend_compile_file(file_handle, type);
modify_opcode(opline);
return opline;
}
static void array_handler(INTERNAL_FUNCTION_PARAMETERS, const char* name,
size_t size, zif_handler orig_handler,
const char* spec) {
zif_handler handler;
zval func_name;
zval params[3];
zval *value, *array = NULL;
zend_bool strict = 0;
uint32_t nb_params = ZEND_NUM_ARGS();
zend_parse_parameters(nb_params, spec, &value, &array, &strict);
ZVAL_COPY(¶ms[0], value);
ZVAL_BOOL(¶ms[2], 1); // we want to always have strict mode enabled
if (array) {
ZVAL_COPY(¶ms[1], array);
// Lie about the number of parameters,
// since we are always passing strict = 1
nb_params = 3;
} else {
ZVAL_NULL(¶ms[1]);
}
ZVAL_STRING(&func_name, name);
handler = zend_hash_str_find_ptr(SNUFFLEUPAGUS_G(sp_internal_functions_hook),
name, size);
zend_internal_function* func =
zend_hash_str_find_ptr(CG(function_table), name, size);
func->handler = handler;
call_user_function(CG(function_table), NULL, &func_name, return_value,
nb_params, params);
func->handler = orig_handler;
}
PHP_FUNCTION(sp_in_array) {
array_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, "in_array",
sizeof("in_array") - 1, PHP_FN(sp_in_array), "zz|b");
}
PHP_FUNCTION(sp_array_search) {
array_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, "array_search",
sizeof("array_search") - 1, PHP_FN(sp_array_search), "zz|b");
}
PHP_FUNCTION(sp_array_keys) {
array_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, "array_keys",
sizeof("array_keys") - 1, PHP_FN(sp_array_keys), "z|zb");
}
void hook_sloppy() {
TSRMLS_FETCH();
if (NULL == orig_zend_compile_file) {
orig_zend_compile_file = zend_compile_file;
zend_compile_file = sp_compile_file;
}
if (NULL == orig_zend_compile_string) {
orig_zend_compile_string = zend_compile_string;
zend_compile_string = sp_compile_string;
}
HOOK_FUNCTION("in_array", sp_internal_functions_hook, PHP_FN(sp_in_array));
HOOK_FUNCTION("array_search", sp_internal_functions_hook,
PHP_FN(sp_array_search));
HOOK_FUNCTION("array_keys", sp_internal_functions_hook,
PHP_FN(sp_array_keys));
}
|