Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit