WordPress.org

Make WordPress Core

Changeset 40124


Ignore:
Timestamp:
02/25/2017 04:07:25 PM (17 months ago)
Author:
joemcgill
Message:

Media: Reduce failing uploads following 4.7.1.

[39831] introduced more strict MIME type checking for uploads, which
resulted in unintetionally blocking several filetypes that were
previously valid. This change uses a more targeted approach to MIME
validation to restore previous behavior for most types.

Props blobfolio, iandunn, ipstenu, markoheijnen, xknown, joemcgill.
Fixes #39550, #39552.

Location:
trunk
Files:
4 added
2 edited

Legend:

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

    r40039 r40124  
    22702270    }
    22712271
     2272    $real_mime = false;
     2273
    22722274    // Validate image types.
    22732275    if ( $type && 0 === strpos( $type, 'image/' ) ) {
     
    22762278        $real_mime = wp_get_image_mime( $file );
    22772279
    2278         if ( ! $real_mime ) {
    2279             $type = $ext = false;
    2280         } elseif ( $real_mime != $type ) {
     2280        if ( $real_mime && $real_mime != $type ) {
    22812281            /**
    22822282             * Filters the list mapping image mime types to their respective extensions.
     
    23092309                $type = $wp_filetype['type'];
    23102310            } else {
    2311                 $type = $ext = false;
     2311                // Reset $real_mime and try validating again.
     2312                $real_mime = false;
    23122313            }
    23132314        }
    2314     } elseif ( function_exists( 'finfo_file' ) ) {
    2315         // Use finfo_file if available to validate non-image files.
     2315    }
     2316
     2317    // Validate files that didn't get validated during previous checks.
     2318    if ( $type && ! $real_mime && extension_loaded( 'fileinfo' ) ) {
    23162319        $finfo = finfo_open( FILEINFO_MIME_TYPE );
    23172320        $real_mime = finfo_file( $finfo, $file );
    23182321        finfo_close( $finfo );
    23192322
    2320         // If the extension does not match the file's real type, return false.
    2321         if ( $real_mime !== $type ) {
    2322             $type = $ext = false;
     2323        /*
     2324         * If $real_mime doesn't match what we're expecting, we need to do some extra
     2325         * vetting of application mime types to make sure this type of file is allowed.
     2326         * Other mime types are assumed to be safe, but should be considered unverified.
     2327         */
     2328        if ( $real_mime && ( $real_mime !== $type ) && ( 0 === strpos( $real_mime, 'application' ) ) ) {
     2329            $allowed = get_allowed_mime_types();
     2330
     2331            if ( ! in_array( $real_mime, $allowed ) ) {
     2332                $type = $ext = false;
     2333            }
    23232334        }
    23242335    }
  • trunk/tests/phpunit/tests/functions.php

    r40044 r40124  
    915915        $this->assertEquals( $uuids, $unique_uuids );
    916916    }
     917
     918    /**
     919     * @ticket 39550
     920     * @dataProvider _wp_check_filetype_and_ext_data
     921     */
     922    function test_wp_check_filetype_and_ext( $file, $filename, $expected ) {
     923        if ( ! extension_loaded( 'fileinfo' ) ) {
     924            $this->markTestSkipped( 'The fileinfo PHP extension is not loaded.' );
     925        }
     926
     927        $this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
     928    }
     929
     930    /**
     931     * @ticket 39550
     932     */
     933    function test_wp_check_filetype_and_ext_with_filtered_svg() {
     934        $file = DIR_TESTDATA . '/uploads/video-play.svg';
     935        $filename = 'video-play.svg';
     936
     937        $expected = array(
     938            'ext' => 'svg',
     939            'type' => 'image/svg+xml',
     940            'proper_filename' => false,
     941        );
     942
     943        add_filter( 'upload_mimes', array( $this, '_filter_mime_types_svg' ) );
     944        $this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
     945
     946        // Cleanup.
     947        remove_filter( 'upload_mimes', array( $this, '_test_add_mime_types_svg' ) );
     948    }
     949
     950    /**
     951     * @ticket 39550
     952     */
     953    function test_wp_check_filetype_and_ext_with_filtered_woff() {
     954        $file = DIR_TESTDATA . '/uploads/dashicons.woff';
     955        $filename = 'dashicons.woff';
     956
     957        $expected = array(
     958            'ext' => 'woff',
     959            'type' => 'application/font-woff',
     960            'proper_filename' => false,
     961        );
     962
     963        add_filter( 'upload_mimes', array( $this, '_filter_mime_types_woff' ) );
     964        $this->assertEquals( $expected, wp_check_filetype_and_ext( $file, $filename ) );
     965
     966        // Cleanup.
     967        remove_filter( 'upload_mimes', array( $this, '_test_add_mime_types_woff' ) );
     968    }
     969
     970    public function _filter_mime_types_svg( $mimes ) {
     971        $mimes['svg'] = 'image/svg+xml';
     972        return $mimes;
     973    }
     974
     975    public function _filter_mime_types_woff( $mimes ) {
     976        $mimes['woff'] = 'application/font-woff';
     977        return $mimes;
     978    }
     979
     980    public function _wp_check_filetype_and_ext_data() {
     981        return array(
     982            // Standard image.
     983            array(
     984                DIR_TESTDATA . '/images/canola.jpg',
     985                'canola.jpg',
     986                array(
     987                    'ext' => 'jpg',
     988                    'type' => 'image/jpeg',
     989                    'proper_filename' => false,
     990                ),
     991            ),
     992            // Image with wrong extension.
     993            array(
     994                DIR_TESTDATA . '/images/test-image-mime-jpg.png',
     995                'test-image-mime-jpg.png',
     996                array(
     997                    'ext' => 'jpg',
     998                    'type' => 'image/jpeg',
     999                    'proper_filename' => 'test-image-mime-jpg.jpg',
     1000                ),
     1001            ),
     1002            // Image without extension.
     1003            array(
     1004                DIR_TESTDATA . '/images/test-image-no-extension',
     1005                'test-image-no-extension',
     1006                array(
     1007                    'ext' => false,
     1008                    'type' => false,
     1009                    'proper_filename' => false,
     1010                ),
     1011            ),
     1012            // Valid non-image file with an image extension.
     1013            array(
     1014                DIR_TESTDATA . '/formatting/big5.txt',
     1015                'big5.jpg',
     1016                array(
     1017                    'ext' => 'jpg',
     1018                    'type' => 'image/jpeg',
     1019                    'proper_filename' => false,
     1020                ),
     1021            ),
     1022            // Standard non-image file.
     1023            array(
     1024                DIR_TESTDATA . '/formatting/big5.txt',
     1025                'big5.txt',
     1026                array(
     1027                    'ext' => 'txt',
     1028                    'type' => 'text/plain',
     1029                    'proper_filename' => false,
     1030                ),
     1031            ),
     1032            // Non-image file with wrong sub-type.
     1033            array(
     1034                DIR_TESTDATA . '/uploads/pages-to-word.docx',
     1035                'pages-to-word.docx',
     1036                array(
     1037                    'ext' => 'docx',
     1038                    'type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
     1039                    'proper_filename' => false,
     1040                ),
     1041            ),
     1042            // Non-image file not allowed.
     1043            array(
     1044                DIR_TESTDATA . '/export/crazy-cdata.xml',
     1045                'crazy-cdata.xml',
     1046                array(
     1047                    'ext' => false,
     1048                    'type' => false,
     1049                    'proper_filename' => false,
     1050                ),
     1051            ),
     1052        );
     1053    }
    9171054}
Note: See TracChangeset for help on using the changeset viewer.