printing to io.StringIO subclass leads to seg fault
I'm aware that MicroPython io documentation says
Note that for efficiency, MicroPython doesn’t provide abstract base classes corresponding to the hierarchy above, and it’s not possible to implement, or subclass, a stream class in pure Python.
Minimal example to reproduce test_stream.py:
import io
class TestStream(io.StringIO):
def __init_(self, alloc_size):
super().__init__(alloc_size)
test = TestStream(100)
print("Now the seg fault...")
print("hello", file=test)
$ micropython test_stream.py
Now the seg fault...
Segmentation fault: 11
But I would expect an Exception if this is not possible not a crash/seg fault.
I was able to reproduce this in unix(MacOS) and stm32(pybV1.1) ports.
Maybe is related to #1067?
I had a look at py/mpprint.c but I cannot see any hint... Is there any tool to debug these types of crashes?
This is the valgrind output:
==20210== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20210== Using Valgrind-3.19.0.GIT-lbmacos and LibVEX; rerun with -h for copyright info
==20210== Command: micropython test_stream.py
==20210==
==20210== Warning: set address range perms: large range [0x7fff201b6000, 0x80001ffb6000) (defined)
==20210== Warning: set address range perms: large range [0x7fff201b6000, 0x7fff7fb4a000) (defined)
==20210== Warning: set address range perms: large range [0x7fff8e41a000, 0x7fffc01b6000) (noaccess)
==20210== Warning: set address range perms: large range [0x7fffc01b6000, 0x7fffe307a000) (defined)
==20210== Warning: set address range perms: large range [0x7fffe307a000, 0x7fffffe00000) (noaccess)
Now the seg fault...
==20210== Invalid read of size 1
==20210== at 0x10002C057: ??? (in /usr/local/bin/micropython)
==20210== by 0x10002E711: ??? (in /usr/local/bin/micropython)
==20210== by 0x10002E7DB: ??? (in /usr/local/bin/micropython)
==20210== by 0x10002BB4F: ??? (in /usr/local/bin/micropython)
==20210== by 0x100030D6F: ??? (in /usr/local/bin/micropython)
==20210== by 0x100023DF5: ??? (in /usr/local/bin/micropython)
==20210== by 0x100034D18: ??? (in /usr/local/bin/micropython)
==20210== by 0x100023FDE: ??? (in /usr/local/bin/micropython)
==20210== by 0x100078425: machine_time_pulse_us (in /usr/local/bin/micropython)
==20210== by 0x100077DD4: machine_time_pulse_us (in /usr/local/bin/micropython)
==20210== by 0x7FFF204DFF3C: ??? (in /dev/ttys016)
==20210== by 0x1: ???
==20210== Address 0x19 is not stack'd, malloc'd or (recently) free'd
==20210==
==20210==
==20210== Process terminating with default action of signal 11 (SIGSEGV)
==20210== Access not within mapped region at address 0x19
==20210== at 0x10002C057: ??? (in /usr/local/bin/micropython)
==20210== by 0x10002E711: ??? (in /usr/local/bin/micropython)
==20210== by 0x10002E7DB: ??? (in /usr/local/bin/micropython)
==20210== by 0x10002BB4F: ??? (in /usr/local/bin/micropython)
==20210== by 0x100030D6F: ??? (in /usr/local/bin/micropython)
==20210== by 0x100023DF5: ??? (in /usr/local/bin/micropython)
==20210== by 0x100034D18: ??? (in /usr/local/bin/micropython)
==20210== by 0x100023FDE: ??? (in /usr/local/bin/micropython)
==20210== by 0x100078425: machine_time_pulse_us (in /usr/local/bin/micropython)
==20210== by 0x100077DD4: machine_time_pulse_us (in /usr/local/bin/micropython)
==20210== by 0x7FFF204DFF3C: ??? (in /dev/ttys016)
==20210== by 0x1: ???
==20210== If you believe this happened as a result of a stack
==20210== overflow in your program's main thread (unlikely but
==20210== possible), you can try to increase the size of the
==20210== main thread stack using the --main-stacksize= flag.
==20210== The main thread stack size used in this run was 8388608.
==20210==
==20210== HEAP SUMMARY:
==20210== in use at exit: 0 bytes in 0 blocks
==20210== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==20210==
==20210== All heap blocks were freed -- no leaks are possible
==20210==
==20210== For lists of detected and suppressed errors, rerun with: -s
==20210== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault: 11
Not sure if this helps...
py/objstringio.c: Fix segfault in stringio_write.
Fixes issue #10402:
printing to io.StringIO subclass leads to seg fault. The reason is that stringio_write function does not check o type.
This checks for proper type and raises TypeError if it isn't.