[pypy-svn] r45883 - in pypy/branch/pypy-more-rtti-inprogress/translator/c: . src

arigo at codespeak.net arigo at codespeak.net
Mon Aug 20 17:23:12 CEST 2007


Author: arigo
Date: Mon Aug 20 17:23:10 2007
New Revision: 45883

Modified:
   pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py
   pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h
Log:
A new debugging macro, RPY_LL_ASSERT, which enables checks for pointer low-level operations 
(pointer-non-null, array index out of bounds...).  This differs from RPY_ASSERT in the 
level at which the checks are made.  See comments.


Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/funcgen.py	Mon Aug 20 17:23:10 2007
@@ -469,29 +469,26 @@
 
     def OP_GETARRAYITEM(self, op):
         ARRAY = self.lltypemap(op.args[0]).TO
-        items = self.expr(op.args[0])
-        if not isinstance(ARRAY, FixedSizeArray):
-            items += '->items'
-        return self.generic_get(op, '%s[%s]' % (items,
-                                                self.expr(op.args[1])))
+        ptr = self.expr(op.args[0])
+        index = self.expr(op.args[1])
+        arraydef = self.db.gettypedefnode(ARRAY)
+        return self.generic_get(op, arraydef.itemindex_access_expr(ptr, index))
 
     def OP_SETARRAYITEM(self, op):
         ARRAY = self.lltypemap(op.args[0]).TO
-        items = self.expr(op.args[0])
-        if not isinstance(ARRAY, FixedSizeArray):
-            items += '->items'
-        return self.generic_set(op, '%s[%s]' % (items,
-                                                self.expr(op.args[1])))
+        ptr = self.expr(op.args[0])
+        index = self.expr(op.args[1])
+        arraydef = self.db.gettypedefnode(ARRAY)
+        return self.generic_set(op, arraydef.itemindex_access_expr(ptr, index))
     OP_BARE_SETARRAYITEM = OP_SETARRAYITEM
 
     def OP_GETARRAYSUBSTRUCT(self, op):
         ARRAY = self.lltypemap(op.args[0]).TO
-        items = self.expr(op.args[0])
-        if not isinstance(ARRAY, FixedSizeArray):
-            items += '->items'
-        return '%s = %s + %s;' % (self.expr(op.result),
-                                  items,
-                                  self.expr(op.args[1]))
+        ptr = self.expr(op.args[0])
+        index = self.expr(op.args[1])
+        arraydef = self.db.gettypedefnode(ARRAY)
+        return '%s = &%s;' % (self.expr(op.result),
+                              arraydef.itemindex_access_expr(ptr, index))
 
     def OP_PTR_NONZERO(self, op):
         return '%s = (%s != NULL);' % (self.expr(op.result),

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/genc.py	Mon Aug 20 17:23:10 2007
@@ -888,6 +888,9 @@
 debug_mem:
 \tmake CFLAGS="-g -DRPY_ASSERT -DNO_OBMALLOC"
 
+llsafer:
+\tmake CFLAGS="-O2 -DRPY_LL_ASSERT"
+
 profile:
 \tmake CFLAGS="-g -pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)"
 

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/node.py	Mon Aug 20 17:23:10 2007
@@ -145,7 +145,7 @@
                 return '(*(%s) %s)' % (cdecl(self.db.gettype(FIRST), '*'),
                                        baseexpr)
         fldname = self.c_struct_field_name(fldname)
-        return '%s->%s' % (baseexpr, fldname)
+        return 'RPyField(%s, %s)' % (baseexpr, fldname)
 
     def definition(self):
         if self.fields is None:   # external definition only
@@ -240,7 +240,14 @@
         return '%s.items[%d]' % (baseexpr, index)
 
     def ptr_access_expr(self, baseexpr, index):
-        return '%s->items[%d]' % (baseexpr, index)
+        assert 0 <= index <= sys.maxint, "invalid constant index %r" % (index,)
+        return self.itemindex_access_expr(baseexpr, index)
+
+    def itemindex_access_expr(self, baseexpr, indexexpr):
+        if self.ARRAY._hints.get('nolength', False):
+            return 'RPyNLenItem(%s, %s)' % (baseexpr, indexexpr)
+        else:
+            return 'RPyItem(%s, %s)' % (baseexpr, indexexpr)
 
     def definition(self):
         gcpolicy = self.db.gcpolicy
@@ -321,10 +328,17 @@
         if not isinstance(index, int):
             assert index.startswith('item')
             index = int(index[4:])
+        if not (0 <= index < self.FIXEDARRAY.length):
+            raise IndexError("refusing to generate a statically out-of-bounds"
+                             " array indexing")
         return '%s[%d]' % (baseexpr, index)
 
     ptr_access_expr = access_expr
 
+    def itemindex_access_expr(self, baseexpr, indexexpr):
+        return 'RPyFxItem(%s, %s, %d)' % (baseexpr, indexexpr,
+                                          self.FIXEDARRAY.length)
+
     def definition(self):
         return []    # no declaration is needed
 

Modified: pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/translator/c/src/support.h	Mon Aug 20 17:23:10 2007
@@ -25,6 +25,16 @@
 		memcpy(itemsarray->items, PyString_AS_STRING(s),        \
                        itemsarray->length)
 
+/* Extra checks can be enabled with the RPY_ASSERT or RPY_LL_ASSERT
+ * macros.  They differ in the level at which the tests are made.
+ * Remember that RPython lists, for example, are implemented as a
+ * GcStruct pointing to an over-allocated GcArray.  With RPY_ASSERT you
+ * get list index out of bound checks from rlist.py; such tests must be
+ * manually written so made we've forgotten a case.  Conversely, with
+ * RPY_LL_ASSERT, all GcArray indexing are checked, which is safer
+ * against attacks and segfaults - but less precise in the case of
+ * lists, because of the overallocated bit.
+ */
 #ifdef RPY_ASSERT
 #  define RPyAssert(x, msg)                                             \
      if (!(x)) RPyAssertFailed(__FILE__, __LINE__, __FUNCTION__, msg)
@@ -45,6 +55,31 @@
 #  define RPyAssert(x, msg)   /* nothing */
 #endif
 
+#ifdef RPY_LL_ASSERT
+/* obscure macros that can be used as expressions and lvalues to refer
+ * to a field of a structure or an item in an array in a "safe" way --
+ * they abort() in case of null pointer or out-of-bounds index.  As a
+ * speed trade-off, RPyItem actually segfaults if the array is null, but
+ * it's a "guaranteed" segfault and not one that can be used by
+ * attackers.
+ */
+#  define RPyCHECK(x)           ((x) || (abort(), 0))
+#  define RPyField(ptr, name)   ((RPyCHECK(ptr), (ptr))->name)
+#  define RPyItem(array, index)                                             \
+     ((RPyCHECK((index) >= 0 && (index) < (array)->length),                 \
+      (array))->items[index])
+#  define RPyFxItem(ptr, index, fixedsize)                                  \
+     ((RPyCHECK((ptr) && (index) >= 0 && (index) < (fixedsize)),            \
+      (ptr))[index])
+#  define RPyNLenItem(array, index)                                         \
+     ((RPyCHECK((array) && (index) >= 0), (array))->items[index])
+#else
+#  define RPyField(ptr, name)                ((ptr)->name)
+#  define RPyItem(array, index)              ((array)->items[index])
+#  define RPyFxItem(ptr, index, fixedsize)   ((ptr)[index])
+#  define RPyNLenItem(array, index)          ((array)->items[index])
+#endif
+
 #ifdef _RPyListOfString_New     /*  :-(  */
 #  define HAVE_RPY_LIST_OF_STRING
 #endif



More information about the Pypy-commit mailing list