diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 65fe00abf8..c5a1f53f7a 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -5496,27 +5496,24 @@ function sanitize_trackback_urls( $to_ping ) { } /** - * Add slashes to a string or array of strings. + * Add slashes to a string or array of strings, in a recursive manner. * * This should be used when preparing data for core API that expects slashed data. * This should not be used to escape data going directly into an SQL query. * * @since 3.6.0 + * @since 5.5.0 Leave a non-string value untouched. * * @param string|array $value String or array of strings to slash. * @return string|array Slashed $value */ function wp_slash( $value ) { if ( is_array( $value ) ) { - foreach ( $value as $k => $v ) { - if ( is_array( $v ) ) { - $value[ $k ] = wp_slash( $v ); - } else { - $value[ $k ] = addslashes( $v ); - } - } - } else { - $value = addslashes( $value ); + $value = array_map( 'wp_slash', $value ); + } + + if ( is_string( $value ) ) { + return addslashes( $value ); } return $value; diff --git a/tests/phpunit/tests/formatting/StripSlashesDeep.php b/tests/phpunit/tests/formatting/StripSlashesDeep.php index aaebf3be55..b27f6422e7 100644 --- a/tests/phpunit/tests/formatting/StripSlashesDeep.php +++ b/tests/phpunit/tests/formatting/StripSlashesDeep.php @@ -2,6 +2,7 @@ /** * @group formatting + * @group slashes */ class Tests_Formatting_StripSlashesDeep extends WP_UnitTestCase { /** diff --git a/tests/phpunit/tests/formatting/WPSlash.php b/tests/phpunit/tests/formatting/WPSlash.php new file mode 100644 index 0000000000..bfe6759535 --- /dev/null +++ b/tests/phpunit/tests/formatting/WPSlash.php @@ -0,0 +1,103 @@ +assertSame( $expected, wp_slash( $value ) ); + } + + /** + * Data provider for test_wp_slash(). + * + * @return array { + * @type array { + * @type mixed $value The value passed to wp_slash(). + * @type string $expected The expected output of wp_slash(). + * } + * } + */ + public function data_wp_slash() { + return array( + array( 123, 123 ), + array( 123.4, 123.4 ), + array( true, true ), + array( false, false ), + array( + array( + 'hello', + null, + '"string"', + 125.41, + ), + array( + 'hello', + null, + '\"string\"', + 125.41, + ), + ), + array( "first level 'string'", "first level \'string\'" ), + ); + } + + /** + * @ticket 24106 + */ + function test_adds_slashes() { + $old = "I can't see, isn't that it?"; + $new = "I can\'t see, isn\'t that it?"; + $this->assertEquals( $new, wp_slash( $old ) ); + $this->assertEquals( "I can\\\\\'t see, isn\\\\\'t that it?", wp_slash( $new ) ); + $this->assertEquals( array( 'a' => $new ), wp_slash( array( 'a' => $old ) ) ); // Keyed array + $this->assertEquals( array( $new ), wp_slash( array( $old ) ) ); // Non-keyed + } + + /** + * @ticket 24106 + */ + function test_preserves_original_datatype() { + + $this->assertEquals( true, wp_slash( true ) ); + $this->assertEquals( false, wp_slash( false ) ); + $this->assertEquals( 4, wp_slash( 4 ) ); + $this->assertEquals( 'foo', wp_slash( 'foo' ) ); + $arr = array( + 'a' => true, + 'b' => false, + 'c' => 4, + 'd' => 'foo', + ); + $arr['e'] = $arr; // Add a sub-array + $this->assertEquals( $arr, wp_slash( $arr ) ); // Keyed array + $this->assertEquals( array_values( $arr ), wp_slash( array_values( $arr ) ) ); // Non-keyed + + $obj = new stdClass; + foreach ( $arr as $k => $v ) { + $obj->$k = $v; + } + $this->assertEquals( $obj, wp_slash( $obj ) ); + } + + /** + * @ticket 24106 + */ + function test_add_even_more_slashes() { + $old = 'single\\slash double\\\\slash triple\\\\\\slash'; + $new = 'single\\\\slash double\\\\\\\\slash triple\\\\\\\\\\\\slash'; + $this->assertEquals( $new, wp_slash( $old ) ); + $this->assertEquals( array( 'a' => $new ), wp_slash( array( 'a' => $old ) ) ); // Keyed array + $this->assertEquals( array( $new ), wp_slash( array( $old ) ) ); // Non-keyed + } + +}