mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Add libxml_get_external_entity_loader()
Add libxml_get_external_entity_loader(), which returns the currently installed external entity loader, i.e. the value which was passed to libxml_set_external_entity_loader() or null if no loader was installed and the default entity loader will be used. This allows libraries to save and restore the loader, controlling entity expansion without interfering with the rest of the application. Add macro Z_PARAM_FUNC_OR_NULL_WITH_ZVAL(). This allows us to get the zval for a callable parameter without duplicating callable argument parsing. The saved zval keeps the object needed for fcc/fci alive, simplifying memory management. Fixes #76763.
This commit is contained in:
parent
35e2a25d83
commit
11796229f2
3
NEWS
3
NEWS
@ -30,6 +30,9 @@ PHP NEWS
|
||||
. Fixed bug GH-9316 ($http_response_header is wrong for long status line).
|
||||
(cmb, timwolla)
|
||||
|
||||
- XML:
|
||||
. Added libxml_get_external_entity_loader() function. (Tim Starling)
|
||||
|
||||
18 Aug 2022, PHP 8.2.0beta3
|
||||
|
||||
- Core:
|
||||
|
@ -251,6 +251,9 @@ PHP 8.2 UPGRADE NOTES
|
||||
ini_parse_quantity(). The `memory_limit` setting accepts values higher than
|
||||
PHP_INT_MAX, than can not be parsed by ini_parse_quantity().
|
||||
|
||||
- XML:
|
||||
. libxml_get_external_entity_loader()
|
||||
|
||||
========================================
|
||||
7. New Classes and Interfaces
|
||||
========================================
|
||||
|
@ -1538,6 +1538,10 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
|
||||
SEPARATE_ZVAL_NOREF(_arg); \
|
||||
}
|
||||
|
||||
/* get the zval* for a previously parsed argument */
|
||||
#define Z_PARAM_GET_PREV_ZVAL(dest) \
|
||||
zend_parse_arg_zval_deref(_arg, &dest, 0);
|
||||
|
||||
/* old "|" */
|
||||
#define Z_PARAM_OPTIONAL \
|
||||
_optional = 1;
|
||||
@ -1700,6 +1704,10 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
|
||||
#define Z_PARAM_FUNC_OR_NULL(dest_fci, dest_fcc) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0)
|
||||
|
||||
#define Z_PARAM_FUNC_OR_NULL_WITH_ZVAL(dest_fci, dest_fcc, dest_zp) \
|
||||
Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 1, 0) \
|
||||
Z_PARAM_GET_PREV_ZVAL(dest_zp)
|
||||
|
||||
/* old "h" */
|
||||
#define Z_PARAM_ARRAY_HT_EX2(dest, check_null, deref, separate) \
|
||||
Z_PARAM_PROLOGUE(deref, separate); \
|
||||
|
@ -228,23 +228,11 @@ static PHP_GINIT_FUNCTION(libxml)
|
||||
ZVAL_UNDEF(&libxml_globals->stream_context);
|
||||
libxml_globals->error_buffer.s = NULL;
|
||||
libxml_globals->error_list = NULL;
|
||||
ZVAL_UNDEF(&libxml_globals->entity_loader.object);
|
||||
ZVAL_NULL(&libxml_globals->entity_loader.callback);
|
||||
libxml_globals->entity_loader.fci.size = 0;
|
||||
libxml_globals->entity_loader_disabled = 0;
|
||||
}
|
||||
|
||||
static void _php_libxml_destroy_fci(zend_fcall_info *fci, zval *object)
|
||||
{
|
||||
if (fci->size > 0) {
|
||||
zval_ptr_dtor(&fci->function_name);
|
||||
fci->size = 0;
|
||||
}
|
||||
if (!Z_ISUNDEF_P(object)) {
|
||||
zval_ptr_dtor(object);
|
||||
ZVAL_UNDEF(object);
|
||||
}
|
||||
}
|
||||
|
||||
/* Channel libxml file io layer through the PHP streams subsystem.
|
||||
* This allows use of ftps:// and https:// urls */
|
||||
|
||||
@ -851,7 +839,9 @@ static PHP_RINIT_FUNCTION(libxml)
|
||||
|
||||
static PHP_RSHUTDOWN_FUNCTION(libxml)
|
||||
{
|
||||
_php_libxml_destroy_fci(&LIBXML(entity_loader).fci, &LIBXML(entity_loader).object);
|
||||
LIBXML(entity_loader).fci.size = 0;
|
||||
zval_ptr_dtor_nogc(&LIBXML(entity_loader).callback);
|
||||
ZVAL_NULL(&LIBXML(entity_loader).callback);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
@ -1071,29 +1061,36 @@ PHP_FUNCTION(libxml_disable_entity_loader)
|
||||
/* {{{ Changes the default external entity loader */
|
||||
PHP_FUNCTION(libxml_set_external_entity_loader)
|
||||
{
|
||||
zval *callback;
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fcc;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_FUNC_OR_NULL(fci, fcc)
|
||||
Z_PARAM_FUNC_OR_NULL_WITH_ZVAL(fci, fcc, callback)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
_php_libxml_destroy_fci(&LIBXML(entity_loader).fci, &LIBXML(entity_loader).object);
|
||||
|
||||
if (ZEND_FCI_INITIALIZED(fci)) { /* argument not null */
|
||||
LIBXML(entity_loader).fci = fci;
|
||||
Z_ADDREF(fci.function_name);
|
||||
if (fci.object != NULL) {
|
||||
ZVAL_OBJ(&LIBXML(entity_loader).object, fci.object);
|
||||
Z_ADDREF(LIBXML(entity_loader).object);
|
||||
}
|
||||
LIBXML(entity_loader).fcc = fcc;
|
||||
} else {
|
||||
LIBXML(entity_loader).fci.size = 0;
|
||||
}
|
||||
|
||||
if (!Z_ISNULL(LIBXML(entity_loader).callback)) {
|
||||
zval_ptr_dtor_nogc(&LIBXML(entity_loader).callback);
|
||||
}
|
||||
ZVAL_COPY(&LIBXML(entity_loader).callback, callback);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Get the current external entity loader, or null if the default loader is installer. */
|
||||
PHP_FUNCTION(libxml_get_external_entity_loader)
|
||||
{
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
RETURN_COPY(&LIBXML(entity_loader).callback);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Common functions shared by extensions */
|
||||
int php_libxml_xmlCheckUTF8(const unsigned char *s)
|
||||
{
|
||||
|
@ -177,3 +177,5 @@ function libxml_clear_errors(): void {}
|
||||
function libxml_disable_entity_loader(bool $disable = true): bool {}
|
||||
|
||||
function libxml_set_external_entity_loader(?callable $resolver_function): bool {}
|
||||
|
||||
function libxml_get_external_entity_loader(): ?callable {}
|
||||
|
7
ext/libxml/libxml_arginfo.h
generated
7
ext/libxml/libxml_arginfo.h
generated
@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: d0c03ca63f0403ea38a59bde94510715e993b423 */
|
||||
* Stub hash: 8fa6f4fa2f3eb8db944626b5b3d814f5e3ae04a3 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_set_streams_context, 0, 1, IS_VOID, 0)
|
||||
ZEND_ARG_INFO(0, context)
|
||||
@ -26,6 +26,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_set_external_entity_loade
|
||||
ZEND_ARG_TYPE_INFO(0, resolver_function, IS_CALLABLE, 1)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_libxml_get_external_entity_loader, 0, 0, IS_CALLABLE, 1)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
||||
ZEND_FUNCTION(libxml_set_streams_context);
|
||||
ZEND_FUNCTION(libxml_use_internal_errors);
|
||||
@ -34,6 +37,7 @@ ZEND_FUNCTION(libxml_get_errors);
|
||||
ZEND_FUNCTION(libxml_clear_errors);
|
||||
ZEND_FUNCTION(libxml_disable_entity_loader);
|
||||
ZEND_FUNCTION(libxml_set_external_entity_loader);
|
||||
ZEND_FUNCTION(libxml_get_external_entity_loader);
|
||||
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
@ -44,6 +48,7 @@ static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(libxml_clear_errors, arginfo_libxml_clear_errors)
|
||||
ZEND_DEP_FE(libxml_disable_entity_loader, arginfo_libxml_disable_entity_loader)
|
||||
ZEND_FE(libxml_set_external_entity_loader, arginfo_libxml_set_external_entity_loader)
|
||||
ZEND_FE(libxml_get_external_entity_loader, arginfo_libxml_get_external_entity_loader)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
|
@ -43,8 +43,8 @@ ZEND_BEGIN_MODULE_GLOBALS(libxml)
|
||||
smart_str error_buffer;
|
||||
zend_llist *error_list;
|
||||
struct _php_libxml_entity_resolver {
|
||||
zval object;
|
||||
zend_fcall_info fci;
|
||||
zval callback;
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fcc;
|
||||
} entity_loader;
|
||||
bool entity_loader_disabled;
|
||||
|
36
ext/libxml/tests/libxml_get_external_entity_loader.phpt
Normal file
36
ext/libxml/tests/libxml_get_external_entity_loader.phpt
Normal file
@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
libxml_get_external_entity_loader() returns current handler
|
||||
--EXTENSIONS--
|
||||
libxml
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Handler {
|
||||
private $name;
|
||||
|
||||
public function __construct($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function handle($public, $system, $context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return "Handler#{$this->name}";
|
||||
}
|
||||
}
|
||||
|
||||
var_dump(libxml_get_external_entity_loader());
|
||||
libxml_set_external_entity_loader([new Handler('A'), 'handle']);
|
||||
print libxml_get_external_entity_loader()[0] . "\n";
|
||||
libxml_set_external_entity_loader([new Handler('B'), 'handle']);
|
||||
print libxml_get_external_entity_loader()[0] . "\n";
|
||||
libxml_set_external_entity_loader(null);
|
||||
var_dump(libxml_get_external_entity_loader());
|
||||
|
||||
--EXPECT--
|
||||
NULL
|
||||
Handler#A
|
||||
Handler#B
|
||||
NULL
|
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
libxml_set_external_entity_loader() with non-callable argument
|
||||
--EXTENSIONS--
|
||||
libxml
|
||||
--FILE--
|
||||
<?php
|
||||
try {
|
||||
libxml_set_external_entity_loader('nonexistent_function');
|
||||
} catch (Throwable $e) {
|
||||
echo "Exception: " . $e->getMessage() . "\n";
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Exception: libxml_set_external_entity_loader(): Argument #1 ($resolver_function) must be a valid callback or null, function "nonexistent_function" not found or invalid function name
|
Loading…
Reference in New Issue
Block a user