Integer overflow with large ranges
Port, board and/or hardware
unix port, ci unix_sanitize_undefined_build
MicroPython version
MicroPython v1.27.0-preview.208.gadf6319884 on 2025-09-26; linux [GCC 14.2.0] version
Reproduction
Run the following snippet: import sys; print(range(sys.maxsize)[0])
Expected behaviour
No UBsan diagnostics; the number 0 is printed
Observed behaviour
The following diagnostics are produced:
../../py/objrange.c:115:14: runtime error: signed integer overflow: 9223372036854775807 + 1 cannot be represented in type 'long int'
../../py/objrange.c:117:13: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long int'
Additional Information
This is related to the cpydiff documented at https://docs.micropython.org/en/latest/genrst/builtin_types.html#range
There are other misbehaving combinations. For instance, here's one with a step that erroneously produces an empty range:
print(range(0, sys.maxsize, sys.maxsize//2)[-1])
but they all seem to stem from signed integer overflows on those two lines (plus line 119 for negative steps)
113 static mp_int_t range_len(mp_obj_range_t *self) {
114 // When computing length, need to take into account step!=1 and step
<0.
115 mp_int_t len = self->stop - self->start + self->step;
116 if (self->step > 0) {
117 len -= 1;
118 } else {
119 len += 1;
120 }
Code of Conduct
Yes, I agree
range() returns wrong results across 1<<31
Port, board and/or hardware
68k private port. rp2 version 1.21, js version on micropython homepage.
MicroPython version
Whatever the JS on the micropython homepage uses ?
Reproduction
Running:
for i in range(0x3c000000, 0x44000000, 0x04000000):
print("A %x" % i)
b = list(range(0x3c000000, 0x44000000, 0x04000000))
for i in b:
print("B %x" % i)
Produces:
A 3c000000
A 40000000
B 3c000000
B -40000000
Expected behaviour
Same output for both sides of the example.
Observed behaviour
See example above.
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree