From 1b92a6db072b1774f81285c022d57356458e0ba0 Mon Sep 17 00:00:00 2001 From: Sergey Biryukov Date: Tue, 30 Nov 2021 21:00:32 +0000 Subject: [PATCH] Options, Meta APIs: Improve error handling in `sanitize_option()`. To prevent potential false negatives, set `$error` to `null` initially, so we can better tell if it was ever changed during the sanitization and be able to better react if an empty string is added to it. Additionally, and mainly for the sake of the Settings API at this point, add error messages to some `WP_Error` objects returned from `wpdb` methods that were previously causing the issues here. Follow-up to [32791]. Props iCaleb, audrasjb, hellofromTonya, SergeyBiryukov. Fixes #53986. git-svn-id: https://develop.svn.wordpress.org/trunk@52294 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/formatting.php | 13 ++++++++++--- src/wp-includes/wp-db.php | 4 ++-- tests/phpunit/tests/option/sanitize-option.php | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/wp-includes/formatting.php b/src/wp-includes/formatting.php index 576b3c657a..5a135f0f0e 100644 --- a/src/wp-includes/formatting.php +++ b/src/wp-includes/formatting.php @@ -4711,7 +4711,7 @@ function sanitize_option( $option, $value ) { global $wpdb; $original_value = $value; - $error = ''; + $error = null; switch ( $option ) { case 'admin_email': @@ -4919,7 +4919,9 @@ function sanitize_option( $option, $value ) { $value = str_replace( 'http://', '', $value ); } - if ( 'permalink_structure' === $option && '' !== $value && ! preg_match( '/%[^\/%]+%/', $value ) ) { + if ( 'permalink_structure' === $option && null === $error + && '' !== $value && ! preg_match( '/%[^\/%]+%/', $value ) + ) { $error = sprintf( /* translators: %s: Documentation URL. */ __( 'A structure tag is required when using custom permalinks. Learn more' ), @@ -4948,7 +4950,12 @@ function sanitize_option( $option, $value ) { break; } - if ( ! empty( $error ) ) { + if ( null !== $error ) { + if ( '' === $error && is_wp_error( $value ) ) { + /* translators: 1: Option name, 2: Error code. */ + $error = sprintf( __( 'Could not sanitize the %1$s option. Error code: %2$s' ), $option, $value->get_error_code() ); + } + $value = get_option( $option ); if ( function_exists( 'add_settings_error' ) ) { add_settings_error( $option, "invalid_{$option}", $error ); diff --git a/src/wp-includes/wp-db.php b/src/wp-includes/wp-db.php index 0eaede8811..fa071c426d 100644 --- a/src/wp-includes/wp-db.php +++ b/src/wp-includes/wp-db.php @@ -2885,7 +2885,7 @@ class wpdb { $table = '`' . implode( '`.`', $table_parts ) . '`'; $results = $this->get_results( "SHOW FULL COLUMNS FROM $table" ); if ( ! $results ) { - return new WP_Error( 'wpdb_get_table_charset_failure' ); + return new WP_Error( 'wpdb_get_table_charset_failure', __( 'Could not retrieve table charset.' ) ); } foreach ( $results as $column ) { @@ -3327,7 +3327,7 @@ class wpdb { $this->check_current_query = false; $row = $this->get_row( 'SELECT ' . implode( ', ', $sql ), ARRAY_A ); if ( ! $row ) { - return new WP_Error( 'wpdb_strip_invalid_text_failure' ); + return new WP_Error( 'wpdb_strip_invalid_text_failure', __( 'Could not strip invalid text.' ) ); } foreach ( array_keys( $data ) as $column ) { diff --git a/tests/phpunit/tests/option/sanitize-option.php b/tests/phpunit/tests/option/sanitize-option.php index 3a1c22215d..c9e56470c7 100644 --- a/tests/phpunit/tests/option/sanitize-option.php +++ b/tests/phpunit/tests/option/sanitize-option.php @@ -155,6 +155,7 @@ class Tests_Sanitize_Option extends WP_UnitTestCase { array( '/%postname%/', '/%postname%/', true ), array( '/%year%/%monthnum%/%day%/%postname%/', '/%year%/%monthnum%/%day%/%postname%/', true ), array( '/%year/%postname%/', '/%year/%postname%/', true ), + array( new WP_Error( 'wpdb_get_table_charset_failure' ), false, false ), // ticket 53986 ); }