[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