Author: Armin Rigo <[email protected]>
Branch:
Changeset: r95041:beeebc0b35f3
Date: 2018-08-30 12:17 +0200
http://bitbucket.org/pypy/pypy/changeset/beeebc0b35f3/
Log: Test and fix: can get a segfault instead of an IndexError "too many
initializers"
diff --git a/pypy/module/_cffi_backend/ctypeobj.py
b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -51,9 +51,12 @@
def unpack_list_of_float_items(self, ptr, length):
return None
- def pack_list_of_items(self, cdata, w_ob):
+ def pack_list_of_items(self, cdata, w_ob, expected_length):
return False
+ def _within_bounds(self, actual_length, expected_length):
+ return expected_length < 0 or actual_length <= expected_length
+
def newp(self, w_init, allocator):
space = self.space
raise oefmt(space.w_TypeError,
diff --git a/pypy/module/_cffi_backend/ctypeprim.py
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -292,9 +292,10 @@
return res
return None
- def pack_list_of_items(self, cdata, w_ob):
+ def pack_list_of_items(self, cdata, w_ob, expected_length):
int_list = self.space.listview_int(w_ob)
- if int_list is not None:
+ if (int_list is not None and
+ self._within_bounds(len(int_list), expected_length)):
if self.size == rffi.sizeof(rffi.LONG): # fastest path
from rpython.rlib.rrawarray import copy_list_to_raw_array
cdata = rffi.cast(rffi.LONGP, cdata)
@@ -305,7 +306,8 @@
if overflowed != 0:
self._overflow(self.space.newint(overflowed))
return True
- return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+ return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
+ expected_length)
class W_CTypePrimitiveUnsigned(W_CTypePrimitive):
@@ -375,15 +377,17 @@
return res
return None
- def pack_list_of_items(self, cdata, w_ob):
+ def pack_list_of_items(self, cdata, w_ob, expected_length):
int_list = self.space.listview_int(w_ob)
- if int_list is not None:
+ if (int_list is not None and
+ self._within_bounds(len(int_list), expected_length)):
overflowed = misc.pack_list_to_raw_array_bounds_unsigned(
int_list, cdata, self.size, self.vrangemax)
if overflowed != 0:
self._overflow(self.space.newint(overflowed))
return True
- return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+ return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
+ expected_length)
class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned):
@@ -471,9 +475,10 @@
return res
return None
- def pack_list_of_items(self, cdata, w_ob):
+ def pack_list_of_items(self, cdata, w_ob, expected_length):
float_list = self.space.listview_float(w_ob)
- if float_list is not None:
+ if (float_list is not None and
+ self._within_bounds(len(float_list), expected_length)):
if self.size == rffi.sizeof(rffi.DOUBLE): # fastest path
from rpython.rlib.rrawarray import copy_list_to_raw_array
cdata = rffi.cast(rffi.DOUBLEP, cdata)
@@ -483,7 +488,8 @@
misc.pack_float_list_to_raw_array(float_list, cdata,
rffi.FLOAT, rffi.FLOATP)
return True
- return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+ return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
+ expected_length)
def unpack_ptr(self, w_ctypeptr, ptr, length):
result = self.unpack_list_of_float_items(ptr, length)
@@ -553,13 +559,15 @@
# 'list(array-of-longdouble)' returns a list of cdata objects,
# not a list of floats.
- def pack_list_of_items(self, cdata, w_ob):
+ def pack_list_of_items(self, cdata, w_ob, expected_length):
float_list = self.space.listview_float(w_ob)
- if float_list is not None:
+ if (float_list is not None and
+ self._within_bounds(len(float_list), expected_length)):
misc.pack_float_list_to_raw_array(float_list, cdata,
rffi.LONGDOUBLE, rffi.LONGDOUBLEP)
return True
- return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob)
+ return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob,
+ expected_length)
@jit.dont_look_inside
def nonzero(self, cdata):
diff --git a/pypy/module/_cffi_backend/ctypeptr.py
b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -56,7 +56,7 @@
def _convert_array_from_listview(self, cdata, lst_w):
space = self.space
- if self.length >= 0 and len(lst_w) > self.length:
+ if not self._within_bounds(len(lst_w), self.length):
raise oefmt(space.w_IndexError,
"too many initializers for '%s' (got %d)",
self.name, len(lst_w))
@@ -69,8 +69,8 @@
space = self.space
if (space.isinstance_w(w_ob, space.w_list) or
space.isinstance_w(w_ob, space.w_tuple)):
- if self.ctitem.pack_list_of_items(cdata, w_ob): # fast path
- pass
+ if self.ctitem.pack_list_of_items(cdata, w_ob, self.length):
+ pass # fast path
else:
self._convert_array_from_listview(cdata, space.listview(w_ob))
elif self.accept_str:
diff --git a/pypy/module/_cffi_backend/test/test_fastpath.py
b/pypy/module/_cffi_backend/test/test_fastpath.py
--- a/pypy/module/_cffi_backend/test/test_fastpath.py
+++ b/pypy/module/_cffi_backend/test/test_fastpath.py
@@ -267,3 +267,9 @@
assert lst == [1.25, -2.5, 3.75]
if not self.runappdirect:
assert self.get_count() == 1
+
+ def test_too_many_initializers(self):
+ import _cffi_backend
+ ffi = _cffi_backend.FFI()
+ raises(IndexError, ffi.new, "int[4]", [10, 20, 30, 40, 50])
+ raises(IndexError, ffi.new, "int[4]", tuple(range(999)))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit