Ticket #32075: 32075-improved-patch-v7.patch
File 32075-improved-patch-v7.patch, 16.8 KB (added by , 9 years ago) |
---|
-
src/wp-admin/admin.php
From f2628465439c7882cec5f1d2e8090929fa00320c Mon Sep 17 00:00:00 2001 Date: Sun, 10 Apr 2016 16:07:39 +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 | 3 +- src/wp-admin/includes/image-edit.php | 3 +- src/wp-includes/class-wp-image-editor-gd.php | 10 +-- src/wp-includes/class-wp-image-editor-imagick.php | 3 +- src/wp-includes/default-constants.php | 43 +++++----- src/wp-includes/deprecated.php | 3 +- src/wp-includes/functions.php | 95 +++++++++++++++++++++++ src/wp-includes/load.php | 58 ++++++++++++++ tests/phpunit/tests/functions.php | 16 ++++ tests/phpunit/tests/load.php | 72 +++++++++++++++++ 11 files changed, 271 insertions(+), 51 deletions(-) create mode 100644 tests/phpunit/tests/load.php diff --git a/src/wp-admin/admin.php b/src/wp-admin/admin.php index a54ca21..6c01415 100644
a b else 138 138 require(ABSPATH . 'wp-admin/menu.php'); 139 139 140 140 if ( current_user_can( 'manage_options' ) ) { 141 /** 142 * Filter 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 72f5e22..4b718a7 100644
a b function unzip_file($file, $to) { 558 558 return new WP_Error('fs_unavailable', __('Could not access filesystem.')); 559 559 560 560 // Unzip can use a lot of memory, but not this much hopefully 561 /** This filter is documented in wp-admin/admin.php */ 562 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 561 wp_raise_memory_limit( 'admin' ); 563 562 564 563 $needed_dirs = array(); 565 564 $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 8947f53..a954d24 100644
a b function image_edit_apply_changes( $image, $changes ) { 586 586 function stream_preview_image( $post_id ) { 587 587 $post = get_post( $post_id ); 588 588 589 /** This filter is documented in wp-admin/admin.php */ 590 @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 589 wp_raise_memory_limit( 'admin' ); 591 590 592 591 $img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) ); 593 592 -
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 2093c6b..9cb756d 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 * Filter 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 99 // Set artificially high because GD uses uncompressed images in memory 108 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ));100 wp_raise_memory_limit( 'image' ); 109 101 110 102 $this->image = @imagecreatefromstring( file_get_contents( $this->file ) ); 111 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 7632cbb..5372eaa 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-imagick.php */141 140 // Even though Imagick uses less PHP memory than GD, set higher limit for users that have low PHP.ini limits 142 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ));141 wp_raise_memory_limit( 'image' ); 143 142 144 143 try { 145 144 $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 c9092bd..cb790fb 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 $current_limit = @ini_get( 'memory_limit' ); 21 $current_limit_int = wp_php_ini_bytes_to_int( $current_limit ); 22 23 // Define memory limits. 24 if ( ! defined( 'WP_MEMORY_LIMIT' ) ) { 25 if ( false === wp_is_ini_value_changable( 'memory_limit' ) ) { 26 define( 'WP_MEMORY_LIMIT', $current_limit ); 27 } elseif ( is_multisite() ) { 28 define( 'WP_MEMORY_LIMIT', '64M' ); 24 29 } else { 25 define( 'WP_MEMORY_LIMIT', '40M');30 define( 'WP_MEMORY_LIMIT', '40M' ); 26 31 } 27 32 } 28 33 29 34 if ( ! defined( 'WP_MAX_MEMORY_LIMIT' ) ) { 30 define( 'WP_MAX_MEMORY_LIMIT', '256M' ); 35 if ( false === wp_is_ini_value_changable( 'memory_limit' ) ) { 36 define( 'WP_MAX_MEMORY_LIMIT', $current_limit ); 37 } elseif ( -1 === $current_limit_int || $current_limit_int > 268435456 ) { 38 define( 'WP_MAX_MEMORY_LIMIT', $current_limit ); 39 } else { 40 define( 'WP_MAX_MEMORY_LIMIT', '256M' ); 41 } 42 } 43 44 // Set memory limits. 45 $wp_limit_int = wp_php_ini_bytes_to_int( WP_MEMORY_LIMIT ); 46 if ( -1 !== $current_limit_int && ( -1 === $wp_limit_int || $wp_limit_int > $current_limit_int ) ) { 47 @ini_set( 'memory_limit', WP_MEMORY_LIMIT ); 31 48 } 32 49 33 50 if ( ! isset($blog_id) ) 34 51 $blog_id = 1; 35 52 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 53 if ( !defined('WP_CONTENT_DIR') ) 51 54 define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' ); // no trailing slash, full paths only - WP_CONTENT_URL is defined further down 52 55 -
src/wp-includes/deprecated.php
diff --git a/src/wp-includes/deprecated.php b/src/wp-includes/deprecated.php index f79761b..0247d4a 100644
a b function wp_load_image( $file ) { 3176 3176 return __('The GD image library is not installed.'); 3177 3177 3178 3178 // Set artificially high because GD uses uncompressed images in memory 3179 @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) ); 3179 wp_raise_memory_limit( 'image' ); 3180 3180 3181 $image = imagecreatefromstring( file_get_contents( $file ) ); 3181 3182 3182 3183 if ( !is_resource( $image ) ) -
src/wp-includes/functions.php
diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php index 0e720ee..f3bef58 100644
a b function mysql_to_rfc3339( $date_string ) { 5280 5280 // Strip timezone information 5281 5281 return preg_replace( '/(?:Z|[+-]\d{2}(?::\d{2})?)$/', '', $formatted ); 5282 5282 } 5283 5284 /** 5285 * Attempts to raise the PHP memory limit for memory intensive processes. 5286 * 5287 * Allows only to raise the existing limit and prevents lowering it. 5288 * 5289 * @since 4.6.0 5290 * 5291 * @param string $context Context in which the function is called. 5292 * Either 'admin' or 'image'. Defaults to 'admin'. 5293 */ 5294 function wp_raise_memory_limit( $context = 'admin' ) { 5295 // Exit early if the limit cannot be changed. 5296 if ( false === wp_is_ini_value_changable( 'memory_limit' ) ) { 5297 return; 5298 } 5299 5300 $current_limit = @ini_get( 'memory_limit' ); 5301 $current_limit_int = wp_php_ini_bytes_to_int( $current_limit ); 5302 5303 if ( -1 === $current_limit_int ) { 5304 return; 5305 } 5306 5307 $wp_max_limit = WP_MAX_MEMORY_LIMIT; 5308 $wp_max_limit_int = wp_php_ini_bytes_to_int( $wp_max_limit ); 5309 $filtered_limit = $wp_max_limit; 5310 5311 switch ( $context ) { 5312 case 'admin': 5313 /** 5314 * Filter the memory limit available for administration screens. 5315 * 5316 * This only applies to administrators, who may require more memory for tasks like updates. 5317 * Memory limits when processing images (uploaded or edited by users of any role) are 5318 * handled separately. 5319 * 5320 * The WP_MAX_MEMORY_LIMIT constant specifically defines the maximum memory limit available 5321 * when in the administration back end. The default is 256M (256 megabytes 5322 * of memory) or the original `memory_limit` php.ini value if this is higher. 5323 * 5324 * @since 3.0.0 5325 * @since 4.6.0 The default takes the original `memory_limit` into account. 5326 * 5327 * @param int|string $filtered_limit The maximum WordPress memory limit. 5328 * Accepts an integer (bytes), or a shorthand string 5329 * notation, such as '256M'. 5330 */ 5331 $filtered_limit = apply_filters( 'admin_memory_limit', $filtered_limit ); 5332 break; 5333 5334 case 'image': 5335 /** 5336 * Filter the memory limit allocated for image manipulation. 5337 * 5338 * @since 3.5.0 5339 * @since 4.6.0 The default takes the original `memory_limit` into account. 5340 * 5341 * @param int|string $filtered_limit Maximum memory limit to allocate for images. 5342 * Default 256M or the original php.ini memory_limit, 5343 * whichever is higher. 5344 * Accepts an integer (bytes), or a shorthand string 5345 * notation, such as '256M'. 5346 */ 5347 $filtered_limit = apply_filters( 'image_memory_limit', $filtered_limit ); 5348 break; 5349 5350 default: 5351 /** 5352 * Filter the memory limit allocated for arbitrary contexts. 5353 * 5354 * The dynamic portion of the hook name, `$context`, refers to an arbitrary 5355 * context passed on calling the function. This allows for plugins to define 5356 * their own contexts for raising the memory limit. 5357 * 5358 * @since 4.6.0 5359 * 5360 * @param int|string $filtered_limit Maximum memory limit to allocate for images. 5361 * Default 256M or the original php.ini memory_limit, 5362 * whichever is higher. 5363 * Accepts an integer (bytes), or a shorthand string 5364 * notation, such as '256M'. 5365 */ 5366 $filtered_limit = apply_filters( "{$context}_memory_limit", $filtered_limit ); 5367 break; 5368 } 5369 5370 $filtered_limit_int = wp_php_ini_bytes_to_int( $filtered_limit ); 5371 5372 if ( -1 === $filtered_limit_int || ( $filtered_limit_int > $wp_max_limit_int && $filtered_limit_int > $current_limit_int ) ) { 5373 @ini_set( 'memory_limit', $filtered_limit ); 5374 } elseif ( -1 === $wp_max_limit_int || $wp_max_limit_int > $current_limit_int ) { 5375 @ini_set( 'memory_limit', $wp_max_limit ); 5376 } 5377 } -
src/wp-includes/load.php
diff --git a/src/wp-includes/load.php b/src/wp-includes/load.php index 2f2d95b..93add7b 100644
a b function wp_installing( $is_installing = null ) { 895 895 896 896 return (bool) $installing; 897 897 } 898 899 /** 900 * Converts a PHP ini shorthand byte value to an integer byte value. 901 * 902 * @since 4.6.0 903 * 904 * @see http://php.net/manual/en/function.ini-get.php 905 * @see http://php.net/manual/en/faq.using.php#faq.using.shorthandbytes 906 * 907 * @param string $value An PHP ini byte value, either shorthand or ordinary. 908 * @return int Value in bytes. 909 */ 910 function wp_php_ini_bytes_to_int( $value ) { 911 $value = trim( $value ); 912 $last = strtolower( $value[ strlen( $value ) - 1 ] ); 913 914 switch( $last ) { 915 // Note: the `break` statement is left out on purpose! 916 case 'g': 917 $value *= 1024; 918 case 'm': 919 $value *= 1024; 920 case 'k': 921 $value *= 1024; 922 default: 923 // Left empty on purpose. 924 break; 925 } 926 927 // Deal with large (float) values which run into the maximum integer size. 928 if ( PHP_INT_MAX < $value ) { 929 $value = PHP_INT_MAX; 930 } 931 return (int) $value; 932 } 933 934 /** 935 * Determines whether a PHP ini value is changable at runtime. 936 * 937 * @since 4.6.0 938 * 939 * @see http://php.net/manual/en/function.ini-get-all.php 940 * 941 * @param string $setting The name of the ini setting to check. 942 * @return bool True if the value is changable at runtime. False otherwise. 943 */ 944 function wp_is_ini_value_changable( $setting ) { 945 static $ini_all; 946 947 if ( ! isset( $ini_all ) ) { 948 $ini_all = ini_get_all(); 949 } 950 951 if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === $ini_all[ $setting ]['access'] || INI_USER === $ini_all[ $setting ]['access'] ) ) { 952 return true; 953 } 954 return false; 955 } -
tests/phpunit/tests/functions.php
diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php index 6d6e177..023e81e 100644
a b class Tests_Functions extends WP_UnitTestCase { 813 813 array( '2016-03-02T19:13:00', '16-03-02 19:13' ) 814 814 ); 815 815 } 816 817 /** 818 * Test raising the memory limit. 819 * 820 * {@internal Unfortunately as the default for 'WP_MAX_MEMORY_LIMIT' in the 821 * test suite is -1, we can not test the memory limit negotiations.}} 822 * 823 * @ticket 32075 824 */ 825 function test_wp_raise_memory_limit() { 826 $original = ini_get( 'memory_limit' ); 827 828 ini_set( 'memory_limit', '40M' ); 829 wp_raise_memory_limit(); 830 $this->assertEquals( '-1', ini_get( 'memory_limit' ) ); 831 } 816 832 } -
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..84133ff
- + 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_php_ini_bytes_to_int 12 */ 13 function test_wp_php_ini_bytes_to_int( $value, $expected ) { 14 $this->assertSame( $expected, wp_php_ini_bytes_to_int( $value ) ); 15 } 16 17 function data_wp_php_ini_bytes_to_int() { 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 while 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 changability of a PHP ini value. 51 * 52 * @dataProvider data_wp_is_ini_value_changable 53 */ 54 function test_wp_is_ini_value_changable( $setting, $expected ) { 55 $this->assertSame( $expected, wp_is_ini_value_changable( $setting ) ); 56 } 57 58 function data_wp_is_ini_value_changable() { 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 }