diff --git a/WordPress/Helpers/SanitizingFunctionsTrait.php b/WordPress/Helpers/SanitizingFunctionsTrait.php new file mode 100644 index 0000000000..f51d3f4e09 --- /dev/null +++ b/WordPress/Helpers/SanitizingFunctionsTrait.php @@ -0,0 +1,238 @@ + + */ + private $sanitizingFunctions = array( + '_wp_handle_upload' => true, + 'esc_url_raw' => true, + 'filter_input' => true, + 'filter_var' => true, + 'hash_equals' => true, + 'is_email' => true, + 'number_format' => true, + 'sanitize_bookmark_field' => true, + 'sanitize_bookmark' => true, + 'sanitize_email' => true, + 'sanitize_file_name' => true, + 'sanitize_hex_color_no_hash' => true, + 'sanitize_hex_color' => true, + 'sanitize_html_class' => true, + 'sanitize_meta' => true, + 'sanitize_mime_type' => true, + 'sanitize_option' => true, + 'sanitize_sql_orderby' => true, + 'sanitize_term_field' => true, + 'sanitize_term' => true, + 'sanitize_text_field' => true, + 'sanitize_textarea_field' => true, + 'sanitize_title_for_query' => true, + 'sanitize_title_with_dashes' => true, + 'sanitize_title' => true, + 'sanitize_user_field' => true, + 'sanitize_user' => true, + 'validate_file' => true, + 'wp_handle_sideload' => true, + 'wp_handle_upload' => true, + 'wp_kses_allowed_html' => true, + 'wp_kses_data' => true, + 'wp_kses_post' => true, + 'wp_kses' => true, + 'wp_parse_id_list' => true, + 'wp_redirect' => true, + 'wp_safe_redirect' => true, + 'wp_sanitize_redirect' => true, + 'wp_strip_all_tags' => true, + ); + + /** + * Sanitizing functions that implicitly unslash the data passed to them. + * + * This list is complementary to the `$sanitizingFunctions` list. + * Sanitizing functions should be added to this list if they also + * implicitely unslash data and to the `$sanitizingFunctions` list + * if they don't. + * + * @since 0.5.0 + * @since 0.11.0 Changed from public static to protected non-static. + * @since 3.0.0 - Moved from the Sniff class to this trait. + * - Visibility changed from protected to private. + * + * @var array + */ + private $unslashingSanitizingFunctions = array( + 'absint' => true, + 'boolval' => true, + 'count' => true, + 'doubleval' => true, + 'floatval' => true, + 'intval' => true, + 'sanitize_key' => true, + 'sizeof' => true, + ); + + /** + * Cache of previously added custom functions. + * + * Prevents having to do the same merges over and over again. + * + * @since 0.4.0 + * @since 0.11.0 - Changed from public static to protected non-static. + * - Changed the format from simple bool to array. + * @since 3.0.0 - Moved from the NonceVerification and the ValidatedSanitizedInput sniff classes to this class. + * - Visibility changed from protected to private. + * + * @var array + */ + private $addedCustomSanitizingFunctions = array( + 'sanitize' => array(), + 'unslashsanitize' => array(), + ); + + /** + * Combined list of WP/PHP native and custom sanitizing functions. + * + * @since 3.0.0 + * + * @var array + */ + private $allSanitizingFunctions = array(); + + /** + * Combined list of WP/PHP native and custom sanitizing and unslashing functions. + * + * @since 3.0.0 + * + * @var array + */ + private $allUnslashingSanitizingFunctions = array(); + + /** + * Retrieve a list of all known sanitizing functions. + * + * @since 3.0.0 + * + * @var array + */ + public function get_sanitizing_functions() { + if ( array() === $this->allSanitizingFunctions + || $this->customSanitizingFunctions !== $this->addedCustomSanitizingFunctions['sanitize'] + ) { + $this->allSanitizingFunctions = RulesetPropertyHelper::merge_custom_array( + $this->customSanitizingFunctions, + $this->sanitizingFunctions + ); + + $this->addedCustomSanitizingFunctions['sanitize'] = $this->customSanitizingFunctions; + } + + return $this->allSanitizingFunctions; + } + + /** + * Retrieve a list of all known sanitizing and unslashing functions. + * + * @since 3.0.0 + * + * @var array + */ + public function get_sanitizing_and_unslashing_functions() { + if ( array() === $this->allUnslashingSanitizingFunctions + || $this->customUnslashingSanitizingFunctions !== $this->addedCustomSanitizingFunctions['unslashsanitize'] + ) { + $this->allUnslashingSanitizingFunctions = RulesetPropertyHelper::merge_custom_array( + $this->customUnslashingSanitizingFunctions, + $this->unslashingSanitizingFunctions + ); + + $this->addedCustomSanitizingFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; + } + + return $this->allUnslashingSanitizingFunctions; + } + + /** + * Check if a particular function is regarded as a sanitizing function. + * + * @since 3.0.0 + * + * @param string $functionName The name of the function to check. + * + * @return bool + */ + public function is_sanitizing_function( $functionName ) { + return isset( $this->get_sanitizing_functions()[ $functionName ] ); + } + + /** + * Check if a particular function is regarded as a sanitizing and unslashing function. + * + * @since 3.0.0 + * + * @param string $functionName The name of the function to check. + * + * @return bool + */ + public function is_sanitizing_and_unslashing_function( $functionName ) { + return isset( $this->get_sanitizing_and_unslashing_functions()[ $functionName ] ); + } +} diff --git a/WordPress/Sniff.php b/WordPress/Sniff.php index 2634cf5375..c1ba74c385 100644 --- a/WordPress/Sniff.php +++ b/WordPress/Sniff.php @@ -16,6 +16,7 @@ use PHPCSUtils\Utils\TextStrings; use WordPressCS\WordPress\Helpers\ArrayWalkingFunctionsHelper; use WordPressCS\WordPress\Helpers\ContextHelper; +use WordPressCS\WordPress\Helpers\SanitizingFunctionsTrait; use WordPressCS\WordPress\Helpers\VariableHelper; /** @@ -39,85 +40,7 @@ */ abstract class Sniff implements PHPCS_Sniff { - /** - * Functions that sanitize values. - * - * This list is complementary to the `$unslashingSanitizingFunctions` - * list. - * Sanitizing functions should be added to this list if they do *not* - * implicitely unslash data and to the `$unslashingsanitizingFunctions` - * list if they do. - * - * @since 0.5.0 - * @since 0.11.0 Changed from public static to protected non-static. - * - * @var array - */ - protected $sanitizingFunctions = array( - '_wp_handle_upload' => true, - 'esc_url_raw' => true, - 'filter_input' => true, - 'filter_var' => true, - 'hash_equals' => true, - 'is_email' => true, - 'number_format' => true, - 'sanitize_bookmark_field' => true, - 'sanitize_bookmark' => true, - 'sanitize_email' => true, - 'sanitize_file_name' => true, - 'sanitize_hex_color_no_hash' => true, - 'sanitize_hex_color' => true, - 'sanitize_html_class' => true, - 'sanitize_meta' => true, - 'sanitize_mime_type' => true, - 'sanitize_option' => true, - 'sanitize_sql_orderby' => true, - 'sanitize_term_field' => true, - 'sanitize_term' => true, - 'sanitize_text_field' => true, - 'sanitize_textarea_field' => true, - 'sanitize_title_for_query' => true, - 'sanitize_title_with_dashes' => true, - 'sanitize_title' => true, - 'sanitize_user_field' => true, - 'sanitize_user' => true, - 'validate_file' => true, - 'wp_handle_sideload' => true, - 'wp_handle_upload' => true, - 'wp_kses_allowed_html' => true, - 'wp_kses_data' => true, - 'wp_kses_post' => true, - 'wp_kses' => true, - 'wp_parse_id_list' => true, - 'wp_redirect' => true, - 'wp_safe_redirect' => true, - 'wp_sanitize_redirect' => true, - 'wp_strip_all_tags' => true, - ); - - /** - * Sanitizing functions that implicitly unslash the data passed to them. - * - * This list is complementary to the `$sanitizingFunctions` list. - * Sanitizing functions should be added to this list if they also - * implicitely unslash data and to the `$sanitizingFunctions` list - * if they don't. - * - * @since 0.5.0 - * @since 0.11.0 Changed from public static to protected non-static. - * - * @var array - */ - protected $unslashingSanitizingFunctions = array( - 'absint' => true, - 'boolval' => true, - 'count' => true, - 'doubleval' => true, - 'floatval' => true, - 'intval' => true, - 'sanitize_key' => true, - 'sizeof' => true, - ); + use SanitizingFunctionsTrait; /** * Functions which unslash the data passed to them. @@ -282,8 +205,8 @@ protected function is_sanitized( $stackPtr, $require_unslash = false ) { return true; } - $valid_functions = $this->sanitizingFunctions; - $valid_functions += $this->unslashingSanitizingFunctions; + $valid_functions = $this->get_sanitizing_functions(); + $valid_functions += $this->get_sanitizing_and_unslashing_functions(); $valid_functions += $this->unslashingFunctions; $valid_functions += ArrayWalkingFunctionsHelper::get_array_walking_functions(); @@ -348,12 +271,12 @@ protected function is_sanitized( $stackPtr, $require_unslash = false ) { } // If slashing is required, give an error. - if ( ! $is_unslashed && $require_unslash && ! isset( $this->unslashingSanitizingFunctions[ $functionName ] ) ) { + if ( ! $is_unslashed && $require_unslash && ! $this->is_sanitizing_and_unslashing_function( $functionName ) ) { $this->add_unslash_error( $stackPtr ); } // Check if this is a sanitizing function. - if ( isset( $this->sanitizingFunctions[ $functionName ] ) || isset( $this->unslashingSanitizingFunctions[ $functionName ] ) ) { + if ( $this->is_sanitizing_function( $functionName ) || $this->is_sanitizing_and_unslashing_function( $functionName ) ) { return true; } diff --git a/WordPress/Sniffs/Security/NonceVerificationSniff.php b/WordPress/Sniffs/Security/NonceVerificationSniff.php index f714f46c07..dc511758a7 100644 --- a/WordPress/Sniffs/Security/NonceVerificationSniff.php +++ b/WordPress/Sniffs/Security/NonceVerificationSniff.php @@ -54,24 +54,6 @@ class NonceVerificationSniff extends Sniff { */ public $customNonceVerificationFunctions = array(); - /** - * Custom list of functions that sanitize the values passed to them. - * - * @since 0.11.0 - * - * @var string|string[] - */ - public $customSanitizingFunctions = array(); - - /** - * Custom sanitizing functions that implicitly unslash the values passed to them. - * - * @since 0.11.0 - * - * @var string|string[] - */ - public $customUnslashingSanitizingFunctions = array(); - /** * Cache of previously added custom functions. * @@ -84,9 +66,7 @@ class NonceVerificationSniff extends Sniff { * @var array */ protected $addedCustomFunctions = array( - 'nonce' => array(), - 'sanitize' => array(), - 'unslashsanitize' => array(), + 'nonce' => array(), ); /** @@ -305,23 +285,5 @@ protected function mergeFunctionLists() { $this->addedCustomFunctions['nonce'] = $this->customNonceVerificationFunctions; } - - if ( $this->customSanitizingFunctions !== $this->addedCustomFunctions['sanitize'] ) { - $this->sanitizingFunctions = RulesetPropertyHelper::merge_custom_array( - $this->customSanitizingFunctions, - $this->sanitizingFunctions - ); - - $this->addedCustomFunctions['sanitize'] = $this->customSanitizingFunctions; - } - - if ( $this->customUnslashingSanitizingFunctions !== $this->addedCustomFunctions['unslashsanitize'] ) { - $this->unslashingSanitizingFunctions = RulesetPropertyHelper::merge_custom_array( - $this->customUnslashingSanitizingFunctions, - $this->unslashingSanitizingFunctions - ); - - $this->addedCustomFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; - } } } diff --git a/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php b/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php index 1132f3c278..3e8f8d1831 100644 --- a/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php +++ b/WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php @@ -12,7 +12,6 @@ use PHP_CodeSniffer\Util\Tokens; use PHPCSUtils\Utils\TextStrings; use WordPressCS\WordPress\Helpers\ContextHelper; -use WordPressCS\WordPress\Helpers\RulesetPropertyHelper; use WordPressCS\WordPress\Helpers\VariableHelper; use WordPressCS\WordPress\Sniff; @@ -38,40 +37,6 @@ class ValidatedSanitizedInputSniff extends Sniff { */ public $check_validation_in_scope_only = false; - /** - * Custom list of functions that sanitize the values passed to them. - * - * @since 0.5.0 - * - * @var string|string[] - */ - public $customSanitizingFunctions = array(); - - /** - * Custom sanitizing functions that implicitly unslash the values passed to them. - * - * @since 0.5.0 - * - * @var string|string[] - */ - public $customUnslashingSanitizingFunctions = array(); - - /** - * Cache of previously added custom functions. - * - * Prevents having to do the same merges over and over again. - * - * @since 0.5.0 - * @since 0.11.0 - Changed from static to non-static. - * - Changed the format from simple bool to array. - * - * @var array - */ - protected $addedCustomFunctions = array( - 'sanitize' => array(), - 'unslashsanitize' => array(), - ); - /** * Returns an array of tokens this test wants to listen for. * @@ -192,8 +157,6 @@ function( $embed ) { return; } - $this->mergeFunctionLists(); - // Now look for sanitizing functions. if ( ! $this->is_sanitized( $stackPtr, true ) ) { $this->phpcsFile->addError( @@ -204,31 +167,4 @@ function( $embed ) { ); } } - - /** - * Merge custom functions provided via a custom ruleset with the defaults, if we haven't already. - * - * @since 0.11.0 Split out from the `process()` method. - * - * @return void - */ - protected function mergeFunctionLists() { - if ( $this->customSanitizingFunctions !== $this->addedCustomFunctions['sanitize'] ) { - $this->sanitizingFunctions = RulesetPropertyHelper::merge_custom_array( - $this->customSanitizingFunctions, - $this->sanitizingFunctions - ); - - $this->addedCustomFunctions['sanitize'] = $this->customSanitizingFunctions; - } - - if ( $this->customUnslashingSanitizingFunctions !== $this->addedCustomFunctions['unslashsanitize'] ) { - $this->unslashingSanitizingFunctions = RulesetPropertyHelper::merge_custom_array( - $this->customUnslashingSanitizingFunctions, - $this->unslashingSanitizingFunctions - ); - - $this->addedCustomFunctions['unslashsanitize'] = $this->customUnslashingSanitizingFunctions; - } - } } diff --git a/WordPress/Tests/Security/ValidatedSanitizedInputUnitTest.php b/WordPress/Tests/Security/ValidatedSanitizedInputUnitTest.php index 9c3b516009..1844d56279 100644 --- a/WordPress/Tests/Security/ValidatedSanitizedInputUnitTest.php +++ b/WordPress/Tests/Security/ValidatedSanitizedInputUnitTest.php @@ -21,6 +21,7 @@ * @since 1.0.0 This sniff has been moved from the `VIP` category to the `Security` category. * * @covers \WordPressCS\WordPress\Helpers\ArrayWalkingFunctionsHelper + * @covers \WordPressCS\WordPress\Helpers\SanitizingFunctionsTrait * @covers \WordPressCS\WordPress\Helpers\VariableHelper * @covers \WordPressCS\WordPress\Sniffs\Security\ValidatedSanitizedInputSniff */