[pypy-commit] pypy default: Detect and raise MemoryError upon mallocs of negative length.

arigo noreply at buildbot.pypy.org
Tue Aug 2 11:25:06 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r46182:f75864d925d1
Date: 2011-08-01 20:33 +0200
http://bitbucket.org/pypy/pypy/changeset/f75864d925d1/

Log:	Detect and raise MemoryError upon mallocs of negative length. These
	likely come from overflows in the logic that computed the length in
	the first place. This should be a general fix for all places that
	cannot overflow by more than twice sys.maxint, like the code that
	does concatenation of two strings.

diff --git a/pypy/rpython/memory/gc/minimark.py b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -517,17 +517,17 @@
         # constant-folded because self.nonlarge_max, size and itemsize
         # are all constants (the arguments are constant due to
         # inlining).
-        if not raw_malloc_usage(itemsize):
-            too_many_items = raw_malloc_usage(nonvarsize) > self.nonlarge_max
-        else:
+        too_many_items = raw_malloc_usage(nonvarsize) > self.nonlarge_max
+        if not too_many_items and raw_malloc_usage(itemsize) > 0:
             maxlength = self.nonlarge_max - raw_malloc_usage(nonvarsize)
             maxlength = maxlength // raw_malloc_usage(itemsize)
-            too_many_items = length > maxlength
+            too_many_items = r_uint(length) > r_uint(maxlength)
 
         if too_many_items:
             #
             # If the total size of the object would be larger than
-            # 'nonlarge_max', then allocate it externally.
+            # 'nonlarge_max', then allocate it externally.  We also
+            # go there if 'length' is actually negative.
             obj = self.external_malloc(typeid, length)
             #
         else:
@@ -610,13 +610,18 @@
             # this includes the case of fixed-size objects, for which we
             # should not even ask for the varsize_item_sizes().
             totalsize = nonvarsize
-        else:
+        elif length > 0:
+            # var-sized allocation with at least one item
             itemsize = self.varsize_item_sizes(typeid)
             try:
                 varsize = ovfcheck(itemsize * length)
                 totalsize = ovfcheck(nonvarsize + varsize)
             except OverflowError:
                 raise MemoryError
+        else:
+            # negative length!  This likely comes from an overflow
+            # earlier.  We will just raise MemoryError here.
+            raise MemoryError
         #
         # If somebody calls this function a lot, we must eventually
         # force a full collection.


More information about the pypy-commit mailing list