Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r2737:763505916552
Date: 2016-08-15 11:03 +0200
http://bitbucket.org/cffi/cffi/changeset/763505916552/

Log:    Give an error when subtracting two pointers and the division's
        result is not exact (in gcc, we get nonsense, so it means it is
        undefined behavior for C, which is best handled by raising in cffi)

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2355,8 +2355,16 @@
             return NULL;
         }
         itemsize = ct->ct_itemdescr->ct_size;
-        if (itemsize <= 0) itemsize = 1;
-        diff = (cdv->c_data - cdw->c_data) / itemsize;
+        diff = cdv->c_data - cdw->c_data;
+        if (itemsize > 1) {
+            if (diff % itemsize) {
+                PyErr_SetString(PyExc_ValueError,
+                     "pointer subtraction: the distance between the two "
+                     "pointers is not a multiple of the item size");
+                return NULL;
+            }
+            diff = diff / itemsize;
+        }
 #if PY_MAJOR_VERSION < 3
         return PyInt_FromSsize_t(diff);
 #else
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -587,6 +587,19 @@
     e = py.test.raises(TypeError, "q - a")
     assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
 
+def test_ptr_sub_unaligned():
+    BInt = new_primitive_type("int")
+    BIntPtr = new_pointer_type(BInt)
+    a = cast(BIntPtr, 1240)
+    for bi in range(1430, 1438):
+        b = cast(BIntPtr, bi)
+        if ((bi - 1240) % size_of_int()) == 0:
+            assert b - a == (bi - 1240) // size_of_int()
+            assert a - b == (1240 - bi) // size_of_int()
+        else:
+            py.test.raises(ValueError, "b - a")
+            py.test.raises(ValueError, "a - b")
+
 def test_cast_primitive_from_cdata():
     p = new_primitive_type("int")
     n = cast(p, cast(p, -42))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to