Skip to content

Commit

Permalink
Do not implicitly fall back to spl_autoload() if no autoloader is reg…
Browse files Browse the repository at this point in the history
…istered on PHP 7 (#2822)

* Do not implicitly fall back to spl_autoload() if no autoloader is registered on PHP 7

This could lead to accidental inclusion of files, breaking __autoload() and possibly including the wrong file.

Signed-off-by: Bob Weinand <bob.weinand@datadoghq.com>
  • Loading branch information
bwoebi authored Aug 30, 2024
1 parent 0d5bf6a commit d03ef3f
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 1 deletion.
54 changes: 53 additions & 1 deletion ext/autoload_php_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,61 @@ static inline bool dd_legacy_autoload_wrapper(INTERNAL_FUNCTION_PARAMETERS) {

zend_string *lower = zend_string_tolower(class_name);
bool found = dd_perform_autoload(class_name, lower) != NULL;

if (found) {
zend_string_release(lower);
return true;
}

bool autoloading = EG(in_autoload) && zend_hash_exists(EG(in_autoload), lower);
zend_string_release(lower);

return found;
// check whether we're actually autoloading
if (autoloading) {
if (dd_has_registered_spl_autoloader) {
return false;
}

zend_function *func =
#if PHP_VERSION_ID >= 70300
zend_fetch_function(ZSTR_KNOWN(ZEND_STR_MAGIC_AUTOLOAD))
#else
zend_hash_str_find_ptr(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1)
#endif
;
if (func) {
zval ret;
zend_fcall_info fcall_info;
zend_fcall_info_cache fcall_cache;

fcall_info.size = sizeof(fcall_info);
ZVAL_STR(&fcall_info.function_name, func->common.function_name);
fcall_info.retval = &ret;
fcall_info.param_count = 1;
fcall_info.params = EX_VAR_NUM(0);
fcall_info.object = NULL;
fcall_info.no_separation = 1;
#if PHP_VERSION_ID < 70100
fcall_info.symbol_table = NULL;
#endif

#if PHP_VERSION_ID < 70300
fcall_cache.initialized = 1;
#endif
fcall_cache.function_handler = func;
fcall_cache.calling_scope = NULL;
fcall_cache.called_scope = NULL;
fcall_cache.object = NULL;

zend_call_function(&fcall_info, &fcall_cache);
zval_ptr_dtor(&ret);
}

// skip original implementation if there's no spl autoloader registered
return true;
}

return false;
}

static ZEND_NAMED_FUNCTION(dd_wrap_autoload_register_fn) {
Expand Down
1 change: 1 addition & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ The default value for datadog.log_backtrace is now set to true, meaning that on
- Implement fallback for when memfd is not available on Linux Datadog/libdatadog#591
- Use the Windows User ID as sidecar identifier instead of the Session ID Datadog/libdatadog#558
- Fix error check in trampoline.c Datadog/libdatadog#569
- Do not implicitly fall back to spl_autoload() if no autoloader is registered on PHP 7 #2822
### Internal
- Send x-datadog-test-session-token metric and send metrics to request-replayer #2802
Expand Down
17 changes: 17 additions & 0 deletions tests/ext/autoload-php-files/default_spl_autoloader.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Execute the default spl_autoload implementation if spl_autoload_register() is called without args
--INI--
datadog.trace.sources_path="{PWD}/.."
--FILE--
<?php

spl_autoload_register();

var_dump(class_exists('splautoload'));

echo "Request start" . PHP_EOL;

?>
--EXPECT--
bool(true)
Request start
23 changes: 23 additions & 0 deletions tests/ext/autoload-php-files/legacy_autoloader.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
--TEST--
Execute __autoload() if present
--SKIPIF--
<?php if (PHP_VERSION_ID >= 80000) die("skip: __autoload was removed in PHP 8") ?>
--INI--
error_reporting=8191
datadog.trace.sources_path="{PWD}/.."
--FILE--
<?php

function __autoload($class) {
print "Autoload $class attempted!\n";
}

var_dump(class_exists('splautoload'));

echo "Request start" . PHP_EOL;

?>
--EXPECT--
Autoload splautoload attempted!
bool(false)
Request start
15 changes: 15 additions & 0 deletions tests/ext/autoload-php-files/skip_default_autoloader.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
Do not execute the default spl_autoload implementation if no autoloader is specified
--INI--
datadog.trace.sources_path="{PWD}/.."
--FILE--
<?php

var_dump(class_exists('splautoload'));

echo "Request start" . PHP_EOL;

?>
--EXPECT--
bool(false)
Request start
5 changes: 5 additions & 0 deletions tests/ext/autoload-php-files/splautoload.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

class splautoload {
var $foo = "Autoloaded!";
}

0 comments on commit d03ef3f

Please sign in to comment.