Skip to content

Commit

Permalink
Move sanitization functions related functionality to dedicated `Sanit…
Browse files Browse the repository at this point in the history
…izingFunctionsTrait` (#2259)

Move sanitization functions related functionality to dedicated `SanitizingFunctionsTrait`

The sanitization function lists are only used by a small set of sniffs, so are better placed in a dedicated trait.

The choice for a `trait` over a `class` is due to the `public` properties allowing for adding additional functions to the lists.

Moving both the base function lists + the `public` properties to the same trait will allow us to encapsulate all the functionality related to the use of these lists in one place.

The `$sanitizingFunctions` and the `$unslashingSanitizingFunctions` property, containing the base lists, have also been made `private`.

Checking whether or not something is a sanitization function should now be done by calling the `SanitizingFunctionsTrait::is_sanitizing_function()` or the `SanitizingFunctionsTrait::is_sanitizing_and_unslashing_function()` method.

Related to #1465
  • Loading branch information
jrfnl authored Jun 23, 2023
1 parent f2b6305 commit 0340cfc
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 186 deletions.
238 changes: 238 additions & 0 deletions WordPress/Helpers/SanitizingFunctionsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
<?php
/**
* WordPress Coding Standard.
*
* @package WPCS\WordPressCodingStandards
* @link https://github.com/WordPress/WordPress-Coding-Standards
* @license https://opensource.org/licenses/MIT MIT
*/

namespace WordPressCS\WordPress\Helpers;

use WordPressCS\WordPress\Helpers\RulesetPropertyHelper;

/**
* Helper functions and function lists for checking whether a sanitizing function is being used.
*
* Any sniff class which incorporates this trait will automatically support the
* following `public` properties which can be changed from within a custom ruleset:
* - `customSanitizingFunctions`.
* - `customUnslashingSanitizingFunctions`
*
* @package WPCS\WordPressCodingStandards
* @since 3.0.0 The properties in this trait were previously contained partially in the
* `WordPressCS\WordPress\Sniff` class and partially in the `NonceVerificationSniff`
* and the `ValidatedSanitizedInputSniff` classes and have been moved here.
*/
trait SanitizingFunctionsTrait {

/**
* Custom list of functions that sanitize the values passed to them.
*
* @since 0.5.0
* @since 3.0.0 Moved from the NonceVerification and the ValidatedSanitizedInput sniff classes to this trait.
*
* @var string[]
*/
public $customSanitizingFunctions = array();

/**
* Custom sanitizing functions that implicitly unslash the values passed to them.
*
* @since 0.5.0
* @since 3.0.0 Moved from the NonceVerification and the ValidatedSanitizedInput sniff classes to this trait.
*
* @var string[]
*/
public $customUnslashingSanitizingFunctions = array();

/**
* Functions that sanitize values.
*
* This list is complementary to the `$unslashingSanitizingFunctions`
* list.
* Sanitizing functions should be added to this list if they do *not*
* implicitly 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.
* @since 3.0.0 - Moved from the Sniff class to this trait.
* - Visibility changed from protected to private.
*
* @var array<string, bool>
*/
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<string, bool>
*/
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<string, string[]>
*/
private $addedCustomSanitizingFunctions = array(
'sanitize' => array(),
'unslashsanitize' => array(),
);

/**
* Combined list of WP/PHP native and custom sanitizing functions.
*
* @since 3.0.0
*
* @var array<string, bool>
*/
private $allSanitizingFunctions = array();

/**
* Combined list of WP/PHP native and custom sanitizing and unslashing functions.
*
* @since 3.0.0
*
* @var array<string, bool>
*/
private $allUnslashingSanitizingFunctions = array();

/**
* Retrieve a list of all known sanitizing functions.
*
* @since 3.0.0
*
* @var array<string, bool>
*/
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<string, bool>
*/
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 ] );
}
}
89 changes: 6 additions & 83 deletions WordPress/Sniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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.
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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;
}

Expand Down
Loading

0 comments on commit 0340cfc

Please sign in to comment.