Skip to content

Commit 3dbe602

Browse files
authored
Merge pull request #1682 from WordPress-Coding-Standards/feature/validatedsanitizedinput-improve-array-comparison-handling
ValidatedSanitizedInput: treat array-value comparison functions same as other comparisons
2 parents 5f56dbb + 0934e18 commit 3dbe602

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

WordPress/Sniff.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ abstract class Sniff implements PHPCS_Sniff {
256256
'filter_input' => true,
257257
'filter_var' => true,
258258
'hash_equals' => true,
259-
'in_array' => true,
260259
'is_email' => true,
261260
'number_format' => true,
262261
'sanitize_bookmark_field' => true,
@@ -380,6 +379,22 @@ abstract class Sniff implements PHPCS_Sniff {
380379
'map_deep' => 2,
381380
);
382381

382+
/**
383+
* Array functions to compare a $needle to a predefined set of values.
384+
*
385+
* If the value is set to an integer, the function needs to have at least that
386+
* many parameters for it to be considered as a comparison.
387+
*
388+
* @since 2.1.0
389+
*
390+
* @var array <string function name> => <true|int>
391+
*/
392+
protected $arrayCompareFunctions = array(
393+
'in_array' => true,
394+
'array_search' => true,
395+
'array_keys' => 2,
396+
);
397+
383398
/**
384399
* Functions that format strings.
385400
*
@@ -2273,6 +2288,34 @@ protected function is_comparison( $stackPtr ) {
22732288
return false;
22742289
}
22752290

2291+
/**
2292+
* Check if a token is inside of an array-value comparison function.
2293+
*
2294+
* @since 2.1.0
2295+
*
2296+
* @param int $stackPtr The index of the token in the stack.
2297+
*
2298+
* @return bool Whether the token is (part of) a parameter to an
2299+
* array-value comparison function.
2300+
*/
2301+
protected function is_in_array_comparison( $stackPtr ) {
2302+
$function_ptr = $this->is_in_function_call( $stackPtr, $this->arrayCompareFunctions, true, true );
2303+
if ( false === $function_ptr ) {
2304+
return false;
2305+
}
2306+
2307+
$function_name = $this->tokens[ $function_ptr ]['content'];
2308+
if ( true === $this->arrayCompareFunctions[ $function_name ] ) {
2309+
return true;
2310+
}
2311+
2312+
if ( $this->get_function_call_parameter_count( $function_ptr ) >= $this->arrayCompareFunctions[ $function_name ] ) {
2313+
return true;
2314+
}
2315+
2316+
return false;
2317+
}
2318+
22762319
/**
22772320
* Check what type of 'use' statement a token is part of.
22782321
*

WordPress/Sniffs/Security/ValidatedSanitizedInputSniff.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ function ( $symbol ) {
155155
return;
156156
}
157157

158+
// If this is a comparison using the array comparison functions, sanitization isn't needed.
159+
if ( $this->is_in_array_comparison( $stackPtr ) ) {
160+
return;
161+
}
162+
158163
$this->mergeFunctionLists();
159164

160165
// Now look for sanitizing functions.

WordPress/Tests/Security/ValidatedSanitizedInputUnitTest.inc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,16 @@ function test_additional_array_walking_functions() {
276276
$sane = map_deep( wp_unslash( $_GET['test'] ), 'sanitize_text_field' ); // Ok.
277277
$sane = map_deep( wp_unslash( $_GET['test'] ), 'foo' ); // Bad.
278278
}
279+
280+
function test_recognize_array_comparison_functions_as_such() {
281+
if ( ! isset( $_POST['form_fields'] ) ) {
282+
return;
283+
}
284+
285+
if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], array( 'install', 'update', 'activate' ), true ) ) {} // OK.
286+
if ( isset( $_REQUEST['plugin_state'] ) && in_array( $_REQUEST['plugin_state'], $states, true ) ) {} // OK.
287+
if ( in_array( 'my_form_hidden_field_value', $_POST['form_fields'], true ) ) {} // OK.
288+
if ( array_search( $_POST['form_fields'], 'my_form_hidden_field_value' ) ) {} // OK.
289+
if ( array_keys( $_POST['form_fields'], 'my_form_hidden_field_value', true ) ) {} // OK.
290+
if ( array_keys( $_POST['form_fields'] ) ) {} // Bad x2.
291+
}

WordPress/Tests/Security/ValidatedSanitizedInputUnitTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public function getErrorList() {
6767
257 => 1,
6868
266 => 1,
6969
277 => 1,
70+
290 => 2,
7071
);
7172
}
7273

0 commit comments

Comments
 (0)