• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

krakjoe / uopz / 10227248408

03 Aug 2024 10:17AM UTC coverage: 95.497%. Remained the same
10227248408

push

github

cmb69
CI: run Linjux on PHP master, too

912 of 955 relevant lines covered (95.5%)

4895.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.98
/src/util.c
1
/*
2
  +----------------------------------------------------------------------+
3
  | uopz                                                                 |
4
  +----------------------------------------------------------------------+
5
  | Copyright (c) Joe Watkins 2016-2021                                  |
6
  +----------------------------------------------------------------------+
7
  | This source file is subject to version 3.01 of the PHP license,      |
8
  | that is bundled with this package in the file LICENSE, and is        |
9
  | available through the world-wide-web at the following url:           |
10
  | http://www.php.net/license/3_01.txt                                  |
11
  | If you did not receive a copy of the PHP license and are unable to   |
12
  | obtain it through the world-wide-web, please send a note to          |
13
  | license@php.net so we can mail you a copy immediately.               |
14
  +----------------------------------------------------------------------+
15
  | Author: Joe Watkins <krakjoe@php.net>                                |
16
  +----------------------------------------------------------------------+
17
 */
18

19
#ifndef UOPZ_UTIL
20
#define UOPZ_UTIL
21

22
#include "php.h"
23
#include "uopz.h"
24

25
#include "class.h"
26
#include "function.h"
27
#include "hook.h"
28
#include "return.h"
29
#include "util.h"
30

31
#include <Zend/zend_closures.h>
32

33
ZEND_EXTERN_MODULE_GLOBALS(uopz);
34

35
static zend_internal_function *zend_call_user_func_ptr;
36
static zend_internal_function *zend_call_user_func_array_ptr;
37
static zend_internal_function *uopz_call_user_func_ptr;
38
static zend_internal_function *uopz_call_user_func_array_ptr;
39

40
static inline void uopz_table_dtor(zval *zv) { /* {{{ */
147✔
41
        zend_hash_destroy(Z_PTR_P(zv));
147✔
42
        efree(Z_PTR_P(zv));
147✔
43
} /* }}} */
147✔
44

45
/* {{{ */
46
typedef struct _uopz_magic_t {
47
        const char *name;
48
        size_t                  length;
49
        int                         id;
50
} uopz_magic_t;
51

52
#define UOPZ_MAGIC(name, id) {name, sizeof(name)-1, id}
53
#define UOPZ_MAGIC_END                 {NULL, 0, 0L}
54

55
static const uopz_magic_t umagic[] = {
56
        UOPZ_MAGIC(ZEND_CONSTRUCTOR_FUNC_NAME, 0),
57
        UOPZ_MAGIC(ZEND_DESTRUCTOR_FUNC_NAME, 1),
58
        UOPZ_MAGIC(ZEND_CLONE_FUNC_NAME, 2),
59
        UOPZ_MAGIC(ZEND_GET_FUNC_NAME, 3),
60
        UOPZ_MAGIC(ZEND_SET_FUNC_NAME, 4),
61
        UOPZ_MAGIC(ZEND_UNSET_FUNC_NAME, 5),
62
        UOPZ_MAGIC(ZEND_ISSET_FUNC_NAME, 6),
63
        UOPZ_MAGIC(ZEND_CALL_FUNC_NAME, 7),
64
        UOPZ_MAGIC(ZEND_CALLSTATIC_FUNC_NAME, 8),
65
        UOPZ_MAGIC(ZEND_TOSTRING_FUNC_NAME, 9),
66
        UOPZ_MAGIC("__serialize", 10),
67
        UOPZ_MAGIC("__unserialize", 11),
68
        UOPZ_MAGIC(ZEND_DEBUGINFO_FUNC_NAME, 12),
69
        UOPZ_MAGIC_END
70
};
71

72
void uopz_handle_magic(zend_class_entry *clazz, zend_string *name, zend_function *function) { /* {{{ */
108✔
73
        uopz_magic_t *magic;
36✔
74

75
        for (magic = (uopz_magic_t*) umagic; magic->name; magic++) {
846✔
76
                if (ZSTR_LEN(name) == magic->length &&
810✔
77
                                strncasecmp(ZSTR_VAL(name), magic->name, magic->length) == SUCCESS) {
135✔
78

79
                        switch (magic->id) {
72✔
80
                                case 0: clazz->constructor = function; break;
9✔
81
                                case 1: clazz->destructor = function; break;
9✔
82
                                case 2: clazz->clone = function; break;
9✔
83
                                case 3: clazz->__get = function; break;
9✔
84
                                case 4: clazz->__set = function; break;
9✔
85
                                case 5: clazz->__unset = function; break;
9✔
86
                                case 6: clazz->__isset = function; break;
9✔
87
                                case 7: clazz->__call = function; break;
×
88
                                case 8: clazz->__callstatic = function; break;
×
89
                                case 9: clazz->__tostring = function; break;
9✔
90
                                case 10: clazz->__serialize = function; break;
×
91
                                case 11: clazz->__unserialize = function; break;
×
92
                                case 12: clazz->__debugInfo = function; break;
×
93
                        }
94
                        return;
72✔
95
                }
96
        }
97
} /* }}} */
98

99
zend_function *uopz_find_method(zend_class_entry *ce, zend_string *name) { /* {{{ */
183✔
100
        return uopz_find_function(&ce->function_table, name);
183✔
101
} /* }}} */
102

103
zend_function *uopz_find_function(HashTable *table, zend_string *name) { /* {{{ */
435✔
104
        zend_string *key = zend_string_tolower(name);
435✔
105
        zend_function *ptr = zend_hash_find_ptr(table, key);
435✔
106
        zend_string_release(key);
435✔
107
        return ptr;
435✔
108
} /* }}} */
109

110
zend_bool uopz_is_magic_method(zend_class_entry *clazz, zend_string *function) /* {{{ */
138✔
111
{ 
112
        if (!clazz) {
138✔
113
                return 0;
12✔
114
        }
115

116
        if (zend_string_equals_literal_ci(function, "__construct") ||
120✔
117
                zend_string_equals_literal_ci(function, "__destruct") ||
120✔
118
                zend_string_equals_literal_ci(function, "__clone") ||
120✔
119
                zend_string_equals_literal_ci(function, "__get") ||
120✔
120
                zend_string_equals_literal_ci(function, "__set") ||
120✔
121
                zend_string_equals_literal_ci(function, "__unset") ||
120✔
122
                zend_string_equals_literal_ci(function, "__isset") ||
120✔
123
                zend_string_equals_literal_ci(function, "__call") ||
120✔
124
                zend_string_equals_literal_ci(function, "__callstatic") ||
120✔
125
                zend_string_equals_literal_ci(function, "__tostring") ||
120✔
126
                zend_string_equals_literal_ci(function, "__debuginfo") ||
120✔
127
                zend_string_equals_literal_ci(function, "__serialize") ||
120✔
128
                zend_string_equals_literal_ci(function, "__unserialize") ||
120✔
129
                zend_string_equals_literal_ci(function, "__sleep") ||
120✔
130
                zend_string_equals_literal_ci(function, "__wakeup")) {
120✔
131
                return 1;
×
132
        }
133

134
        return 0;
79✔
135
} /* }}} */
136

137
int uopz_clean_function(zval *zv) { /* {{{ */
1,092,151✔
138
        zend_function *fp = Z_PTR_P(zv);
1,092,151✔
139

140
        if (fp->type == ZEND_USER_FUNCTION && fp->common.fn_flags & ZEND_ACC_UOPZ) {
1,092,151✔
141
                return ZEND_HASH_APPLY_REMOVE;
108✔
142
        }
143

144
        return ZEND_HASH_APPLY_KEEP;
741,476✔
145
} /* }}} */
146

147
int uopz_clean_class(zval *zv) { /* {{{ */
57,517✔
148
        zend_class_entry *ce = Z_PTR_P(zv);
57,517✔
149

150
        if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
57,517✔
151
                return ZEND_HASH_APPLY_KEEP;
48✔
152
        }
153
        
154
        zend_hash_apply(
57,371✔
155
                &ce->function_table, uopz_clean_function);
156
        
157
        return ZEND_HASH_APPLY_KEEP;
57,371✔
158
} /* }}} */
159

160
static inline void uopz_caller_switch(zif_handler *old, zif_handler *new) {
1,496✔
161
        zif_handler *current = old;
1,496✔
162

163
        *old = *new;
1,496✔
164

165
        *new = *current;
1,496✔
166
}
1,196✔
167

168
static void uopz_callers_init(void) { /* {{{ */
449✔
169
         uopz_call_user_func_ptr = zend_hash_str_find_ptr(
898✔
170
                        CG(function_table), "uopz_call_user_func", sizeof("uopz_call_user_func")-1);
449✔
171
         uopz_call_user_func_array_ptr = zend_hash_str_find_ptr(
898✔
172
                        CG(function_table), "uopz_call_user_func_array", sizeof("uopz_call_user_func_array")-1);
449✔
173
        zend_call_user_func_ptr = zend_hash_str_find_ptr(
898✔
174
                        CG(function_table), "call_user_func", sizeof("call_user_func")-1);
449✔
175
        zend_call_user_func_array_ptr = zend_hash_str_find_ptr(
898✔
176
                        CG(function_table), "call_user_func_array", sizeof("call_user_func_array")-1);
449✔
177

178
        uopz_caller_switch(&zend_call_user_func_ptr->handler, &uopz_call_user_func_ptr->handler);
449✔
179
        uopz_caller_switch(&zend_call_user_func_array_ptr->handler, &uopz_call_user_func_array_ptr->handler);
449✔
180
} /* }}} */
449✔
181

182
static void uopz_callers_shutdown(void) { /* {{{ */
449✔
183
        uopz_caller_switch(&uopz_call_user_func_ptr->handler, &zend_call_user_func_ptr->handler);
449✔
184
        uopz_caller_switch(&uopz_call_user_func_array_ptr->handler, &zend_call_user_func_array_ptr->handler);
449✔
185
} /* }}} */
449✔
186

187
#define UOPZ_CALL_HOOKS(variadic) do { \
188
        if (!fcc.function_handler) { \
189
                break; \
190
        } \
191
        \
192
        { \
193
                uopz_hook_t *uhook = uopz_find_hook(fcc.function_handler); \
194
                \
195
                if (uhook && !uhook->busy) { \
196
                        uopz_execute_hook(uhook, execute_data, 1, variadic); \
197
                } \
198
        } \
199
        \
200
        do { \
201
                uopz_return_t *ureturn = uopz_find_return(fcc.function_handler); \
202
                \
203
                if (ureturn) { \
204
                        if (UOPZ_RETURN_IS_EXECUTABLE(ureturn)) { \
205
                                if (UOPZ_RETURN_IS_BUSY(ureturn)) { \
206
                                        break; \
207
                                } \
208
                                \
209
                                uopz_execute_return(ureturn, execute_data, return_value); \
210
                                return; \
211
                        } \
212
                        \
213
                        ZVAL_COPY(return_value, &ureturn->value); \
214
                        return; \
215
                } \
216
        } while (0); \
217
} while (0)
218
/* {{{ proto mixed uopz_call_user_func(callable function, ... args) */
219
PHP_FUNCTION(uopz_call_user_func) {
36✔
220
        zval retval;
12✔
221
        zend_fcall_info fci;
12✔
222
        zend_fcall_info_cache fcc;
12✔
223

224
        ZEND_PARSE_PARAMETERS_START(1, -1)
36✔
225
                Z_PARAM_FUNC(fci, fcc)
48✔
226
                Z_PARAM_VARIADIC_WITH_NAMED(fci.params, fci.param_count, fci.named_params)
36✔
227
        ZEND_PARSE_PARAMETERS_END();
36✔
228

229
        fci.retval = &retval;
36✔
230

231
        UOPZ_CALL_HOOKS(0);
36✔
232

233
        if (zend_call_function(&fci, &fcc) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
18✔
234
                if (Z_ISREF(retval)) {
18✔
235
                        zend_unwrap_reference(&retval);
×
236
                }
237
                ZVAL_COPY_VALUE(return_value, &retval);
18✔
238
        }
239
} /* }}} */
240

241
/* {{{ proto mixed uopz_call_user_func_array(callable function, array args) */
242
PHP_FUNCTION(uopz_call_user_func_array) {
45✔
243
        HashTable *params;
15✔
244
        zval retval;
15✔
245
        zend_fcall_info fci;
15✔
246
        zend_fcall_info_cache fcc;
15✔
247

248
        ZEND_PARSE_PARAMETERS_START(2, 2)
45✔
249
                Z_PARAM_FUNC(fci, fcc)
60✔
250
                Z_PARAM_ARRAY_HT(params)
60✔
251
        ZEND_PARSE_PARAMETERS_END();
45✔
252

253
        fci.named_params = params;
45✔
254
        fci.retval = &retval;
45✔
255

256
        UOPZ_CALL_HOOKS(1);
45✔
257

258
        if (zend_call_function(&fci, &fcc) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
36✔
259
                if (Z_ISREF(retval)) {
36✔
260
                        zend_unwrap_reference(&retval);
×
261
                }
262
                ZVAL_COPY_VALUE(return_value, &retval);
36✔
263
        }
264
} /* }}} */
265

266
void uopz_request_init(void) { /* {{{ */
449✔
267
        UOPZ(copts) = CG(compiler_options);
449✔
268

269
        CG(compiler_options) |=
449✔
270
                                ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION |
271
                                ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION |
272
                                ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS | 
273
                                ZEND_COMPILE_IGNORE_USER_FUNCTIONS | 
274
                                ZEND_COMPILE_GUARDS;
275

276
        zend_hash_init(&UOPZ(returns), 8, NULL, uopz_table_dtor, 0);
449✔
277
        zend_hash_init(&UOPZ(mocks), 8, NULL, uopz_zval_dtor, 0);
449✔
278
        zend_hash_init(&UOPZ(hooks), 8, NULL, uopz_table_dtor, 0);
449✔
279

280
        {
281
                char *report = getenv("UOPZ_REPORT_MEMLEAKS");
449✔
282

283
                PG(report_memleaks) = 
599✔
284
                        (report && report[0] == '1');
449✔
285
        }
286

287
        uopz_callers_init();
449✔
288
} /* }}} */
449✔
289

290
void uopz_request_shutdown(void) { /* {{{ */
449✔
291
        CG(compiler_options) = UOPZ(copts);
449✔
292

293
        zend_hash_apply(CG(class_table),        uopz_clean_class);
449✔
294
        zend_hash_apply(CG(function_table), uopz_clean_function);
449✔
295

296
        zend_hash_destroy(&UOPZ(mocks));
449✔
297
        zend_hash_destroy(&UOPZ(returns));
449✔
298
        zend_hash_destroy(&UOPZ(hooks));
449✔
299

300
        uopz_callers_shutdown();
449✔
301
} /* }}} */
449✔
302

303
#endif        /* UOPZ_UTIL */
304

305
/*
306
 * Local variables:
307
 * tab-width: 4
308
 * c-basic-offset: 4
309
 * End:
310
 * vim600: noet sw=4 ts=4 fdm=marker
311
 * vim<600: noet sw=4 ts=4
312
 */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc