Serhiy Storchaka added the comment:

> So maybe the fix should be to special case zero in PyLong_AsVoidPtr, and
> turn 0L back into NULL there?

Yes, of course. If we have a special case in PyLong_FromVoidPtr(), it is wrong 
that we do not have the special case in PyLong_AsVoidPtr(). But this will 
change the current (potentially buggy) behaviour. ;-)

The patch long_fromvoidptr_2.patch contains such changes (as you want).

But this changes are buggy too, because now PyLong_FromVoidPtr() and 
PyLong_AsVoidPtr() are multivalued. PyLong_FromVoidPtr() maps to 0 NULL and 
may be yet another pointer, PyLong_AsVoidPtr() maps to NULL 0 and may be yet 
another integer.

The patch long_fromvoidptr_3.patch is more consistent in this sense. Now both 
functions are univalued, 

> I think it's just too risky to change the current behaviour in 3.2 and 3.3,
> given the number of places that PyLong_FromVoidPtr is used.  

Buggy behaviour changed if we fix the bug.

> Unlike you, I
> don't have confidence that there are no current or future platforms that
> don't map NULL to 0.

I just want to say that I'm not sure whether to fix this bug. But if we fix it 
for purity, it should be fixed right.

----------
Added file: http://bugs.python.org/file27611/long_fromvoidptr_2.patch
Added file: http://bugs.python.org/file27612/long_fromvoidptr_3.patch

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue16277>
_______________________________________
diff -r a45cb181e4d0 Objects/longobject.c
--- a/Objects/longobject.c      Wed Oct 17 20:29:07 2012 -0700
+++ b/Objects/longobject.c      Thu Oct 18 22:18:07 2012 +0300
@@ -935,17 +935,20 @@
 PyObject *
 PyLong_FromVoidPtr(void *p)
 {
+    /* special-case null pointer */
+    if (!p)
+        return PyLong_FromLong(0);
+#if SIZEOF_VOID_P <= SIZEOF_LONG
+    return PyLong_FromUnsignedLong((unsigned long)(Py_uintptr_t)p);
+#else
 #ifndef HAVE_LONG_LONG
 #   error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long"
 #endif
 #if SIZEOF_LONG_LONG < SIZEOF_VOID_P
 #   error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
 #endif
-    /* special-case null pointer */
-    if (!p)
-        return PyLong_FromLong(0);
     return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)(Py_uintptr_t)p);
-
+#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
 }
 
 /* Get a C pointer from a long int object. */
@@ -977,6 +980,9 @@
 
 #endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
 
+    /* special-case null pointer */
+    if (!x)
+        return NULL;
     if (x == -1 && PyErr_Occurred())
         return NULL;
     return (void *)x;
diff -r a45cb181e4d0 Objects/longobject.c
--- a/Objects/longobject.c      Wed Oct 17 20:29:07 2012 -0700
+++ b/Objects/longobject.c      Thu Oct 18 22:03:11 2012 +0300
@@ -935,17 +935,19 @@
 PyObject *
 PyLong_FromVoidPtr(void *p)
 {
+    /* always convert NULL to 0 */
+    Py_uintptr_t x = (Py_uintptr_t)p - (Py_uintptr_t)(void *)NULL;
+#if SIZEOF_VOID_P <= SIZEOF_LONG
+    return PyLong_FromUnsignedLong((unsigned long)x);
+#else
 #ifndef HAVE_LONG_LONG
 #   error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long"
 #endif
 #if SIZEOF_LONG_LONG < SIZEOF_VOID_P
 #   error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
 #endif
-    /* special-case null pointer */
-    if (!p)
-        return PyLong_FromLong(0);
-    return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)(Py_uintptr_t)p);
-
+    return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)x);
+#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
 }
 
 /* Get a C pointer from a long int object. */
@@ -979,7 +981,8 @@
 
     if (x == -1 && PyErr_Occurred())
         return NULL;
-    return (void *)x;
+    /* always convert 0 to NULL */
+    return (void *)((Py_uintptr_t)x + (Py_uintptr_t)(void *)NULL);
 }
 
 #ifdef HAVE_LONG_LONG
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to