diff --git a/src/wp-includes/shortcodes.php b/src/wp-includes/shortcodes.php index 10b3e19a2e..6657ef3b26 100644 --- a/src/wp-includes/shortcodes.php +++ b/src/wp-includes/shortcodes.php @@ -88,6 +88,19 @@ $shortcode_tags = array(); */ function add_shortcode($tag, $func) { global $shortcode_tags; + + if ( '' == trim( $tag ) ) { + $message = __( 'Invalid shortcode name. Empty name given.' ); + _doing_it_wrong( __FUNCTION__, $message, '4.4.0' ); + return; + } + + if ( 0 !== preg_match( '@[<>&/\[\]\x00-\x20]@', $tag ) ) { + $message = sprintf( __( 'Invalid shortcode name: %s Do not use spaces or reserved chars: & / < > [ ]' ), $tag ); + _doing_it_wrong( __FUNCTION__, $message, '4.4.0' ); + return; + } + $shortcode_tags[ $tag ] = $func; } diff --git a/tests/phpunit/tests/shortcode.php b/tests/phpunit/tests/shortcode.php index bde37f8df8..680dee3441 100644 --- a/tests/phpunit/tests/shortcode.php +++ b/tests/phpunit/tests/shortcode.php @@ -539,4 +539,81 @@ EOF; $this->assertTrue( has_shortcode( $content_nested, 'gallery' ) ); remove_shortcode( 'foo' ); } + + /** + * Make sure invalid shortcode names are not allowed. + * + * @dataProvider data_registration_bad + * @expectedIncorrectUsage add_shortcode + */ + function test_registration_bad( $input, $expected ) { + return $this->sub_registration( $input, $expected ); + } + + /** + * Make sure valid shortcode names are allowed. + * + * @dataProvider data_registration_good + */ + function test_registration_good( $input, $expected ) { + return $this->sub_registration( $input, $expected ); + } + + function sub_registration( $input, $expected ) { + add_shortcode( $input, '' ); + $actual = shortcode_exists( $input ); + $test = $this->assertEquals( $expected, $actual ); + if ( $actual ) remove_shortcode( $input ); + return $test; + } + + function data_registration_bad() { + return array( + array( + '', + false, + ), + array( + '[shortcode]', + false, + ), + array( + 'bad/', + false, + ), + array( + '/bad', + false, + ), + array( + 'bad space', + false, + ), + array( + '&', + false, + ), + array( + '', + false, + ), + ); + } + + function data_registration_good() { + return array( + array( + 'good!', + true, + ), + array( + 'plain', + true, + ), + array( + 'unreserved!#$%()*+,-.;?@^_{|}~chars', + true, + ), + ); + } }