From 10be03b2d72edce32b5def82a65a16f1c89e9cab Mon Sep 17 00:00:00 2001 From: Michael Adams Date: Mon, 27 Apr 2015 18:30:15 +0000 Subject: [PATCH] 3.9: - WPDB: Sanity check that any strings being stored in the DB are not too long to store correctly. - When upgrading, remove any suspicious comments. Built from https://develop.svn.wordpress.org/branches/3.9@32316 git-svn-id: http://core.svn.wordpress.org/branches/3.9@32287 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- readme.html | 2 +- wp-admin/about.php | 6 +- wp-admin/includes/upgrade.php | 31 +++++++++ wp-includes/version.php | 2 +- wp-includes/wp-db.php | 114 ++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 3 deletions(-) diff --git a/readme.html b/readme.html index ddd2a00fcd..5dda64d786 100644 --- a/readme.html +++ b/readme.html @@ -9,7 +9,7 @@

WordPress -
Version 3.9.5 +
Version 3.9.6

Semantic Personal Publishing Platform

diff --git a/wp-admin/about.php b/wp-admin/about.php index ff20cd7504..91e8de34ff 100644 --- a/wp-admin/about.php +++ b/wp-admin/about.php @@ -39,7 +39,11 @@ include( ABSPATH . 'wp-admin/admin-header.php' );
-

+

+

Version %1$s addressed a security issue.', + 'Version %1$s addressed some security issues.', 1 ), '3.9.6' ); ?> + the release notes.' ), 'http://codex.wordpress.org/Version_3.9.6' ); ?> +

Version %1$s addressed %2$s bug.', 'Version %1$s addressed %2$s bugs.', 1 ), '3.9.5', number_format_i18n( 1 ) ); ?> the release notes.' ), 'https://codex.wordpress.org/Version_3.9.5' ); ?> diff --git a/wp-admin/includes/upgrade.php b/wp-admin/includes/upgrade.php index 4a853fed0b..2f4f53144a 100644 --- a/wp-admin/includes/upgrade.php +++ b/wp-admin/includes/upgrade.php @@ -430,6 +430,9 @@ function upgrade_all() { if ( $wp_current_db_version < 26691 ) upgrade_380(); + if ( $wp_current_db_version < 27917 ) + upgrade_396(); + maybe_disable_link_manager(); maybe_disable_automattic_widgets(); @@ -1270,6 +1273,34 @@ function upgrade_380() { deactivate_plugins( array( 'mp6/mp6.php' ), true ); } } + +/** + * Execute changes made in WordPress 3.9.6. + * + * @since 3.9.6 + */ +function upgrade_396() { + global $wp_current_db_version, $wpdb; + + if ( $wp_current_db_version < 27917 ) { + $content_length = $wpdb->get_col_length( $wpdb->comments, 'comment_content' ); + if ( ! $content_length ) { + $content_length = 65535; + } + + $comments = $wpdb->get_results( + "SELECT comment_ID FROM $wpdb->comments + WHERE comment_date_gmt > '2015-04-26' + AND CHAR_LENGTH( comment_content ) >= $content_length + AND ( comment_content LIKE '%<%' OR comment_content LIKE '%>%' )" + ); + + foreach ( $comments as $comment ) { + wp_delete_comment( $comment->comment_ID, true ); + } + } +} + /** * Execute network level changes * diff --git a/wp-includes/version.php b/wp-includes/version.php index 5b742f029a..4c32c333d4 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -11,7 +11,7 @@ $wp_version = '3.9.6'; * * @global int $wp_db_version */ -$wp_db_version = 27916; +$wp_db_version = 27917; /** * Holds the TinyMCE version diff --git a/wp-includes/wp-db.php b/wp-includes/wp-db.php index 57032ed237..b7f803bdca 100644 --- a/wp-includes/wp-db.php +++ b/wp-includes/wp-db.php @@ -1893,11 +1893,20 @@ class wpdb { */ protected function process_fields( $table, $data, $format ) { $data = $this->process_field_formats( $data, $format ); + if ( false === $data ) { + return false; + } + $data = $this->process_field_charsets( $data, $table ); if ( false === $data ) { return false; } + $data = $this->process_field_lengths( $data, $table ); + if ( false === $data ) { + return false; + } + $converted_data = $this->strip_invalid_text( $data ); if ( $data !== $converted_data ) { @@ -1978,6 +1987,40 @@ class wpdb { return $data; } + /** + * For string fields, record the maximum string length that field can safely save. + * + * @since 4.2.1 + * @access protected + * + * @param array $data As it comes from the wpdb::process_field_charsets() method. + * @param string $table Table name. + * @return array|False The same array as $data with additional 'length' keys, or false if + * any of the values were too long for their corresponding field. + */ + protected function process_field_lengths( $data, $table ) { + foreach ( $data as $field => $value ) { + if ( '%d' === $value['format'] || '%f' === $value['format'] ) { + // We can skip this field if we know it isn't a string. + // This checks %d/%f versus ! %s because it's sprintf() could take more. + $value['length'] = false; + } else { + $value['length'] = $this->get_col_length( $table, $field ); + if ( is_wp_error( $value['length'] ) ) { + return false; + } + } + + if ( false !== $value['length'] && strlen( $value['value'] ) > $value['length'] ) { + return false; + } + + $data[ $field ] = $value; + } + + return $data; + } + /** * Retrieve one variable from the database. * @@ -2298,6 +2341,77 @@ class wpdb { return $charset; } + /** + * Retrieve the maximum string length allowed in a given column. + * + * @since 4.2.1 + * @access public + * + * @param string $table Table name. + * @param string $column Column name. + * @return mixed Max column length as an int. False if the column has no + * length. WP_Error object if there was an error. + */ + public function get_col_length( $table, $column ) { + $tablekey = strtolower( $table ); + $columnkey = strtolower( $column ); + + // Skip this entirely if this isn't a MySQL database. + if ( false === $this->is_mysql ) { + return false; + } + + if ( empty( $this->col_meta[ $tablekey ] ) ) { + // This primes column information for us. + $table_charset = $this->get_table_charset( $table ); + if ( is_wp_error( $table_charset ) ) { + return $table_charset; + } + } + + if ( empty( $this->col_meta[ $tablekey ][ $columnkey ] ) ) { + return false; + } + + $typeinfo = explode( '(', $this->col_meta[ $tablekey ][ $columnkey ]->Type ); + + $type = strtolower( $typeinfo[0] ); + if ( ! empty( $typeinfo[1] ) ) { + $length = trim( $typeinfo[1], ')' ); + } else { + $length = false; + } + + switch( $type ) { + case 'binary': + case 'char': + case 'varbinary': + case 'varchar': + return $length; + break; + case 'tinyblob': + case 'tinytext': + return 255; // 2^8 - 1 + break; + case 'blob': + case 'text': + return 65535; // 2^16 - 1 + break; + case 'mediumblob': + case 'mediumtext': + return 16777215; // 2^24 - 1 + break; + case 'longblob': + case 'longtext': + return 4294967295; // 2^32 - 1 + break; + default: + return false; + } + + return false; + } + /** * Check if a string is ASCII. *