Skip to content

Add libxml_get_external_entity_loader() #7977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ PHP 8.2 UPGRADE NOTES
- Curl:
. curl_upkeep() (libcurl >= 7.62.0)

- libxml:
. libxml_get_external_entity_loader()

- mysqli:
. mysqli_execute_query()

Expand Down
8 changes: 8 additions & 0 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -1528,6 +1528,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;
Expand Down Expand Up @@ -1690,6 +1694,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); \
Expand Down
43 changes: 20 additions & 23 deletions ext/libxml/libxml.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
{
Expand Down
2 changes: 2 additions & 0 deletions ext/libxml/libxml.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 6 additions & 1 deletion ext/libxml/libxml_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ext/libxml/php_libxml.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
36 changes: 36 additions & 0 deletions ext/libxml/tests/libxml_get_external_entity_loader.phpt
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions ext/libxml/tests/libxml_set_external_entity_loader_error2.phpt
Original file line number Diff line number Diff line change
@@ -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