summaryrefslogtreecommitdiffstats
path: root/libpython.py
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2010-02-18 23:31:02 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2010-02-18 23:31:02 -0500
commite5826809d4b1bf545a41070caad23a013ce7817e (patch)
tree2f243b22726f9ec2d5a33139f8a2e560a01397e3 /libpython.py
parent36a517ef7848cbd0b3dcc7371f32e47ac4c87eba (diff)
downloadlibpython-e5826809d4b1bf545a41070caad23a013ce7817e.tar.gz
libpython-e5826809d4b1bf545a41070caad23a013ce7817e.tar.xz
libpython-e5826809d4b1bf545a41070caad23a013ce7817e.zip
Introduce safety_limit and safe_range to protect against corrupt integer values; handle corrupt ob_type pointers
Diffstat (limited to 'libpython.py')
-rw-r--r--libpython.py26
1 files changed, 20 insertions, 6 deletions
diff --git a/libpython.py b/libpython.py
index afb9869..8af75f5 100644
--- a/libpython.py
+++ b/libpython.py
@@ -52,6 +52,17 @@ import gdb
class NullPyObjectPtr(RuntimeError):
pass
+def safety_limit(val):
+ # Given a integer value from the process being debugged, limit it to some
+ # safety threshold so that arbitrary breakage within said process doesn't
+ # break the gdb process too much (e.g. sizes of iterations, sizes of lists)
+ return min(val, 100)
+
+def safe_range(val):
+ # As per range, but don't trust the value too much: cap it to a safety
+ # threshold in case the data was corrupted
+ return xrange(safety_limit(val))
+
def is_py3k():
# This code assumes that a libpython's DWARF data has actually been
# loaded by the point that this function is called
@@ -150,6 +161,9 @@ class PyObjectPtr(object):
except NullPyObjectPtr:
# NULL tp_name?
tp_name = 'unknown'
+ except RuntimeError:
+ # Can't even read the object at all?
+ tp_name = 'unknown'
return FakeRepr(tp_name,
long(self._gdbval))
@@ -238,7 +252,7 @@ class PyDictObjectPtr(PyObjectPtr):
def proxyval(self):
result = {}
- for i in xrange(self.field('ma_mask')):
+ for i in safe_range(self.field('ma_mask')):
ep = self.field('ma_table') + i
pvalue = PyObjectPtr.from_pyobject_ptr(ep['me_value'])
if not pvalue.is_null():
@@ -285,7 +299,7 @@ class PyListObjectPtr(PyObjectPtr):
def proxyval(self):
result = [PyObjectPtr.from_pyobject_ptr(self[i]).proxyval()
- for i in range(int_from_int(self.field('ob_size')))]
+ for i in safe_range(int_from_int(self.field('ob_size')))]
return result
class PyLongObjectPtr(PyObjectPtr):
@@ -321,7 +335,7 @@ class PyLongObjectPtr(PyObjectPtr):
# FIXME: I haven't yet tested this case
SHIFT = 30L
- digits = [long(ob_digit[i]) * 2**(SHIFT*i) for i in xrange(abs(ob_size))]
+ digits = [long(ob_digit[i]) * 2**(SHIFT*i) for i in safe_range(abs(ob_size))]
result = sum(digits)
if ob_size < 0:
result = -result
@@ -357,7 +371,7 @@ class PyTupleObjectPtr(PyObjectPtr):
def proxyval(self):
result = tuple([PyObjectPtr.from_pyobject_ptr(self[i]).proxyval()
- for i in range(int_from_int(self.field('ob_size')))])
+ for i in safe_range(int_from_int(self.field('ob_size')))])
return result
class PyTypeObjectPtr(PyObjectPtr):
@@ -375,7 +389,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
# Gather a list of ints from the Py_UNICODE array; these are either
# UCS-2 or UCS-4 code points:
- Py_UNICODEs = [int(field_str[i]) for i in xrange(field_length)]
+ Py_UNICODEs = [int(field_str[i]) for i in safe_range(field_length)]
# Convert the int code points to unicode characters, and generate a
# local unicode instance:
@@ -409,7 +423,7 @@ class FrameInfo:
self.co_varnames = PyTupleObjectPtr.from_pyobject_ptr(self.co.field('co_varnames'))
self.locals = [] # list of kv pairs
f_localsplus = self.fval.field('f_localsplus')
- for i in xrange(min(self.co_nlocals, 200)): # arbitrary upper sanity limit in case co_nlocals is corrupt
+ for i in safe_range(self.co_nlocals):
#print 'i=%i' % i
value = PyObjectPtr.from_pyobject_ptr(f_localsplus[i])
if not value.is_null():