Make WordPress Core

Changeset 32299


Ignore:
Timestamp:
04/27/2015 02:02:45 PM (11 years ago)
Author:
pento
Message:

WPDB: Sanity check that any strings being stored in the DB are not too long to store correctly.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/wp-db.php

    r32261 r32299  
    19471947        protected function process_fields( $table, $data, $format ) {
    19481948                $data = $this->process_field_formats( $data, $format );
     1949                if ( false === $data ) {
     1950                        return false;
     1951                }
     1952
    19491953                $data = $this->process_field_charsets( $data, $table );
     1954                if ( false === $data ) {
     1955                        return false;
     1956                }
     1957
     1958                $data = $this->process_field_lengths( $data, $table );
    19501959                if ( false === $data ) {
    19511960                        return false;
     
    20242033                                // This isn't ASCII. Don't have strip_invalid_text() re-check.
    20252034                                $value['ascii'] = false;
     2035                        }
     2036
     2037                        $data[ $field ] = $value;
     2038                }
     2039
     2040                return $data;
     2041        }
     2042
     2043        /**
     2044         * For string fields, record the maximum string length that field can safely save.
     2045         *
     2046         * @since 4.2.1
     2047         * @access protected
     2048         *
     2049         * @param array  $data  As it comes from the wpdb::process_field_charsets() method.
     2050         * @param string $table Table name.
     2051         * @return array|False The same array as $data with additional 'length' keys, or false if
     2052         *                     any of the values were too long for their corresponding field.
     2053         */
     2054        protected function process_field_lengths( $data, $table ) {
     2055                foreach ( $data as $field => $value ) {
     2056                        if ( '%d' === $value['format'] || '%f' === $value['format'] ) {
     2057                                // We can skip this field if we know it isn't a string.
     2058                                // This checks %d/%f versus ! %s because it's sprintf() could take more.
     2059                                $value['length'] = false;
     2060                        } else {
     2061                                $value['length'] = $this->get_col_length( $table, $field );
     2062                                if ( is_wp_error( $value['length'] ) ) {
     2063                                        return false;
     2064                                }
     2065                        }
     2066
     2067                        if ( false !== $value['length'] && strlen( $value['value'] ) > $value['length'] ) {
     2068                                return false;
    20262069                        }
    20272070
     
    23632406
    23642407        /**
     2408         * Retrieve the maximum string length allowed in a given column.
     2409         *
     2410         * @since 4.2.1
     2411         * @access public
     2412         *
     2413         * @param string $table  Table name.
     2414         * @param string $column Column name.
     2415         * @return mixed Max column length as an int. False if the column has no
     2416         *               length. WP_Error object if there was an error.
     2417         */
     2418        public function get_col_length( $table, $column ) {
     2419                $tablekey = strtolower( $table );
     2420                $columnkey = strtolower( $column );
     2421
     2422                // Skip this entirely if this isn't a MySQL database.
     2423                if ( false === $this->is_mysql ) {
     2424                        return false;
     2425                }
     2426
     2427                if ( empty( $this->col_meta[ $tablekey ] ) ) {
     2428                        // This primes column information for us.
     2429                        $table_charset = $this->get_table_charset( $table );
     2430                        if ( is_wp_error( $table_charset ) ) {
     2431                                return $table_charset;
     2432                        }
     2433                }
     2434
     2435                if ( empty( $this->col_meta[ $tablekey ][ $columnkey ] ) ) {
     2436                        return false;
     2437                }
     2438
     2439                $typeinfo = explode( '(', $this->col_meta[ $tablekey ][ $columnkey ]->Type );
     2440
     2441                $type = strtolower( $typeinfo[0] );
     2442                if ( ! empty( $typeinfo[1] ) ) {
     2443                        $length = trim( $typeinfo[1], ')' );
     2444                } else {
     2445                        $length = false;
     2446                }
     2447
     2448                switch( $type ) {
     2449                        case 'binary':
     2450                        case 'char':
     2451                        case 'varbinary':
     2452                        case 'varchar':
     2453                                return $length;
     2454                                break;
     2455                        case 'tinyblob':
     2456                        case 'tinytext':
     2457                                return 255; // 2^8 - 1
     2458                                break;
     2459                        case 'blob':
     2460                        case 'text':
     2461                                return 65535; // 2^16 - 1
     2462                                break;
     2463                        case 'mediumblob':
     2464                        case 'mediumtext':
     2465                                return 16777215; // 2^24 - 1
     2466                                break;
     2467                        case 'longblob':
     2468                        case 'longtext':
     2469                                return 4294967295; // 2^32 - 1
     2470                                break;
     2471                        default:
     2472                                return false;
     2473                }
     2474
     2475                return false;
     2476        }
     2477
     2478        /**
    23652479         * Check if a string is ASCII.
    23662480         *
  • trunk/tests/phpunit/tests/comment.php

    r31615 r32299  
    113113                }
    114114        }
     115
     116        public function test_comment_field_lengths() {
     117                // `wp_new_comment()` checks REMOTE_ADDR, so we fake it to avoid PHP notices.
     118                if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
     119                        $remote_addr = $_SERVER['REMOTE_ADDR'];
     120                } else {
     121                        $_SERVER['REMOTE_ADDR'] = '';
     122                }
     123
     124                $post_id = $this->factory->post->create();
     125
     126                $data = array(
     127                        'comment_post_ID' => $post_id,
     128                        'comment_author' => rand_str(),
     129                        'comment_author_url' => '',
     130                        'comment_author_email' => '',
     131                        'comment_type' => '',
     132                        'comment_content' => str_repeat( 'A', 65536 ),
     133                        'comment_date' => '2011-01-01 10:00:00',
     134                        'comment_date_gmt' => '2011-01-01 10:00:00',
     135                );
     136
     137                $id = wp_new_comment( $data );
     138
     139                $this->assertFalse( $id );
     140        }
    115141}
  • trunk/tests/phpunit/tests/db.php

    r31372 r32299  
    748748                                'charset' => $expected_charset,
    749749                                'ascii' => false,
     750                                'length' => $wpdb->get_col_length( $wpdb->posts, 'post_content' ),
    750751                        )
    751752                );
Note: See TracChangeset for help on using the changeset viewer.