[New-bugs-announce] [issue31637] integer overflow in the size of a ctypes.Array

Oren Milman report at bugs.python.org
Fri Sep 29 06:39:58 EDT 2017

New submission from Oren Milman <orenmn at gmail.com>:

The following code:
from ctypes import *
from _testcapi import PY_SSIZE_T_MAX, LONG_MAX

if LONG_MAX == PY_SSIZE_T_MAX == (1 << 31) - 1:
    class MyArray(Array):
        _type_ = c_longlong
        _length_ = 1 << 29

    arr = MyArray()
    for i in range(3):
        arr[i] = i
    for i in range(3):

Produces this output (on a 32bit Python on my Windows 10):

This is because PyCArrayType_new() (in Modules/_ctypes/_ctypes.c) raises a
"array too large" error in case (length * itemsize < 0). However, this
multiplication might also overflow to a non-negative number, e.g. to zero in
the code above.
PyCArrayType_new() then does:
    stgdict->size = itemsize * length;

Array_ass_item() and Array_item() both do:
    size = stgdict->size / stgdict->length;
    offset = index * size;

So in the above code, the integer overflow caused the array to collapse to a
single element (the first element).

ISTM that we can fix this by changing the overflow detection logic to this:
    assert(itemsize >= 0 && length >= 0);
    array_size = itemsize * length;
    if (itemsize && array_size / itemsize != length) {
                        "array too large");
        goto error;

The assertion is guaranteed to be true after #29843 is resolved. (I would open
a PR for #29843 soon.)

components: ctypes
messages: 303322
nosy: Oren Milman
priority: normal
severity: normal
status: open
title: integer overflow in the size of a ctypes.Array
type: behavior
versions: Python 3.7

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list