[pypy-svn] r18552 - in pypy/dist/pypy/translator/c: . src test

arigo at codespeak.net arigo at codespeak.net
Fri Oct 14 16:39:03 CEST 2005


Author: arigo
Date: Fri Oct 14 16:38:59 2005
New Revision: 18552

Modified:
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/src/mem.h
   pypy/dist/pypy/translator/c/test/test_annotated.py
Log:
Check for impossibly large number of items before malloc'ing arrays.



Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Fri Oct 14 16:38:59 2005
@@ -517,11 +517,19 @@
         eresult = self.expr(op.result)
         if VARPART.OF is Void:    # strange
             esize = 'sizeof(%s)' % (cdecl(typename, ''),)
+            result = ''
         else:
-            esize = 'sizeof(%s)+((%s-1)*sizeof(%s))' % (cdecl(typename, ''),
-                                                       elength,
-                                                       cdecl(itemtypename, ''))
-        result = self.gcpolicy.zero_malloc(TYPE, esize, eresult, err)
+            itemtype = cdecl(itemtypename, '')
+            result = 'OP_MAX_VARSIZE(%s, %s, %s);\n' % (
+                elength,
+                itemtype,
+                err)
+            esize = 'sizeof(%s)-sizeof(%s)+%s*sizeof(%s)' % (
+                cdecl(typename, ''),
+                itemtype,
+                elength,
+                itemtype)
+        result += self.gcpolicy.zero_malloc(TYPE, esize, eresult, err)
         result += '\n%s->%s = %s;' % (eresult, lenfld, elength)
         return result
 

Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h	(original)
+++ pypy/dist/pypy/translator/c/src/mem.h	Fri Oct 14 16:38:59 2005
@@ -3,6 +3,17 @@
  /***  C header subsection: operations on LowLevelTypes    ***/
 
 
+/* a reasonably safe bound on the largest allowed argument value
+   that we can pass to malloc.  This is used for var-sized mallocs
+   to compute the largest allowed number of items in the array. */
+#define MAXIMUM_MALLOCABLE_SIZE   (LONG_MAX-4096)
+
+#define OP_MAX_VARSIZE(numitems, itemtype, err)  {			\
+    if ((numitems) > (MAXIMUM_MALLOCABLE_SIZE / sizeof(itemtype)))	\
+        FAIL_EXCEPTION(err, PyExc_MemoryError, "addr space overflow");	\
+  } 
+
+
 /* XXX hack to initialize the refcount of global structures: officially,
    we need a value equal to the number of references to this global from
    other globals, plus one.  This upper bound "approximation" will do... */

Modified: pypy/dist/pypy/translator/c/test/test_annotated.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_annotated.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_annotated.py	Fri Oct 14 16:38:59 2005
@@ -1,5 +1,5 @@
 import autopath
-import py
+import py, sys
 from pypy.translator.tool.cbuild import skip_missing_compiler
 from pypy.translator.translator import Translator
 
@@ -166,3 +166,14 @@
         fn = self.getcompiled(f)
         assert fn(-4.5) == 92.125
         assert fn(4.5) == 90.125
+
+    def test_memoryerror(self):
+        def f(i=int):
+            lst = [0]*i
+            lst[-1] = 5
+            return lst[0]
+        fn = self.getcompiled(f)
+        assert fn(1) == 5
+        assert fn(2) == 0
+        py.test.raises(MemoryError, fn, sys.maxint//2+1)
+        py.test.raises(MemoryError, fn, sys.maxint)



More information about the Pypy-commit mailing list