Ticket #32075: 32075-patch-v11.patch
File 32075-patch-v11.patch, 19.3 KB (added by , 9 years ago) |
---|
-
src/wp-admin/admin.php
From 1cbc918895300a551b49d371d9fde6c7bdbbead0 Mon Sep 17 00:00:00 2001 From: jrfnl <github_nospam@adviesenzo.nl> Date: Fri, 8 Jul 2016 08:43:26 +0200 Subject: [PATCH] Prevent WP setting the memory limit to a value lower than it currently is. Also fixes a bug in how the memory limits were tested in the first place. Includes unit tests for the newly added functions in load.php. --- src/wp-admin/admin.php | 16 +--- src/wp-admin/includes/file.php | 5 +- src/wp-admin/includes/image-edit.php | 3 +- src/wp-includes/class-wp-image-editor-gd.php | 12 +-- src/wp-includes/class-wp-image-editor-imagick.php | 5 +- src/wp-includes/default-constants.php | 65 +++++++------ src/wp-includes/deprecated.php | 5 +- src/wp-includes/functions.php | 110 ++++++++++++++++++++++ src/wp-includes/load.php | 57 +++++++++++ src/wp-includes/media.php | 20 ---- tests/phpunit/tests/functions.php | 14 +++ tests/phpunit/tests/load.php | 72 ++++++++++++++ 12 files changed, 294 insertions(+), 90 deletions(-) create mode 100644 tests/phpunit/tests/load.php diff --git a/src/wp-admin/admin.php b/src/wp-admin/admin.php index 3fabd87..ad341c8 100644
a b else 138 138 require(ABSPATH . 'wp-admin/menu.php'); 139 139 140 140 if ( current_user_can( 'manage_options' ) ) { 141 /** 142 * Filters the maximum memory limit available for administration screens. 143 * 144 * This only applies to administrators, who may require more memory for tasks like updates. 145 * Memory limits when processing images (uploaded or edited by users of any role) are 146 * handled separately. 147 * 148 * The WP_MAX_MEMORY_LIMIT constant specifically defines the maximum memory limit available 149 * when in the administration back end. The default is 256M, or 256 megabytes of memory. 150 * 151 * @since 3.0.0 152 * 153 * @param string 'WP_MAX_MEMORY_LIMIT' The maximum WordPress memory limit. Default 256M. 154 */ 155 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 141 wp_raise_memory_limit( 'admin' ); 156 142 } 157 143 158 144 /** -
src/wp-admin/includes/file.php
diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php index 3b754df..ad66a8d 100644
a b function unzip_file($file, $to) { 569 569 if ( ! $wp_filesystem || !is_object($wp_filesystem) ) 570 570 return new WP_Error('fs_unavailable', __('Could not access filesystem.')); 571 571 572 // Unzip can use a lot of memory, but not this much hopefully 573 /** This filter is documented in wp-admin/admin.php */ 574 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 572 // Unzip can use a lot of memory, but not this much hopefully. 573 wp_raise_memory_limit( 'admin' ); 575 574 576 575 $needed_dirs = array(); 577 576 $to = trailingslashit($to); -
src/wp-admin/includes/image-edit.php
diff --git a/src/wp-admin/includes/image-edit.php b/src/wp-admin/includes/image-edit.php index b34d2ac..c614a77 100644
a b function image_edit_apply_changes( $image, $changes ) { 585 585 function stream_preview_image( $post_id ) { 586 586 $post = get_post( $post_id ); 587 587 588 /** This filter is documented in wp-admin/admin.php */ 589 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 588 wp_raise_memory_limit( 'admin' ); 590 589 591 590 $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) ); 592 591 -
src/wp-includes/class-wp-image-editor-gd.php
diff --git a/src/wp-includes/class-wp-image-editor-gd.php b/src/wp-includes/class-wp-image-editor-gd.php index 96e7bf1..d7823eb 100644
a b class WP_Image_Editor_GD extends WP_Image_Editor { 96 96 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) 97 97 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); 98 98 99 /**100 * Filters the memory limit allocated for image manipulation.101 *102 * @since 3.5.0103 *104 * @param int|string $limit Maximum memory limit to allocate for images. Default WP_MAX_MEMORY_LIMIT.105 * Accepts an integer (bytes), or a shorthand string notation, such as '256M'.106 */107 $image_memory_limit = apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT );108 109 99 // Set artificially high because GD uses uncompressed images in memory. 110 @ini_set( 'memory_limit', $image_memory_limit);100 wp_raise_memory_limit( 'image' ); 111 101 112 102 $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); 113 103 -
src/wp-includes/class-wp-image-editor-imagick.php
diff --git a/src/wp-includes/class-wp-image-editor-imagick.php b/src/wp-includes/class-wp-image-editor-imagick.php index 3d92d39..82b872d 100644
a b class WP_Image_Editor_Imagick extends WP_Image_Editor { 137 137 if ( ! is_file( $this->file ) && ! preg_match( '|^https?://|', $this->file ) ) 138 138 return new WP_Error( 'error_loading_image', __('File doesn’t exist?'), $this->file ); 139 139 140 /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */141 $image_memory_limit = apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT );142 143 140 /* 144 141 * Even though Imagick uses less PHP memory than GD, set higher limit 145 142 * for users that have low PHP.ini limits. 146 143 */ 147 @ini_set( 'memory_limit', $image_memory_limit);144 wp_raise_memory_limit( 'image' ); 148 145 149 146 try { 150 147 $this->image = new Imagick( $this->file ); -
src/wp-includes/default-constants.php
diff --git a/src/wp-includes/default-constants.php b/src/wp-includes/default-constants.php index fe96e34..2aa3430 100644
a b 17 17 function wp_initial_constants() { 18 18 global $blog_id; 19 19 20 // set memory limits 21 if ( !defined('WP_MEMORY_LIMIT') ) { 22 if ( is_multisite() ) { 23 define('WP_MEMORY_LIMIT', '64M'); 20 /**#@+ 21 * Constants for expressing human-readable data sizes in their respective number of bytes. 22 * 23 * @since 4.4.0 24 */ 25 define( 'KB_IN_BYTES', 1024 ); 26 define( 'MB_IN_BYTES', 1024 * KB_IN_BYTES ); 27 define( 'GB_IN_BYTES', 1024 * MB_IN_BYTES ); 28 define( 'TB_IN_BYTES', 1024 * GB_IN_BYTES ); 29 /**#@-*/ 30 31 $current_limit = @ini_get( 'memory_limit' ); 32 $current_limit_int = wp_convert_hr_to_bytes( $current_limit ); 33 34 // Define memory limits. 35 if ( ! defined( 'WP_MEMORY_LIMIT' ) ) { 36 if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) { 37 define( 'WP_MEMORY_LIMIT', $current_limit ); 38 } elseif ( is_multisite() ) { 39 define( 'WP_MEMORY_LIMIT', '64M' ); 24 40 } else { 25 define( 'WP_MEMORY_LIMIT', '40M');41 define( 'WP_MEMORY_LIMIT', '40M' ); 26 42 } 27 43 } 28 44 29 45 if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) ) { 30 define( 'WP_MAX_MEMORY_LIMIT', '256M' ); 46 if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) { 47 define( 'WP_MAX_MEMORY_LIMIT', $current_limit ); 48 } elseif ( -1 === $current_limit_int || $current_limit_int > 268435456 /* = 256M */ ) { 49 define( 'WP_MAX_MEMORY_LIMIT', $current_limit ); 50 } else { 51 define( 'WP_MAX_MEMORY_LIMIT', '256M' ); 52 } 53 } 54 55 // Set memory limits. 56 $wp_limit_int = wp_convert_hr_to_bytes( WP_MEMORY_LIMIT ); 57 if ( -1 !== $current_limit_int && ( -1 === $wp_limit_int || $wp_limit_int > $current_limit_int ) ) { 58 @ini_set( 'memory_limit', WP_MEMORY_LIMIT ); 31 59 } 32 60 33 61 if ( ! isset($blog_id) ) 34 62 $blog_id = 1; 35 63 36 // set memory limits.37 if ( function_exists( 'memory_get_usage' ) ) {38 $current_limit = @ini_get( 'memory_limit' );39 $current_limit_int = intval( $current_limit );40 if ( false !== strpos( $current_limit, 'G' ) )41 $current_limit_int *= 1024;42 $wp_limit_int = intval( WP_MEMORY_LIMIT );43 if ( false !== strpos( WP_MEMORY_LIMIT, 'G' ) )44 $wp_limit_int *= 1024;45 46 if ( -1 != $current_limit && ( -1 == WP_MEMORY_LIMIT || $current_limit_int < $wp_limit_int ) )47 @ini_set( 'memory_limit', WP_MEMORY_LIMIT );48 }49 50 64 if ( !defined('WP_CONTENT_DIR') ) 51 65 define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' ); // no trailing slash, full paths only - WP_CONTENT_URL is defined further down 52 66 … … function wp_initial_constants() { 110 124 define( 'MONTH_IN_SECONDS', 30 * DAY_IN_SECONDS ); 111 125 define( 'YEAR_IN_SECONDS', 365 * DAY_IN_SECONDS ); 112 126 /**#@-*/ 113 114 /**#@+115 * Constants for expressing human-readable data sizes in their respective number of bytes.116 *117 * @since 4.4.0118 */119 define( 'KB_IN_BYTES', 1024 );120 define( 'MB_IN_BYTES', 1024 * KB_IN_BYTES );121 define( 'GB_IN_BYTES', 1024 * MB_IN_BYTES );122 define( 'TB_IN_BYTES', 1024 * GB_IN_BYTES );123 /**#@-*/124 127 } 125 128 126 129 /** -
src/wp-includes/deprecated.php
diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index c61e5d3..0d30113 100644
a b function wp_load_image( $file ) { 3175 3175 if ( ! function_exists('imagecreatefromstring') ) 3176 3176 return __('The GD image library is not installed.'); 3177 3177 3178 /** This filter is documented in wp-includes/class-wp-image-editor-gd.php */3179 $image_memory_limit = apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT );3180 3181 3178 // Set artificially high because GD uses uncompressed images in memory. 3182 @ini_set( 'memory_limit', $image_memory_limit);3179 wp_raise_memory_limit( 'image' ); 3183 3180 3184 3181 $image = imagecreatefromstring( file_get_contents( $file ) ); 3185 3182 -
src/wp-includes/functions.php
diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index df0dbce..1920e39 100644
a b function wp_object_type_exists( $object_type ) { 5379 5379 5380 5380 return false; 5381 5381 } 5382 5383 /** 5384 * Attempts to raise the PHP memory limit for memory intensive processes. 5385 * 5386 * Only allows raising the existing limit and prevents lowering it. 5387 * 5388 * @since 4.6.0 5389 * 5390 * @param string $context Context in which the function is called. 5391 * Either 'admin', 'image' or an arbitrary other context. 5392 * Defaults to 'admin'. 5393 * If an arbitrary context is passed, the similarly arbitrary 5394 * "{$context}_memory_limit" filter will be invoked. 5395 * @return bool|int|string The limit that was set or false on failure. 5396 */ 5397 function wp_raise_memory_limit( $context = 'admin' ) { 5398 // Exit early if the limit cannot be changed. 5399 if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) { 5400 return false; 5401 } 5402 5403 $current_limit = @ini_get( 'memory_limit' ); 5404 $current_limit_int = wp_convert_hr_to_bytes( $current_limit ); 5405 5406 if ( -1 === $current_limit_int ) { 5407 return false; 5408 } 5409 5410 $wp_max_limit = WP_MAX_MEMORY_LIMIT; 5411 $wp_max_limit_int = wp_convert_hr_to_bytes( $wp_max_limit ); 5412 $filtered_limit = $wp_max_limit; 5413 5414 switch ( $context ) { 5415 case 'admin': 5416 /** 5417 * Filters the maximum memory limit available for administration screens. 5418 * 5419 * This only applies to administrators, who may require more memory for tasks like updates. 5420 * Memory limits when processing images (uploaded or edited by users of any role) are 5421 * handled separately. 5422 * 5423 * The WP_MAX_MEMORY_LIMIT constant specifically defines the maximum memory limit available 5424 * when in the administration back end. The default is 256M (256 megabytes 5425 * of memory) or the original `memory_limit` php.ini value if this is higher. 5426 * 5427 * @since 3.0.0 5428 * @since 4.6.0 The default takes the original `memory_limit` into account. 5429 * 5430 * @param int|string $filtered_limit The maximum WordPress memory limit. 5431 * Accepts an integer (bytes), or a shorthand string 5432 * notation, such as '256M'. 5433 */ 5434 $filtered_limit = apply_filters( 'admin_memory_limit', $filtered_limit ); 5435 break; 5436 5437 case 'image': 5438 /** 5439 * Filters the memory limit allocated for image manipulation. 5440 * 5441 * @since 3.5.0 5442 * @since 4.6.0 The default takes the original `memory_limit` into account. 5443 * 5444 * @param int|string $filtered_limit Maximum memory limit to allocate for images. 5445 * Default WP_MAX_MEMORY_LIMIT or the original 5446 * php.ini memory_limit, whichever is higher. 5447 * Accepts an integer (bytes), or a shorthand string 5448 * notation, such as '256M'. 5449 */ 5450 $filtered_limit = apply_filters( 'image_memory_limit', $filtered_limit ); 5451 break; 5452 5453 default: 5454 /** 5455 * Filters the memory limit allocated for arbitrary contexts. 5456 * 5457 * The dynamic portion of the hook name, `$context`, refers to an arbitrary 5458 * context passed on calling the function. This allows for plugins to define 5459 * their own contexts for raising the memory limit. 5460 * 5461 * @since 4.6.0 5462 * 5463 * @param int|string $filtered_limit Maximum memory limit to allocate for images. 5464 * Default 256M or the original php.ini memory_limit, 5465 * whichever is higher. 5466 * Accepts an integer (bytes), or a shorthand string 5467 * notation, such as '256M'. 5468 */ 5469 $filtered_limit = apply_filters( "{$context}_memory_limit", $filtered_limit ); 5470 break; 5471 } 5472 5473 $filtered_limit_int = wp_convert_hr_to_bytes( $filtered_limit ); 5474 5475 if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) { 5476 if ( false !== @ini_set( 'memory_limit', $filtered_limit ) ) { 5477 return $filtered_limit; 5478 } else { 5479 return false; 5480 } 5481 } elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) { 5482 if ( false !== @ini_set( 'memory_limit', $wp_max_limit ) ) { 5483 return $wp_max_limit; 5484 } else { 5485 return false; 5486 } 5487 } 5488 else { 5489 return false; 5490 } 5491 } -
src/wp-includes/load.php
diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php index c6ff6cb..1d8e52d 100644
a b function is_ssl() { 974 974 } 975 975 return false; 976 976 } 977 978 /** 979 * Converts a shorthand byte value to an integer byte value. 980 * 981 * @since 2.3.0 982 * 983 * @link http://php.net/manual/en/function.ini-get.php 984 * @link http://php.net/manual/en/faq.using.php#faq.using.shorthandbytes 985 * 986 * @param string $value An (PHP ini) byte value, either shorthand or ordinary. 987 * @return int An integer byte value. 988 */ 989 function wp_convert_hr_to_bytes( $value ) { 990 $value = trim( $value ); 991 $last = strtolower( substr( $value, -1 ) ); 992 993 switch ( $last ) { 994 case 'g': 995 $value *= GB_IN_BYTES; 996 break; 997 case 'm': 998 $value *= MB_IN_BYTES; 999 break; 1000 case 'k': 1001 $value *= KB_IN_BYTES; 1002 break; 1003 default: 1004 // Left empty on purpose. 1005 break; 1006 } 1007 1008 // Deal with large (float) values which run into the maximum integer size. 1009 return (int) min( PHP_INT_MAX, $value ); 1010 } 1011 1012 /** 1013 * Determines whether a PHP ini value is changeable at runtime. 1014 * 1015 * @since 4.6.0 1016 * 1017 * @link http://php.net/manual/en/function.ini-get-all.php 1018 * 1019 * @param string $setting The name of the ini setting to check. 1020 * @return bool True if the value is changeable at runtime. False otherwise. 1021 */ 1022 function wp_is_ini_value_changeable( $setting ) { 1023 static $ini_all; 1024 1025 if ( ! isset( $ini_all ) ) { 1026 $ini_all = ini_get_all(); 1027 } 1028 1029 if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === $ini_all[ $setting ]['access'] || INI_USER === $ini_all[ $setting ]['access'] ) ) { 1030 return true; 1031 } 1032 return false; 1033 } -
src/wp-includes/media.php
diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 6a060b1..df96a17 100644
a b function wp_expand_dimensions( $example_width, $example_height, $max_width, $max 2777 2777 } 2778 2778 2779 2779 /** 2780 * Converts a shorthand byte value to an integer byte value.2781 *2782 * @since 2.3.02783 *2784 * @param string $size A shorthand byte value.2785 * @return int An integer byte value.2786 */2787 function wp_convert_hr_to_bytes( $size ) {2788 $size = strtolower( $size );2789 $bytes = (int) $size;2790 if ( strpos( $size, 'k' ) !== false )2791 $bytes = intval( $size ) * KB_IN_BYTES;2792 elseif ( strpos( $size, 'm' ) !== false )2793 $bytes = intval($size) * MB_IN_BYTES;2794 elseif ( strpos( $size, 'g' ) !== false )2795 $bytes = intval( $size ) * GB_IN_BYTES;2796 return $bytes;2797 }2798 2799 /**2800 2780 * Determines the maximum upload size allowed in php.ini. 2801 2781 * 2802 2782 * @since 2.5.0 -
tests/phpunit/tests/functions.php
diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index ce5f657..ff49f28 100644
a b class Tests_Functions extends WP_UnitTestCase { 865 865 866 866 $this->assertNull( wp_ext2type( 'unknown_format' ) ); 867 867 } 868 869 /** 870 * Test raising the memory limit. 871 * 872 * Unfortunately as the default for 'WP_MAX_MEMORY_LIMIT' in the 873 * test suite is -1, we can not test the memory limit negotiations. 874 * 875 * @ticket 32075 876 */ 877 function test_wp_raise_memory_limit() { 878 ini_set( 'memory_limit', '40M' ); 879 $this->assertSame( -1, wp_raise_memory_limit() ); 880 $this->assertEquals( '-1', ini_get( 'memory_limit' ) ); 881 } 868 882 } -
new file tests/phpunit/tests/load.php
diff --git a/tests/phpunit/tests/load.php b/tests/phpunit/tests/load.php new file mode 100644 index 0000000..a27de49
- + 1 <?php 2 3 /** 4 * @group load.php 5 */ 6 class Tests_Load extends WP_UnitTestCase { 7 8 /** 9 * Test converting (PHP ini) byte values to integer byte values. 10 * 11 * @dataProvider data_wp_convert_hr_to_bytes 12 */ 13 function test_wp_convert_hr_to_bytes( $value, $expected ) { 14 $this->assertSame( $expected, wp_convert_hr_to_bytes( $value ) ); 15 } 16 17 function data_wp_convert_hr_to_bytes() { 18 $array = array( 19 // Integer input. 20 array( -1, -1 ), // = no memory limit. 21 array( 8388608, 8388608 ), // 8M. 22 23 // String input (memory limit shorthand values). 24 array( '32k', 32768 ), 25 array( '64K', 65536 ), 26 array( '128m', 134217728 ), 27 array( '256M', 268435456 ), 28 array( '1g', 1073741824 ), 29 array( '1024', 1024 ), // No letter will be interpreted as integer value. 30 31 // Edge cases. 32 array( 'g', 0 ), 33 array( 'null', 0 ), 34 array( 'off', 0 ), 35 ); 36 37 // Test for running into maximum integer size limit on 32bit systems. 38 if ( 2147483647 === PHP_INT_MAX ) { 39 $array[] = array( '2G', 2147483647 ); 40 $array[] = array( '4G', 2147483647 ); 41 } else { 42 $array[] = array( '2G', 2147483648 ); 43 $array[] = array( '4G', 4294967296 ); 44 } 45 46 return $array; 47 } 48 49 /** 50 * Test the determining of the changeability of a PHP ini value. 51 * 52 * @dataProvider data_wp_is_ini_value_changeable 53 */ 54 function test_wp_is_ini_value_changeable( $setting, $expected ) { 55 $this->assertSame( $expected, wp_is_ini_value_changeable( $setting ) ); 56 } 57 58 function data_wp_is_ini_value_changeable() { 59 $array = array( 60 array( 'memory_limit', true ), // PHP_INI_ALL. 61 array( 'log_errors', true ), // PHP_INI_ALL. 62 array( 'upload_max_filesize', false ), // PHP_INI_PERDIR. 63 array( 'upload_tmp_dir', false ), // PHP_INI_SYSTEM. 64 ); 65 66 if ( extension_loaded( 'Tidy' ) && version_compare( PHP_VERSION, '7.0.0', '>' ) ) { 67 $array[] = array( 'tidy.clean_output', true ); // PHP_INI_USER. 68 } 69 70 return $array; 71 } 72 }