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