php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #34156 memory_limit doesn't prevent exit
Submitted: 2005-08-16 20:58 UTC Modified: 2005-08-18 17:14 UTC
From: robert at rw-it dot net Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 5CVS, 4CVS (2005-08-18) OS: *
Private report: No CVE-ID: None
 [2005-08-16 20:58 UTC] robert at rw-it dot net
Description:
------------
If memory_limit is turned on, memory will be marked as allocated although it isn't, because the _CHECK_MEMORY_LIMIT macro (zend_alloc.c) starts like this:

#define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { AG(allocated_memory) += rs;\

Thus, allocated_memory is increased by the block size, even though zend_error might be called.

This seems to apply to PHP-5.0.4, too, but not tested (only looked at the code).

Reproduce code:
---------------
Write some script that consumes all available memory:

for ($i = 0, $b = 'x'; ; $i++, $b .= $b)
	echo "$i, ";

Reload a few times.


Expected result:
----------------
Same output everytime, no exit(1).
Output for memory_limit = 8M on my machine:

Allowed memory size of 8388608 bytes exhausted (tried to allocate 4194305 bytes)


Actual result:
--------------
Available memory decreases with each reload, until finally AG(memory_limit)+1048576 < AG(allocated_memory) - rs and PHP exits.
Output for memory_limit = 8M:

Allowed memory size of 8388608 bytes exhausted (tried to allocate 4194305 bytes)

Allowed memory size of 8388608 bytes exhausted (tried to allocate 2097153 bytes)

...

Allowed memory size of 8388608 bytes exhausted (tried to allocate 2049 bytes)

(Server process exits on next reload)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-08-16 21:48 UTC] robert at rw-it dot net
Here is a patch that solves the problem (against 4.4.0, I hope it survives being pasted into a textarea):

--- zend_alloc.c0	Thu Apr  7 20:54:33 2005
+++ zend_alloc.c	Tue Aug 16 19:36:52 2005
@@ -64,11 +64,11 @@
 #define CHECK_MEMORY_LIMIT(s, rs)	_CHECK_MEMORY_LIMIT(s, rs, NULL, 0)
 #  endif
 
-#define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { AG(allocated_memory) += rs;\
-								if (AG(memory_limit)<AG(allocated_memory)) {\
-									int php_mem_limit = AG(memory_limit); \
-									if (EG(in_execution) && AG(memory_limit)+1048576 > AG(allocated_memory) - rs) { \
-										AG(memory_limit) = AG(allocated_memory) + 1048576; \
+#define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { unsigned int php_alloc_mem = AG(allocated_memory) + rs; \
+								if (AG(memory_limit)<php_alloc_mem) {\
+									unsigned int php_mem_limit = AG(memory_limit); \
+									if (EG(in_execution) && AG(memory_limit)+1048576 > AG(allocated_memory)) { \
+										AG(memory_limit) = php_alloc_mem + 1048576; \
 										if (file) { \
 											zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)", php_mem_limit, file, lineno, s); \
 										} else { \
@@ -83,6 +83,7 @@
 										exit(1); \
 									} \
 								} \
+								AG(allocated_memory) = php_alloc_mem; \
 							}
 # endif
 [2005-08-18 17:14 UTC] iliaa@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Dec 13 09:01:28 2024 UTC