You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Overflows happened silently in array.array setters for 'e', 'f' and 'Zf' format types #156865
>>> import array
>>> a = array.array('e', [123])
>>> a[0] =123456
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
a[0] = 123456
~^^^
OverflowError: float too large to pack with e format
>>> a = array.array('f', [123])
>>> a[0] =1e70# no OverflowError
>>> a
array('f', [inf])
>>> a = array.array('Zf', [123])
>>> a[0] =1e70j# no OverflowError
>>> a
array('Zf', [infj])
>>> import struct
>>> struct.pack('f', 1e70)
Traceback (most recent call last):
File "<python-input-7>", line 1, in <module>
struct.pack('f', 1e70)
~~~~~~~~~~~^^^^^^^^^^^
OverflowError: float too large to pack with f format
>>> struct.pack('>Zf', 1e70j)
Traceback (most recent call last):
File "<python-input-13>", line 1, in <module>
struct.pack('>Zf', 1e70j)
~~~~~~~~~~~^^^^^^^^^^^^^^
OverflowError: float too large to pack with f format
(BTW, f_setitem() suffers from same issue as #156864.)
Maybe it's a feature and array() should behave differently wrt the struct module. In either case, this behavior looks inconsistent. If we consider cases for 'f'/'Zf' types being correct - we should clear exceptions also for 'e' type code.
See also struct/array issues (merged to this per @vstinner suggestion):
changed the title [-]Overflows happen silently in array.array setters for 'f' and 'Zf' format types[/-][+]Overflows happened silently in array.array setters for 'f' and 'Zf' format types[/+]on Sep 3, 2026
This one is tricky. In the array module we raise OverflowError's for 'e' format type, but not for 'f'. In the struct - in both cases.
In the ctypes - overflows are silent, even for swapped types, except for the Zf type: the f_set_sw() also uses PyFloat_Pack4, but do first type-cast to float for PyFloat_AsDouble(value). Perhaps, behavior for the complex type is a bug, or vice-versa.
What should we do here? CC @encukou, CC @meadori (per experts index)
Edit:
Note, that floating-point types in ctypes raise OverflowError's, when integer value overflows double (this handled by PyFloat_AsDouble(), just like in the memoryview or the struct module, or by PyArg_Parse in the array module):
Python 3.16.0a0 (heads/main:ee68f5f46a1, Aug 12 2026, 11:19:39) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> ctypes.c_float(10**1000)
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
ctypes.c_float(10**1000)
~~~~~~~~~~~~~~^^^^^^^^^^
OverflowError: int too large to convert to float
In the memoryview, overflows also are silent for 'f' type:
>>> array.array('e', [10])
array('e', [10.0])
>>> m =memoryview(_)
>>> m[0] =123456.0# not overflows float or double
Traceback (most recent call last):
File "<python-input-7>", line 1, in <module>
m[0] = 123456.0
~^^^
ValueError: memoryview: invalid value for format 'e'
Note also, that exceptions raised for integer types in struct, array and memoryview, but not in the ctypes:
Python 3.16.0a0 (heads/main:ee68f5f46a1, Aug 12 2026, 11:19:39) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import array, ctypes, struct
>>> struct.pack('i', 10**100)
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
struct.pack('i', 10**100)
~~~~~~~~~~~^^^^^^^^^^^^^^
struct.error: 'i' format requires -2147483648 <= number <= 2147483647
>>> a = array.array('i', [0])
>>> m =memoryview(a)
>>> a[0] =10**100
Traceback (most recent call last):
File "<python-input-4>", line 1, in <module>
a[0] = 10**100
~^^^
OverflowError: Python int too large to convert to C long
>>> m[0] =10**100
Traceback (most recent call last):
File "<python-input-5>", line 1, in <module>
m[0] = 10**100
~^^^
ValueError: memoryview: invalid value for format 'i'
>>> ctypes.c_int(10**100) # just wraps
c_int(0)
The last one looks undocumented, but long-standing behavior of the ctypes module.
The evil plan is:
raise OverflowError's in struct/array/memoryview for floating-point types
be silent on overflows in the ctypes, except for conversions from ints to floating-point types (i.e. c_double(10**1000).
If that's OK, I'll open separate issues for memoryview and ctypes.
2026-09-03T08:11:26.876088000+0200 maurycy@gimel /Users/maurycy/src/github.com/maurycy/cpython (main c700121) % ./python.exe
Python 3.16.0a0 (heads/main:c700121b15c, Sep 3 2026, 08:11:05) [Clang 21.0.0 (clang-2100.1.1.101)] on darwin
Type "help", "copyright", "credits" or "license"for more information.
>>> import struct
>>> struct.pack('>Zf', 1e70j)
Traceback (most recent call last):
File "<python-input-1>", line 1, in<module>
struct.pack('>Zf', 1e70j)
~~~~~~~~~~~^^^^^^^^^^^^^^
OverflowError: float too large to pack with f format
>>> struct.pack('<Zf', 1e70j)
b'\x00\x00\x00\x00\x00\x00\x80\x7f'
>>>
Similarly:
2026-09-03T08:14:39.455948815+0200 maurycy@eiger /home/maurycy % python
Python 3.14.2 (main, Jan 14 2026, 19:38:07) [Clang 21.1.4 ] on linux
Type "help", "copyright", "credits" or "license"for more information.
>>> import struct
>>> struct.pack('>F', 1e70j)
Traceback (most recent call last):
File "<python-input-1>", line 1, in<module>
struct.pack('>F', 1e70j)
~~~~~~~~~~~^^^^^^^^^^^^^
OverflowError: float too large to pack with f format
>>> struct.pack('<F', 1e70j)
b'\x00\x00\x00\x00\x00\x00\x80\x7f'
>>>
This issue is similar to issues gh-156864 and gh-156867. I would prefer to merge the 3 issues to solve all issues at once. IMO we should chose a behavior and make sure that all struct/memoryview/array/ctypes functions respect this behavior.
The exception also depends on the byte order...
For example, IMO the behavior should not depend on the byte order :-) If we are able to detect underflow and overflow, we should raise an error for all byte orders.
About backports, I'm worried that changing the behavior can break an unknown number of projects, even if we consider that the current behavior is "wrong". If we change the behavior, I would suggest to only change Python 3.16 and not backport the changes. IMO it's too late to change Python 3.15 as well (release candidate 2 was just released).
changed the title [-]Overflows happened silently in array.array setters for 'f' and 'Zf' format types[/-][+]Overflows happened silently in array.array setters for 'e', 'f' and 'Zf' format types[/+]on Sep 3, 2026
If struct/memoryview/array/ctypes is modified to raise an exception instead of silently "truncating" the result of "+/-inf", would it be possible to provide a recipe to get the old behavior on new Python? It doesn't sound easy to do :-( I suppose that the recipe would have to replace float larger than the maximum with 'inf' and float smaller than the minimum with '-inf' before calling modified functions. Problem: we do not expose the minimum or maximum of binary16 and binary32.
If struct/memoryview/array/ctypes is modified to raise an exception instead of silently "truncating" the result of "+/-inf", would it be possible to provide a recipe to get the old behavior on new Python? It doesn't sound easy to do :-(
Yes, we don't have an equivalent of C type cast like
floatf= (float)(some_double)
(ctypes.cast is for pointers.)
Well, if we keep old behavior for ctypes - this will be available as ctypes.c_float(python_double).
Problem: we do not expose the minimum or maximum of binary16 and binary32.
This might be a problem for alternative interpreters. Not for CPython, as we require IEEE doubles (then highly likely that C floats are binary32 and so on).
I merged the 4 changes (array, struct, memoryview, ctypes). As I wrote previously, I prefer to not backport these changes to stable branches. I close the issue.
Activity
[-]Overflows happen silently in array.array setters for 'f' and 'Zf' format types[/-][+]Overflows happened silently in array.array setters for 'f' and 'Zf' format types[/+]skirpichev commentedon Sep 3, 2026
This one is tricky. In the array module we raise OverflowError's for 'e' format type, but not for 'f'. In the struct - in both cases.
In the ctypes - overflows are silent, even for swapped types, except for the
Zftype: thef_set_sw()also uses PyFloat_Pack4, but do first type-cast to float forPyFloat_AsDouble(value). Perhaps, behavior for the complex type is a bug, or vice-versa.What should we do here? CC @encukou, CC @meadori (per experts index)
Edit:
Note, that floating-point types in ctypes raise OverflowError's, when integer value overflows double (this handled by
PyFloat_AsDouble(), just like in the memoryview or the struct module, or by PyArg_Parse in the array module):In the memoryview, overflows also are silent for 'f' type:
But not for 'e':
skirpichev commentedon Sep 3, 2026
Note also, that exceptions raised for integer types in struct, array and memoryview, but not in the ctypes:
The last one looks undocumented, but long-standing behavior of the ctypes module.
The evil plan is:
c_double(10**1000).If that's OK, I'll open separate issues for memoryview and ctypes.
maurycy commentedon Sep 3, 2026
The exception also depends on the byte order...
Similarly:
This does not smell right to me:
cpython/Modules/_struct.c
Lines 793 to 800 in 39a9a47
vstinner commentedon Sep 3, 2026
This issue is similar to issues gh-156864 and gh-156867. I would prefer to merge the 3 issues to solve all issues at once. IMO we should chose a behavior and make sure that all struct/memoryview/array/ctypes functions respect this behavior.
For example, IMO the behavior should not depend on the byte order :-) If we are able to detect underflow and overflow, we should raise an error for all byte orders.
skirpichev commentedon Sep 3, 2026
Done.
This looks as even more evil plan than mine evil plan. Great!
It's hard to say, but there might be some code, that rely on silent overflows in the ctypes...
vstinner commentedon Sep 3, 2026
About backports, I'm worried that changing the behavior can break an unknown number of projects, even if we consider that the current behavior is "wrong". If we change the behavior, I would suggest to only change Python 3.16 and not backport the changes. IMO it's too late to change Python 3.15 as well (release candidate 2 was just released).
[-]Overflows happened silently in array.array setters for 'f' and 'Zf' format types[/-][+]Overflows happened silently in array.array setters for 'e', 'f' and 'Zf' format types[/+]vstinner commentedon Sep 3, 2026
If struct/memoryview/array/ctypes is modified to raise an exception instead of silently "truncating" the result of "+/-inf", would it be possible to provide a recipe to get the old behavior on new Python? It doesn't sound easy to do :-( I suppose that the recipe would have to replace float larger than the maximum with 'inf' and float smaller than the minimum with '-inf' before calling modified functions. Problem: we do not expose the minimum or maximum of binary16 and binary32.
skirpichev commentedon Sep 4, 2026
Yes, we don't have an equivalent of C type cast like
(
ctypes.castis for pointers.)Well, if we keep old behavior for ctypes - this will be available as
ctypes.c_float(python_double).This might be a problem for alternative interpreters. Not for CPython, as we require IEEE doubles (then highly likely that C floats are binary32 and so on).
gh-156865: Correctly detect overflows for array's "e", "f" and "Zf" t…
vstinner commentedon Sep 18, 2026
@encukou: Do you agree that ctypes should not write OverflowError?
encukou commentedon Sep 18, 2026
Yes,
ctypesshould emulate how C casts work on common platforms.gh-156865: Correctly handle float/complex overflows in memoryview (#1…
gh-156865: Don't raise exceptions for ctypes.c_float_complex overflows (
gh-156865: struct.pack() check for overflows for Zf type (#156868)
vstinner commentedon Sep 24, 2026
I merged the 4 changes (array, struct, memoryview, ctypes). As I wrote previously, I prefer to not backport these changes to stable branches. I close the issue.