This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: bug fix: ctypes truncates 64-bit pointers
Type: Stage:
Components: Interpreter Core Versions:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: theller Nosy List: belopolsky, nnorwitz, theller
Priority: normal Keywords: patch

Created on 2007-04-18 22:09 by belopolsky, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
_ctypes-callproc.patch belopolsky, 2007-04-18 22:09 diff against revision 54869
_ctypes-callproc-1.patch belopolsky, 2007-04-20 21:07
_ctypes-callproc-2.patch theller, 2007-05-03 19:42
Messages (9)
msg52450 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2007-04-18 22:09
At several places _ctypes module converts a python integer to a void* pointer by first extracting an argument into an int.  Attached patch changes int to Py_ssize_t that is guaranteed to be wide enough to hold a pointer. 
msg52451 - (view) Author: Neal Norwitz (nnorwitz) * (Python committer) Date: 2007-04-19 05:56
Thanks for the patch.  The changes look correct, however, can you create a test for these cases?
msg52452 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2007-04-19 06:44
Here are (failing) test cases:

Python 2.5 (r25:51908, Oct  4 2006, 18:25:28) 
[GCC 3.4.4 20050721 (Red Hat 3.4.4-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> dlopen('libc.so.6')
182896775816
>>> dlclose(_)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: signed integer is greater than maximum
>>> dlsym(_, 'printf')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: signed integer is greater than maximum
>>> call_function(_, ()) # pretend that _ is a function pointer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: signed integer is greater than maximum
>>> call_cdeclfunction(_, ()) # pretend that _ is a function pointer
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: signed integer is greater than maximum


With the patch:

>>> from _ctypes import *
>>> dlopen('libc.so.6')
182894214624
>>> dlclose(_)

I don't know how to meaningfully exercise call_function and call_cdeclfunction to trigger the bug because in the default (small memory) model on AMD64 function pointers always fit into 32 bits.  Maybe a pseudo-function pointer created by an ffi callback can be used for this purpose.

I am not sure where these test belong in the testsuit.  Maybe in ctypes/test/test_loading.py? 



msg52453 - (view) Author: Neal Norwitz (nnorwitz) * (Python committer) Date: 2007-04-19 06:49
Thomas would be the best person to answer you question about where it should go.  Maybe he has some other ideas how to test this.
msg52454 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2007-04-20 19:33
The patch is only correct for Python2.5 and later, earlier Python versions don't have the Py_ssize_t type (or, when it's defined, it has still the same size as int in these versions).  Unfortunately the 'n' typecode also isn't available in these versions.

Also the patch has to be extended for Windows, the LoadLibrary function has the same problem.

Would you like to extend this patch (for Windows, I can do it myself later)?
msg52455 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2007-04-20 21:07
I think you meant FreeLibrary function.  LoadLibrary seems ok.

I am attaching a new patch that should be pre-2.5 compatible and which extends to FreeLibrary.  I don't have access to windows, so please check/test that it works.
File Added: _ctypes-callproc-1.patch
msg52456 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2007-05-03 19:42
IMO the patch is still incorrect.  Py_ssize_t cannot be used since sizeof(Py_ssize_t) != sizeof(void *) in older Python versions.  Also, the 'n' typecode cannot be used in PyArg_Parse for the same reason.

I attach _ctypes-callproc-2.patch, which demonstrates one approach that I think should work.  If you can verify that it works I'll apply it.

I am not sure it is possible to write really cross-platform test cases.
File Added: _ctypes-callproc-2.patch
msg52457 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2007-05-04 19:59
Fixed in SVN trunk revisions 55129/55131.  I will backport the patch to the release25-maint branch later.

belopolsky, thanks for your efforts - I hope the changes work for you.
msg52458 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2007-06-08 19:41
The fix has been backported to the release25-maint branch as SVN rev. 55836.
History
Date User Action Args
2022-04-11 14:56:23adminsetgithub: 44864
2007-04-18 22:09:31belopolskycreate