-
Notifications
You must be signed in to change notification settings - Fork 107
Python ctypes not checking for overflow
-
Affected Components : ctypes
-
Operating System : Linux
-
Python Versions : 2.6.x, 2.7.x, 3.1.x, 3.2.x
-
Reproducible : Yes
import ctypes
#32-bit test with max 32bit integer 2147483647
ctypes.c_char * int(2147483647)
#32-bit test with max 32bit integer 2147483647 + 1
ctypes.c_char * int(2147483648)
#64-bit test with max 64bit integer 9223372036854775807
ctypes.c_char * int(9223372036854775807)
#64-bit test with max 64bit integer 9223372036854775807 + 1
ctypes.c_char * int(9223372036854775808)
To reproduce the problem copy the source code
in a file and execute the script using the following command syntax:
$ python -OOBRtt test.py
Alternatively you can open python in interactive mode:
$ python -OOBRtt <press enter>
Then copy the lines of code into the interpreter.
Overflow message:
OverflowError: cannot fit 'long' into an index-sized integer
Python ctypes call |
32bit | 32bit + 1 | 64bit | 64bit + 1 |
---|---|---|---|---|
.c_byte * int(x) |
PASS | Overflow | PASS | Overflow |
.c_char * int(x) |
PASS | Overflow | PASS | Overflow |
.c_char_p * int(x) |
PASS | Overflow | PASS | Overflow |
.c_double * int(x) |
PASS | Overflow | PASS | Overflow |
.c_longdouble * int(x) |
PASS | Overflow | PASS | Overflow |
.c_float * int(x) |
PASS | Overflow | PASS | Overflow |
.c_int * int(x) |
PASS | Overflow | PASS | Overflow |
.c_long * int(x) |
PASS | Overflow | PASS | Overflow |
.c_longdouble * int(x) |
PASS | Overflow | PASS | Overflow |
.c_longlong * int(x) |
PASS | Overflow | PASS | Overflow |
.c_short * int(x) |
PASS | Overflow | PASS | Overflow |
.c_wchar_p * int(x) |
PASS | Overflow | PASS | Overflow |
.c_void_p * int(x) |
PASS | Overflow | PASS | Overflow |
Example of overflow message in a 32bit system:
>>> ctypes.c_char * int(2147483648)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'long' into an index-sized integer
Example of overflow message in a 64bit system:
>>> ctypes.c_char * int(9223372036854775808)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: cannot fit 'long' into an index-sized integer
This behaviour is described in the official [documentation][02] in most of the details regarding fundamentals ctypes data types with the phrase:
no overflow checking is done.
Also to note that some types are just aliases as in the case of c_int
and c_long
.
Note: Some code samples reference the ctypes c_int type. This type is an alias for the c_long type on 32-bit systems. So, you should not be confused if c_long is printed if you would expect c_int — they are actually the same type.
Due to the fact that ctypes are not limited to size of memory and overflow checks are missing, developers should pay extreme attention to this condition when using ctypes
.
We are not aware on any easy solution other than trying to avoid using ctypes for cases like the one examined.
[Python ctypes][01] [01]:https://docs.python.org/2/library/ctypes.html
[Python bug 16865][02] [02]:http://bugs.python.org/issue16865
Main site: pythonsecurity.org
OWASP Page: owasp.org/index.php/OWASP_Python_Security_Project