From 40946e984a5c6b775a0e34d86b36a004c6a70204 Mon Sep 17 00:00:00 2001 From: Aaron Jorbin Date: Sun, 3 Nov 2019 22:08:56 +0000 Subject: [PATCH] General: wp_safe_redirect() and wp_redirect() shouldn't allow non-3xx status codes Redirects should use redirect status codes and if you attempt to call wp_safe_redirect or wp_redirect with a non redirect status it can lead to undesired behavior and head scratching. Fixes #44317. Props spenserhale, johnbillion, mjnewman for initial patch. git-svn-id: https://develop.svn.wordpress.org/trunk@46641 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/pluggable.php | 5 ++++ tests/phpunit/tests/pluggable.php | 47 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/wp-includes/pluggable.php b/src/wp-includes/pluggable.php index 47bdafd395..fb44dc35d5 100644 --- a/src/wp-includes/pluggable.php +++ b/src/wp-includes/pluggable.php @@ -1215,6 +1215,7 @@ if ( ! function_exists( 'wp_redirect' ) ) : * * @since 1.5.1 * @since 5.1.0 The `$x_redirect_by` parameter was added. + * @since 5.4.0 On invalid status codes, wp_die() is called. * * @global bool $is_IIS * @@ -1250,6 +1251,10 @@ if ( ! function_exists( 'wp_redirect' ) ) : return false; } + if ( 300 > $status || 399 < $status ) { + wp_die( __( 'HTTP redirect status code must be a redirection code, 3xx.' ) ); + } + $location = wp_sanitize_redirect( $location ); if ( ! $is_IIS && PHP_SAPI != 'cgi-fcgi' ) { diff --git a/tests/phpunit/tests/pluggable.php b/tests/phpunit/tests/pluggable.php index fd97a2dd77..663da4bd3f 100644 --- a/tests/phpunit/tests/pluggable.php +++ b/tests/phpunit/tests/pluggable.php @@ -5,6 +5,53 @@ */ class Tests_Pluggable extends WP_UnitTestCase { + /** + * @dataProvider get_good_status_codes + * + * @ticket 44317 + * @param string $location The path or URL to redirect to. + * @param int $status HTTP response status code to use. + */ + public function test_wp_redirect_good_status_code( $location, $status ) { + $this->assertTrue( wp_redirect( $location, $status ) ); + } + + public function get_good_status_codes() { + return [ + // Expected Statuses + [ '/wp-admin', 301 ], + [ '/wp-admin', 302 ], + [ '/wp-admin', 307 ], + // Outliers that are valid + [ '/wp-admin', 300 ], + [ '/wp-admin', 399 ], + ]; + } + + /** + * @expectedException WPDieException + * @dataProvider get_bad_status_codes + * + * @ticket 44317 + * @param string $location The path or URL to redirect to. + * @param int $status HTTP response status code to use. + */ + public function test_wp_redirect_bad_status_code( $location, $status ) { + wp_redirect( $location, $status ); + } + + public function get_bad_status_codes() { + return [ + // Tests for bad arguments + [ '/wp-admin', 404 ], + [ '/wp-admin', 410 ], + [ '/wp-admin', 500 ], + // Tests for condition. + [ '/wp-admin', 299 ], + [ '/wp-admin', 400 ], + ]; + } + /** * Tests that the signatures of all functions in pluggable.php match their expected signature. *