-
-
Notifications
You must be signed in to change notification settings - Fork 8.4k
Description
Port, board and/or hardware
unix port, coverage variant w/address sanitizer, x86_64 linux
MicroPython version
MicroPython v1.26.0-preview.524.g255d74b5a8 on 2025-08-06; linux [GCC 12.2.0] version
Reproduction
Build with . tools/ci.sh; ci_unix_sanitize_address_build
. Then, run the following code (I did it at the repl):
>>> import machine
>>> import ssl
>>> ctx = ssl.SSLContext(1)
>>> p = machine.PinBase()
>>> ctx.wrap_socket(p)
Expected behaviour
ctx.wrap_socket
should raise an exception, because a PinBase does not implement the stream protocol. For instance, ctx.wrap_socket(1)
throws OSError: stream operation not supported
.
Observed behaviour
>>> ctx.wrap_socket(p)
=================================================================
==2165677==ERROR: AddressSanitizer: global-buffer-overflow on address 0x5585c4169a28 at pc 0x5585c3f6a4fb bp 0x7ffe114fe930 sp 0x7ffe114fe928
READ of size 8 at 0x5585c4169a28 thread T0
#0 0x5585c3f6a4fa in mp_get_stream_raise ../../py/stream.c:102
#1 0x5585c3fb01cc in ssl_socket_make_new ../../extmod/modtls_mbedtls.c:623
#2 0x5585c3fb0a30 in ssl_context_wrap_socket ../../extmod/modtls_mbedtls.c:519
#3 0x5585c3f3c338 in fun_builtin_var_call ../../py/objfun.c:118
#4 0x5585c3f1c0d8 in mp_call_function_n_kw ../../py/runtime.c:727
#5 0x5585c3f1ca56 in mp_call_method_n_kw ../../py/runtime.c:743
#6 0x5585c3f7e435 in mp_execute_bytecode ../../py/vm.c:1069
#7 0x5585c3f3c700 in fun_bc_call ../../py/objfun.c:295
#8 0x5585c3f1c0d8 in mp_call_function_n_kw ../../py/runtime.c:727
#9 0x5585c3f1ca56 in mp_call_method_n_kw ../../py/runtime.c:743
#10 0x5585c3f7e435 in mp_execute_bytecode ../../py/vm.c:1069
#11 0x5585c3f3c700 in fun_bc_call ../../py/objfun.c:295
#12 0x5585c3f1c0d8 in mp_call_function_n_kw ../../py/runtime.c:727
#13 0x5585c3f2006a in mp_call_function_0 ../../py/runtime.c:701
#14 0x5585c4091d84 in execute_from_lexer /home/jepler/src/micropython/ports/unix/main.c:162
#15 0x5585c40923fb in do_repl /home/jepler/src/micropython/ports/unix/main.c:273
#16 0x5585c4093b3d in main_ /home/jepler/src/micropython/ports/unix/main.c:753
#17 0x5585c4093d6d in main /home/jepler/src/micropython/ports/unix/main.c:494
#18 0x7f12f5e46249 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#19 0x7f12f5e46304 in __libc_start_main_impl ../csu/libc-start.c:360
#20 0x5585c3ec0bf0 in _start (/home/jepler/src/micropython/ports/unix/build-coverage/micropython+0x1a7bf0)
0x5585c4169a28 is located 56 bytes to the left of global variable 'pinbase_singleton' defined in '../../extmod/machine_pinbase.c:43:27' (0x5585c4169a60) of size 8
0x5585c4169a28 is located 0 bytes to the right of global variable 'pinbase_pin_p' defined in '../../extmod/machine_pinbase.c:75:25' (0x5585c4169a20) of size 8
SUMMARY: AddressSanitizer: global-buffer-overflow ../../py/stream.c:102 in mp_get_stream_raise
Pin objects and stream objects both fill the protocol
spot. However, their protocol definitions are different and incompatible.
Without ASan, this resulted in an exception (yay!) but this is by luck, because mp_get_stream_raise can't tell that the protocol
slot of the object is an incompatible "Pin" protocol (with only ioctl) rather than the standard "Stream" protocol (with read/write/ioctl).
Additional Information
Somewhat related: #17714 (can pass an object without protocol to machine.time_pulse_us
; missing check whether the protocol slot is filled at all).
There's a third leg to the problem, in which this calls read
a bunch of times on sys.stdout (due to incorrectly calling through the read function of mp_stream_p_t
):
>>> machine.time_pulse_us(sys.stdout, .001)
-2
For once this wasn't from fuzzing. 😜
Code of Conduct
Yes, I agree