array: frombytes() Skips the Overflow Validation Every Other Entry Point Enforces (tested)
array.array('b', ...) is supposed to only ever hold values that fit the type code's range -- for 'b' (signed byte) that's -128 to 127. We measured whether that guarantee actually holds across every way you can put data into an array, including the byte-oriented ones.
1. Every integer-based entry point rejects an out-of-range value
import array
a = array.array('b') # signed byte: -128..127
try:
a.append(200)
except OverflowError as e:
print("append:", e)
try:
a.extend([200])
except OverflowError as e:
print("extend:", e)
try:
a.fromlist([200])
except OverflowError as e:
print("fromlist:", e)
try:
array.array('b', [200])
except OverflowError as e:
print("constructor from list:", e)
append: signed char is greater than maximum
extend: signed char is greater than maximum
fromlist: signed char is greater than maximum
constructor from list: signed char is greater than maximum
Measured: all four ways of handing array a Python int -- append(), extend(), fromlist(), and building the array directly from a list -- raise the same OverflowError the moment a value is outside the type code's range. 200 doesn't fit in a signed byte, and none of these let it through.
2. frombytes() and the bytes constructor take the same 200 with no error
import array
b = array.array('b', bytes([200]))
print(b, b[0])
c = array.array('b', [1, 2, 3])
c.frombytes(bytes([200]))
print(c)
array('b', [-56]) -56
array('b', [1, 2, 3, -56])
Measured: both the bytes constructor and the frombytes() method accept the same byte value 200 with no exception at all. There's no range check here because there's nothing to check against -- a raw byte is just reinterpreted as whatever the type code says, so 200 (which doesn't fit as a non-negative signed byte) silently becomes its two's-complement equivalent, -56.
3. The same raw byte means a different value depending on the type code -- also with no warning
import array
signed = array.array('b', bytes([200]))
unsigned = array.array('B', bytes([200]))
print("signed 'b': ", signed[0])
print("unsigned 'B':", unsigned[0])
signed 'b': -56
unsigned 'B': 200
Measured: the exact same input byte, 200, decodes to -56 under the signed type code and 200 under the unsigned one -- both calls succeed, neither raises, and nothing signals that the interpretation depends entirely on which type code you picked. If you load untrusted or corrupted binary data with frombytes() expecting the same safety net append() gives you, there isn't one: bad data just becomes a different, silently wrong number.
Frequently asked questions
Does array.array validate integer ranges the same way for every method?
No -- we measured append(), extend(), fromlist(), and the list-based constructor all raising OverflowError on an out-of-range int like 200 for a signed-byte ('b') array, while frombytes() and the bytes-based constructor accepted the same value with no error at all.
What happens when you load an out-of-range byte value with array.frombytes()?
It's silently reinterpreted via two's-complement wraparound, not rejected -- we measured byte value 200 becoming -56 once loaded into a signed-byte ('b') array through frombytes(), with no exception raised.
Why does array.array('b', bytes([200])) not raise OverflowError like array.array('b', [200]) does?
Because the bytes constructor and frombytes() just reinterpret raw bytes according to the type code's binary layout -- there's no Python int being range-checked, so the normal OverflowError path never runs. We measured both forms taking 200 silently, one via two's-complement decoding.
Is it safe to use array.frombytes() on untrusted binary data?
Not for catching out-of-range values -- we measured it accepting any byte pattern without validation, unlike append()/extend()/fromlist(), which reject values that don't fit the array's type code. Validate the source or type code choice separately if that matters.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in array module: compared range validation across append(), extend(), fromlist(), the iterable constructor, frombytes(), and the bytes constructor on a signed-byte ('b') array. PlainHeaders is our extension; Python's array module is built in.