Commits

Armin Rigo committed 15cf69c

More tests, small fixes

Comments (0)

Files changed (2)

c/_cffi_backend.c

 {
     Py_ssize_t start, stop;
     CDataObject_own_length *scd;
-    CTypeDescrObject *ct = cd->c_type;
-
-    if (!(ct->ct_flags & (CT_ARRAY | CT_POINTER))) {
-        PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
-                     ct->ct_name);
-        return NULL;
-    }
+    CTypeDescrObject *ct;
+
     start = PyInt_AsSsize_t(slice->start);
     if (start == -1 && PyErr_Occurred()) {
         if (slice->start == Py_None)
         return NULL;
     }
 
-    if (ct->ct_flags & CT_ARRAY)
+    ct = cd->c_type;
+    if (ct->ct_flags & CT_ARRAY) {
+        if (start < 0) {
+            PyErr_SetString(PyExc_IndexError,
+                            "negative index not supported");
+            return NULL;
+        }
+        if (stop >= get_array_length(cd)) {
+            PyErr_Format(PyExc_IndexError,
+                         "index too large for cdata '%s' (expected %zd < %zd)",
+                         cd->c_type->ct_name,
+                         stop, get_array_length(cd));
+            return NULL;
+        }
         ct = (CTypeDescrObject *)ct->ct_stuff;
-    assert(ct->ct_flags & CT_POINTER);
+    }
+    else if (!(ct->ct_flags & CT_POINTER)) {
+        PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
+                     ct->ct_name);
+        return NULL;
+    }
+
     if (ct->ct_stuff == NULL) {
         ct->ct_stuff = new_array_type(ct, Py_None);
         if (ct->ct_stuff == NULL)
     d[2] = 456
     assert c[1] == 123
     assert c[3] == 456
+    assert d[2] == 456
     py.test.raises(IndexError, "d[3]")
     py.test.raises(IndexError, "d[-1]")
+
+def test_slice_ptr():
+    BIntP = new_pointer_type(new_primitive_type("int"))
+    BIntArray = new_array_type(BIntP, None)
+    c = newp(BIntArray, 5)
+    d = (c+1)[0:2]
+    assert len(d) == 2
+    assert repr(d) == "<cdata 'int[]' sliced length 2>"
+    d[1] += 50
+    assert c[2] == 50
+
+def test_slice_array_checkbounds():
+    BIntP = new_pointer_type(new_primitive_type("int"))
+    BIntArray = new_array_type(BIntP, None)
+    c = newp(BIntArray, 5)
+    py.test.raises(IndexError, "c[-1:1]")
+    cp = c + 0
+    cp[-1:1]