1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
29 # include "php_config.h"
34 #include "ext/standard/info.h"
35 #include "zend_constants.h"
36 #include "zend_operators.h"
46 # define PSI_ENGINE "jit"
51 # define PSI_ENGINE "ffi"
54 ZEND_DECLARE_MODULE_GLOBALS(psi
);
56 //#define ZEND_INI_MH(name) int name(zend_ini_entry *entry, zend_string *new_value, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage)
58 static void OnUpdateBlacklist(const char *str
, void (*cb
)(const char*, size_t))
65 end
= strchr(str
, ',');
79 static void psi_blacklist_add_decl(const char *pattern
, size_t len
);
80 static ZEND_INI_MH(OnUpdateBlacklistedDecls
)
82 OnUpdateBlacklist(new_value
->val
, psi_blacklist_add_decl
);
86 static void psi_blacklist_add_var(const char *pattern
, size_t len
);
87 static ZEND_INI_MH(OnUpdateBlacklistedVars
)
89 OnUpdateBlacklist(new_value
->val
, psi_blacklist_add_var
);
93 static void OnDisplayBlacklist(struct psi_plist
*bl
)
98 while (psi_plist_get(bl
, i
++, &item
)) {
105 static ZEND_INI_DISP(OnDisplayBlacklistedDecls
)
107 OnDisplayBlacklist(PSI_G(blacklist
).decls
);
109 static ZEND_INI_DISP(OnDisplayBlacklistedVars
)
111 OnDisplayBlacklist(PSI_G(blacklist
).vars
);
115 STD_PHP_INI_ENTRY("psi.engine", PSI_ENGINE
, PHP_INI_SYSTEM
, OnUpdateString
, engine
, zend_psi_globals
, psi_globals
)
116 STD_PHP_INI_ENTRY("psi.directory", "psi.d", PHP_INI_SYSTEM
, OnUpdateString
, directory
, zend_psi_globals
, psi_globals
)
117 PHP_INI_ENTRY_EX("psi.blacklist.decls", "", PHP_INI_SYSTEM
, OnUpdateBlacklistedDecls
, OnDisplayBlacklistedDecls
)
118 PHP_INI_ENTRY_EX("psi.blacklist.vars", "", PHP_INI_SYSTEM
, OnUpdateBlacklistedVars
, OnDisplayBlacklistedVars
)
121 static zend_object_handlers psi_object_handlers
;
122 static zend_class_entry
*psi_class_entry
;
124 zend_class_entry
*psi_object_get_class_entry()
126 return psi_class_entry
;
129 static void psi_object_free(zend_object
*o
)
131 psi_object
*obj
= PSI_OBJ(NULL
, o
);
135 obj
->dtor(obj
->data
);
139 zend_object_std_dtor(o
);
142 zend_object
*psi_object_init_ex(zend_class_entry
*ce
, void *data
, void (*dtor
)(void *))
147 ce
= psi_class_entry
;
150 o
= ecalloc(1, sizeof(*o
) + zend_object_properties_size(ce
));
155 zend_object_std_init(&o
->std
, ce
);
156 object_properties_init(&o
->std
, ce
);
157 o
->std
.handlers
= &psi_object_handlers
;
161 zend_object
*psi_object_init(zend_class_entry
*ce
)
163 return psi_object_init_ex(ce
, NULL
, NULL
);
166 ZEND_BEGIN_ARG_INFO_EX(ai_psi_dump
, 0, 0, 0)
167 ZEND_ARG_INFO(0, stream
)
169 static PHP_FUNCTION(psi_dump
)
173 struct psi_dump dump
= {.fun
= (psi_dump_cb
) php_stream_printf
};
175 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "|r!", &r
)) {
179 php_stream_from_zval(s
, r
);
182 dump
.ctx
.hn
= php_stream_open_wrapper("php://output", "w", REPORT_ERRORS
, NULL
);
184 psi_context_dump(&dump
, PSI_G(context
));
187 ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate
, 0, 0, 1)
188 ZEND_ARG_INFO(0, file
)
189 ZEND_ARG_INFO(0, flags
)
190 ZEND_ARG_INFO(1, errcnt
)
192 static PHP_FUNCTION(psi_validate
)
195 struct psi_parser_input
*I
;
197 struct psi_data D
= {0};
198 struct psi_validate_scope S
= {0};
203 if (psi_check_env("PSI_DEBUG")) {
208 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "P|lz", &file
, &flags
, &errcnt
)) {
212 if (!psi_parser_init(&P
, psi_error_wrapper
, flags
)) {
215 if (!(I
= psi_parser_open_file(&P
, file
->val
, true))) {
220 psi_parser_parse(&P
, I
);
221 psi_data_ctor(&D
, P
.error
, P
.flags
);
222 psi_validate_scope_ctor(&S
);
225 RETVAL_BOOL(psi_validate(&S
, &D
, PSI_DATA(&P
)));
229 convert_to_long(errcnt
);
230 ZVAL_LONG(errcnt
, P
.errors
);
233 psi_validate_scope_dtor(&S
);
236 psi_parser_input_free(&I
);
239 ZEND_BEGIN_ARG_INFO_EX(ai_psi_validate_string
, 0, 0, 1)
240 ZEND_ARG_INFO(0, string
)
241 ZEND_ARG_INFO(0, flags
)
242 ZEND_ARG_INFO(1, errcnt
)
244 static PHP_FUNCTION(psi_validate_string
)
247 struct psi_parser_input
*I
;
249 struct psi_data D
= {0};
250 struct psi_validate_scope S
= {0};
255 if (psi_check_env("PSI_DEBUG")) {
260 if (SUCCESS
!= zend_parse_parameters(ZEND_NUM_ARGS(), "S|lz", &string
, &flags
, &errcnt
)) {
264 if (!psi_parser_init(&P
, psi_error_wrapper
, flags
)) {
267 if (!(I
= psi_parser_open_string(&P
, string
->val
, string
->len
))) {
272 psi_parser_parse(&P
, I
);
273 psi_data_ctor(&D
, P
.error
, P
.flags
);
274 psi_validate_scope_ctor(&S
);
277 RETVAL_BOOL(psi_validate(&S
, &D
, PSI_DATA(&P
)));
281 convert_to_long(errcnt
);
282 ZVAL_LONG(errcnt
, P
.errors
);
285 psi_validate_scope_dtor(&S
);
288 psi_parser_input_free(&I
);
291 PHP_MINIT_FUNCTION(psi_cpp
);
292 PHP_MINIT_FUNCTION(psi_builtin
);
293 PHP_MINIT_FUNCTION(psi_context
);
294 static PHP_MINIT_FUNCTION(psi
)
296 zend_class_entry ce
= {0};
298 REGISTER_INI_ENTRIES();
300 zend_register_long_constant(ZEND_STRL("PSI_DEBUG"), PSI_DEBUG
, CONST_CS
|CONST_PERSISTENT
, module_number
);
301 zend_register_long_constant(ZEND_STRL("PSI_SILENT"), PSI_SILENT
, CONST_CS
|CONST_PERSISTENT
, module_number
);
303 INIT_NS_CLASS_ENTRY(ce
, "psi", "object", NULL
);
304 psi_class_entry
= zend_register_internal_class_ex(&ce
, NULL
);
305 psi_class_entry
->create_object
= psi_object_init
;
307 memcpy(&psi_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
308 psi_object_handlers
.offset
= XtOffsetOf(psi_object
, std
);
309 psi_object_handlers
.free_obj
= psi_object_free
;
310 psi_object_handlers
.clone_obj
= NULL
;
312 if (SUCCESS
!= PHP_MINIT(psi_builtin
)(type
, module_number
)) {
315 if (SUCCESS
!= PHP_MINIT(psi_cpp
)(type
, module_number
)) {
318 if (SUCCESS
!= PHP_MINIT(psi_context
)(type
, module_number
)) {
325 PHP_MSHUTDOWN_FUNCTION(psi_cpp
);
326 PHP_MSHUTDOWN_FUNCTION(psi_builtin
);
327 PHP_MSHUTDOWN_FUNCTION(psi_context
);
328 static PHP_MSHUTDOWN_FUNCTION(psi
)
330 PHP_MSHUTDOWN(psi_context
)(type
, module_number
);
331 PHP_MSHUTDOWN(psi_cpp
)(type
, module_number
);
332 PHP_MSHUTDOWN(psi_builtin
)(type
, module_number
);
334 UNREGISTER_INI_ENTRIES();
339 #if defined(COMPILE_DL_PSI) && defined(ZTS)
340 static PHP_RINIT_FUNCTION(psi
)
342 ZEND_TSRMLS_CACHE_UPDATE();
347 static PHP_MINFO_FUNCTION(psi
)
349 php_info_print_table_start();
350 php_info_print_table_header(2, "PSI Support", "enabled");
351 php_info_print_table_row(2, "Extension Version", PHP_PSI_VERSION
);
352 php_info_print_table_row(2, "Search Path", PSI_G(search_path
));
353 php_info_print_table_end();
355 php_info_print_table_start();
356 php_info_print_table_header(3, "Used Library", "Compiled", "Linked");
357 php_info_print_table_row(3, "libffi",
358 #ifndef PHP_PSI_LIBFFI_VERSION
359 # define PHP_PSI_LIBFFI_VERSION "unknown"
362 PHP_PSI_LIBFFI_VERSION
, "unknown"
364 "disabled", "disabled"
367 php_info_print_table_row(3, "libjit",
371 "disabled", "disabled"
375 DISPLAY_INI_ENTRIES();
378 static void ptr_free(void *ptr
)
380 free(*(void **) ptr
);
383 static void psi_blacklist_add_decl(const char *pattern
, size_t len
)
385 char *tmp
= strndup(pattern
, len
);
386 struct psi_plist
**decls
= &PSI_G(blacklist
).decls
;
388 *decls
= psi_plist_add(*decls
, &tmp
);
391 static void psi_blacklist_add_var(const char *pattern
, size_t len
)
393 char *tmp
= strndup(pattern
, len
);
394 struct psi_plist
**vars
= &PSI_G(blacklist
).vars
;
396 *vars
= psi_plist_add(*vars
, &tmp
);
399 static PHP_GINIT_FUNCTION(psi
)
402 struct psi_plist
**bl_decls
= &psi_globals
->blacklist
.decls
;
403 struct psi_plist
**bl_vars
= &psi_globals
->blacklist
.vars
;
405 *bl_decls
= psi_plist_init(ptr_free
);
406 *bl_vars
= psi_plist_init(ptr_free
);
408 #define BL_ADD(D, d) \
410 *D = psi_plist_add(*D, &tmp)
411 #define BL_DECL_ADD(d) BL_ADD(bl_decls, d)
412 #define BL_VAR_ADD(d) BL_ADD(bl_vars, d)
414 BL_DECL_ADD("dlsym");
415 BL_DECL_ADD("alloca");
416 BL_DECL_ADD("atexit");
417 BL_DECL_ADD("at_quick_exit");
420 BL_DECL_ADD("_IO_cookie_init");
421 BL_DECL_ADD("bindresvport6");
424 BL_DECL_ADD("*v*printf");
425 BL_DECL_ADD("*v*scanf");
426 BL_DECL_ADD("vsyslog");
428 /* LFS/LFO for 32bit */
429 BL_DECL_ADD("*stat*64");
430 BL_DECL_ADD("*glob*64");
432 BL_DECL_ADD("getumask");
434 /* using hidden structs */
435 BL_VAR_ADD("_IO_2_*");
438 static PHP_GSHUTDOWN_FUNCTION(psi
)
440 psi_plist_free(psi_globals
->blacklist
.decls
);
443 static const zend_function_entry psi_functions
[] = {
444 PHP_FE(psi_dump
, ai_psi_dump
)
445 PHP_FE(psi_validate
, ai_psi_validate
)
446 PHP_FE(psi_validate_string
, ai_psi_validate_string
)
450 static const zend_module_dep psi_deps
[] = {
451 ZEND_MOD_REQUIRED("standard")
455 zend_module_entry psi_module_entry
= {
456 STANDARD_MODULE_HEADER_EX
,
463 #if defined(COMPILE_DL_PSI) && defined(ZTS)
464 PHP_RINIT(psi
), /* Replace with NULL if there's nothing to do at request start */
471 ZEND_MODULE_GLOBALS(psi
),
474 NULL
, /* post-deactivate */
475 STANDARD_MODULE_PROPERTIES_EX
478 #ifdef COMPILE_DL_PSI
480 ZEND_TSRMLS_CACHE_DEFINE();
490 * vim600: noet sw=4 ts=4 fdm=marker
491 * vim<600: noet sw=4 ts=4