mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-01 05:39:10 +02:00
Merge pull request #10364 from creative-commoners/pulls/4/update-backtrace-filter-methods
ENH Update list of filtered backtrace methods
This commit is contained in:
commit
f63655bd40
43
_config/backtrace.yml
Normal file
43
_config/backtrace.yml
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
Name: framework-backtrace
|
||||
---
|
||||
SilverStripe\Dev\Backtrace:
|
||||
ignore_function_args:
|
||||
- 'mssql_connect'
|
||||
- 'mysql_connect'
|
||||
- 'pg_connect'
|
||||
- ['mysqli', 'mysqli']
|
||||
- ['mysqli', 'real_connect']
|
||||
- ['mysqli', 'select_db']
|
||||
- ['PDO', '__construct']
|
||||
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\GetParameter', buildConfirmationItem]
|
||||
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\Url', buildConfirmationItem]
|
||||
- ['SilverStripe\Control\Middleware\ConfirmationMiddleware\UrlPathStartswith', buildConfirmationItem]
|
||||
- ['SilverStripe\Core\Startup\AbstractConfirmationToken', 'checkToken']
|
||||
- ['SilverStripe\Core\Startup\AbstractConfirmationToken', 'pathForToken']
|
||||
- ['SilverStripe\Core\Startup\AbstractConfirmationToken', 'prepare_tokens']
|
||||
- ['SilverStripe\ORM\DB', 'connect']
|
||||
- ['SilverStripe\ORM\DB', 'createDatabase']
|
||||
- ['SilverStripe\Security\Confirmation\Item', '__construct']
|
||||
- ['SilverStripe\Security\DefaultAdminService', 'isDefaultAdminCredentials']
|
||||
- ['SilverStripe\Security\DefaultAdminService', 'setDefaultAdmin']
|
||||
- ['SilverStripe\Security\Member', 'changePassword']
|
||||
- ['SilverStripe\Security\MemberAuthenticator\ChangePasswordHandler', 'setSessionToken']
|
||||
- ['SilverStripe\Security\MemberAuthenticator\CookieAuthenticationHandler', 'setTokenCookieName']
|
||||
- ['SilverStripe\Security\MemberAuthenticator\CookieAuthenticationHandler', 'setTokenCookieSecure']
|
||||
- ['SilverStripe\Security\MemberAuthenticator\LostPasswordHandler', 'sendEmail']
|
||||
- ['SilverStripe\Security\PasswordEncryptor', 'check']
|
||||
- ['SilverStripe\Security\PasswordEncryptor', 'encrypt']
|
||||
- ['SilverStripe\Security\PasswordEncryptor', 'salt']
|
||||
- ['SilverStripe\Security\PasswordEncryptor_Blowfish', 'encryptA']
|
||||
- ['SilverStripe\Security\PasswordEncryptor_Blowfish', 'encryptX']
|
||||
- ['SilverStripe\Security\PasswordEncryptor_Blowfish', 'encryptY']
|
||||
- ['SilverStripe\Security\PasswordValidator', 'validate']
|
||||
- ['SilverStripe\Security\RememberLoginHash', 'setToken']
|
||||
- ['SilverStripe\Security\Security', 'check_default_admin']
|
||||
- ['SilverStripe\Security\Security', 'encrypt_password']
|
||||
- ['SilverStripe\Security\Security', 'setDefaultAdmin']
|
||||
- ['*', 'checkPassword']
|
||||
- ['*', 'onAfterChangePassword']
|
||||
- ['*', 'onBeforeChangePassword']
|
||||
- ['*', 'updateValidatePassword']
|
@ -13,42 +13,14 @@ class Backtrace
|
||||
use Configurable;
|
||||
|
||||
/**
|
||||
* @var array Replaces all arguments with a '<filtered>' string,
|
||||
* Replaces all arguments with a '<filtered>' string,
|
||||
* mostly for security reasons. Use string values for global functions,
|
||||
* and array notation for class methods.
|
||||
* PHP's debug_backtrace() doesn't allow to inspect the argument names,
|
||||
* so all arguments of the provided functions will be filtered out.
|
||||
* @var array
|
||||
*/
|
||||
private static $ignore_function_args = [
|
||||
'mysql_connect',
|
||||
'mssql_connect',
|
||||
'pg_connect',
|
||||
['PDO', '__construct'],
|
||||
['mysqli', 'mysqli'],
|
||||
['mysqli', 'select_db'],
|
||||
['mysqli', 'real_connect'],
|
||||
['SilverStripe\\ORM\\DB', 'connect'],
|
||||
['SilverStripe\\Security\\Security', 'check_default_admin'],
|
||||
['SilverStripe\\Security\\Security', 'encrypt_password'],
|
||||
['SilverStripe\\Security\\Security', 'setDefaultAdmin'],
|
||||
['SilverStripe\\ORM\\DB', 'createDatabase'],
|
||||
['SilverStripe\\Security\\Member', 'checkPassword'],
|
||||
['SilverStripe\\Security\\Member', 'changePassword'],
|
||||
['SilverStripe\\Security\\MemberAuthenticator\\MemberAuthenticator', 'checkPassword'],
|
||||
['SilverStripe\\Security\\MemberPassword', 'checkPassword'],
|
||||
['SilverStripe\\Security\\PasswordValidator', 'validate'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_PHPHash', 'encrypt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_PHPHash', 'salt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_LegacyPHPHash', 'encrypt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_LegacyPHPHash', 'salt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_MySQLPassword', 'encrypt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_MySQLPassword', 'salt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_MySQLOldPassword', 'encrypt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_MySQLOldPassword', 'salt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_Blowfish', 'encrypt'],
|
||||
['SilverStripe\\Security\\PasswordEncryptor_Blowfish', 'salt'],
|
||||
['*', 'updateValidatePassword'],
|
||||
];
|
||||
private static $ignore_function_args = [];
|
||||
|
||||
/**
|
||||
* Return debug_backtrace() results with functions filtered
|
||||
@ -107,22 +79,23 @@ class Backtrace
|
||||
// Filter out arguments
|
||||
foreach ($bt as $i => $frame) {
|
||||
$match = false;
|
||||
if (!empty($bt[$i]['class'])) {
|
||||
if (!empty($frame['class'])) {
|
||||
foreach ($ignoredArgs as $fnSpec) {
|
||||
if (is_array($fnSpec) &&
|
||||
('*' == $fnSpec[0] || $bt[$i]['class'] == $fnSpec[0]) &&
|
||||
$bt[$i]['function'] == $fnSpec[1]
|
||||
if (is_array($fnSpec)
|
||||
&& self::matchesFilterableClass($frame['class'], $fnSpec[0])
|
||||
&& $frame['function'] == $fnSpec[1]
|
||||
) {
|
||||
$match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (in_array($bt[$i]['function'], $ignoredArgs ?? [])) {
|
||||
if (in_array($frame['function'], $ignoredArgs ?? [])) {
|
||||
$match = true;
|
||||
}
|
||||
}
|
||||
if ($match) {
|
||||
foreach ($bt[$i]['args'] as $j => $arg) {
|
||||
foreach ($frame['args'] as $j => $arg) {
|
||||
$bt[$i]['args'][$j] = '<filtered>';
|
||||
}
|
||||
}
|
||||
@ -229,4 +202,13 @@ class Backtrace
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the filterable class is wildcard, of if the class name is the filterable class, or a subclass of it,
|
||||
* or implements it.
|
||||
*/
|
||||
private static function matchesFilterableClass(string $className, string $filterableClass): bool
|
||||
{
|
||||
return $filterableClass === '*' || $className === $filterableClass || is_subclass_of($className, $filterableClass);
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,13 @@
|
||||
|
||||
namespace SilverStripe\Dev\Tests;
|
||||
|
||||
use ReflectionMethod;
|
||||
use SilverStripe\Core\BaseKernel;
|
||||
use SilverStripe\Core\CoreKernel;
|
||||
use SilverStripe\Core\Kernel;
|
||||
use SilverStripe\Dev\Backtrace;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class BacktraceTest extends SapphireTest
|
||||
{
|
||||
@ -109,4 +114,56 @@ class BacktraceTest extends SapphireTest
|
||||
$this->assertEquals('<filtered>', $filtered[1]['args']['password']);
|
||||
$this->assertEquals('myval', $filtered[2]['args']['myarg']);
|
||||
}
|
||||
|
||||
public function matchesFilterableClassProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'anything',
|
||||
'*',
|
||||
true,
|
||||
'Wildcard counts as a match',
|
||||
],
|
||||
[
|
||||
DataObject::class,
|
||||
BaseKernel::class,
|
||||
false,
|
||||
'No match',
|
||||
],
|
||||
[
|
||||
DataObject::class,
|
||||
DataObject::class,
|
||||
true,
|
||||
'Exact match',
|
||||
],
|
||||
[
|
||||
CoreKernel::class,
|
||||
BaseKernel::class,
|
||||
true,
|
||||
'Subclass counts as a match',
|
||||
],
|
||||
[
|
||||
BaseKernel::class,
|
||||
CoreKernel::class,
|
||||
false,
|
||||
'Superclass does not count as a match',
|
||||
],
|
||||
[
|
||||
CoreKernel::class,
|
||||
Kernel::class,
|
||||
true,
|
||||
'Implements interface counts as a match',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider matchesFilterableClassProvider
|
||||
*/
|
||||
public function testMatchesFilterableClass(string $className, string $filterableClass, bool $expected, string $message): void
|
||||
{
|
||||
$reflectionMethod = new ReflectionMethod(Backtrace::class . '::matchesFilterableClass');
|
||||
$reflectionMethod->setAccessible(true);
|
||||
$this->assertSame($expected, $reflectionMethod->invoke(null, $className, $filterableClass), $message);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user