Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/wp-includes/formatting.php
Original file line number Diff line number Diff line change
Expand Up @@ -5180,6 +5180,22 @@ function sanitize_option( $option, $value ) {
$value = implode( "\n", $value );
}
break;

case '_site_transient_update_plugins':
case '_site_transient_update_themes':
$value = map_deep(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any risk in touching every field? which field have actual user controlled data, can/should we limit to just those?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could skip some fields. But one problem is that plugins can use the Update URI header field and the update_plugins_{$hostname} filter to basically put whatever they want in any field. So even if there are some fields that will never contain anything but ASCII for plugins hosted in the wordpress.org plugin directory, there may be other third-party plugins which get their update information from some external server, and that information could basically contain anything anywhere.

$value,
static function ( $scalar_value ) use ( &$error ) {
global $wpdb;

$scalar_value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $scalar_value );
if ( is_wp_error( $scalar_value ) ) {
$error = $scalar_value->get_error_message();
}
return $scalar_value;
}
);
break;
}

if ( null !== $error ) {
Expand Down
120 changes: 120 additions & 0 deletions tests/phpunit/tests/option/sanitizeOption.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,126 @@ public function test_emoji_in_blogname_and_description() {
$this->assertSame( $expected, sanitize_option( 'blogdescription', $value ) );
}

/**
* @ticket 64550
*
* @dataProvider data_emoji_in_plugin_updates
*
* @covers ::sanitize_option
*/
public function test_emoji_in_plugin_updates( $updates ) {
global $wpdb;

// Create a deep copy.
$expected = unserialize( serialize( $updates ) );

if ( 'utf8mb4' !== $wpdb->get_col_charset( $wpdb->options, 'option_value' ) ) {
// Iterate through all properties of all plugins and strip out any non-ASCII characters.
foreach ( $expected->response as $plugin ) {
$object_vars = get_object_vars( $plugin );
foreach ( $plugin as $property_name => $property_value ) {
if ( is_string( $property_value ) ) {
$plugin->$property_name = preg_replace( '/[\x80-\xff]/', '', $property_value );
}
}
}
}

$this->assertEquals( $expected, sanitize_option( '_site_transient_update_plugins', $updates ) );
}

public function data_emoji_in_plugin_updates() {
return array(
array(
// This is the sort of plugin data you could expect to see from the wordpress.org plugin directory.
(object) array(
'last_checked' => 1234567890,
'response' => array(
'classic-editor/classic-editor.php' => (object) array(
'id' => 'w.org/plugins/classic-editor',
'slug' => 'classic-editor',
'plugin' => 'classic-editor/classic-editor.php',
'new_version' => '1.7.0',
'url' => 'https://wordpress.org/plugins/classic-editor/',
'package' => 'https://downloads.wordpress.org/plugin/classic-editor.1.7.0.zip',
'icons' => array(
'2x' => 'https://ps.w.org/classic-editor/assets/icon-256x256.png?rev=1998671',
'1x' => 'https://ps.w.org/classic-editor/assets/icon-128x128.png?rev=1998671',
),
'banners' => array(
'2x' => 'https://ps.w.org/classic-editor/assets/banner-1544x500.png?rev=1998671',
'1x' => 'https://ps.w.org/classic-editor/assets/banner-772x250.png?rev=1998676',
),
'banners_rtl' => array(),
'requires' => '4.9',
'tested' => '7.0.4',
'requires_php' => '5.2.4',
'requires_plugins' => array(),
),
'classic-widgets/classic-widgets.php' => (object) array(
'id' => 'w.org/plugins/classic-widgets',
'slug' => 'classic-widgets',
'plugin' => 'classic-widgets/classic-widgets.php',
'new_version' => '0.3',
'url' => 'https://wordpress.org/plugins/classic-widgets/',
'package' => 'https://downloads.wordpress.org/plugin/classic-widgets.0.3.zip',
'icons' => array(
'default' => 'https://s.w.org/plugins/geopattern-icon/classic-widgets.svg',
),
'banners' => array(),
'banners_rtl' => array(),
'requires' => '4.9',
'tested' => '6.9.7',
'requires_php' => '5.6',
'requires_plugins' => array(),
'upgrade_notice' => "\xf0\x9f\x98\x88 This plugin does not really have an upgrade notice, but if it did, it would be here.",
),
),
'translations' => array(),
'no_update' => array(),
'checked' => array(
'classic-editor/classic-editor.php' => '1.6.7',
'classic-widgets/classic-widgets.php' => '0.2',
),
),
),

array(
/*
* This plugin data contains non-BMP Unicode data in several different places.
* You would probably never see this from the wordpress.org plugin directory.
* But you might see it for a plugin which gets its updates from elswehere.
*/
(object) array(
'last_checked' => 1234567890,
'response' => array(
'unicode-everywhere-plugin/unicode-everywhere-plugin.php' => (object) array(
'id' => 'w.org/plugins/unicode-everywhere-plugin',
'slug' => 'unicode-everywhere-plugin',
'plugin' => 'unicode-everywhere-plugin/unicode-everywhere-plugin.php',
'new_version' => '0.2',
'url' => "https://example.com/plugins\xf0\x9f\x94\x8c/unicode-everywhere-plugin/",
'package' => "https://example.com/plugins\xf0\x9f\x94\x8c/unicode-everywhere-plugin/unicode-everywhere-plugin.0.2.zip",
'icons' => array(),
'banners' => array(),
'banners_rtl' => array(),
'requires' => '4.9',
'tested' => "6.9.7 \xf0\x9f\x9a\x80",
'requires_php' => '5.6',
'requires_plugins' => array(),
'foobar' => "You probably wouldn't see a property named 'foobar' in a response from wordpress.org, but a third-party plugin might include it. \xf0\x9f\x98\x80",
),
),
'translations' => array(),
'no_update' => array(),
'checked' => array(
'unicode-everywhere-plugin/unicode-everywhere-plugin.php' => '0.1',
),
),
),
);
}

/**
* @dataProvider data_sanitize_option_permalink_structure
*
Expand Down
Loading