From c5be565eb457361b98b4785ea8e4d6088b5bf06b Mon Sep 17 00:00:00 2001 From: Peter Bay Date: Mon, 14 Sep 2026 17:10:41 +0200 Subject: [PATCH] warnings, getpass, os, adafruit_bus_device, traceback: failures reported as success mp_raise_msg_str asserts that the type's make_new is mp_obj_exception_make_new. A Python subclass of Warning has mp_obj_instance_make_new instead, and the assert is compiled out of a release build, so warnings.warn called the wrong function with the exception's arguments and faulted the board. It calls the category and raises what comes back. getpass passed its prompt to mp_printf as the format string, so a prompt containing a percent sign read conversions off the varargs area. os.chdir wrote cwd_path and vfs_cur before the lookup and the proxy call that can fail, with no restore on the raise path, so a chdir to a missing directory raised and left the current directory pointing at it. adafruit_bus_device broke out of its acquire loop when an exception was pending and then returned as though it held the bus; it calls mp_handle_pending(true) now. traceback.print_exception overwrites the live exception's traceback, and its context and cause when chain is false, and restored them only on the path where printing returned. --- shared-bindings/traceback/__init__.c | 13 ++++++++++++- .../adafruit_bus_device/i2c_device/I2CDevice.c | 4 +--- shared-module/getpass/__init__.c | 2 +- shared-module/os/__init__.c | 7 ++++--- shared-module/warnings/__init__.c | 5 ++--- 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/shared-bindings/traceback/__init__.c b/shared-bindings/traceback/__init__.c index 651ec2c0142..dcdf2914a4f 100644 --- a/shared-bindings/traceback/__init__.c +++ b/shared-bindings/traceback/__init__.c @@ -102,7 +102,18 @@ static void traceback_exception_common(bool is_print_exception, mp_print_t *prin exc->traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; } - shared_module_traceback_print_exception(MP_OBJ_TO_PTR(value), print, limit); + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + shared_module_traceback_print_exception(MP_OBJ_TO_PTR(value), print, limit); + nlr_pop(); + } else { + exc->traceback = trace_backup; + #if MICROPY_CPYTHON_EXCEPTION_CHAIN + exc->context = context_backup; + exc->cause = cause_backup; + #endif + nlr_jump(nlr.ret_val); + } exc->traceback = trace_backup; #if MICROPY_CPYTHON_EXCEPTION_CHAIN exc->context = context_backup; diff --git a/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c b/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c index e01875452b1..0ed2d35be53 100644 --- a/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c +++ b/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c @@ -24,9 +24,7 @@ void common_hal_adafruit_bus_device_i2cdevice_lock(adafruit_bus_device_i2cdevice while (!mp_obj_is_true(success)) { RUN_BACKGROUND_TASKS; - if (mp_hal_is_interrupted()) { - break; - } + mp_handle_pending(true); success = mp_call_method_n_kw(0, 0, dest); } diff --git a/shared-module/getpass/__init__.c b/shared-module/getpass/__init__.c index 5263ff637d6..446e1b1d280 100644 --- a/shared-module/getpass/__init__.c +++ b/shared-module/getpass/__init__.c @@ -15,7 +15,7 @@ mp_obj_t shared_module_getpass_getpass(const char *prompt, mp_print_t *print) { if (print == NULL) { mp_hal_stdout_tx_str(prompt); } else { - mp_printf(print, prompt); + mp_print_str(print, prompt); } for (;;) { diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 2090dcbcdc4..3a74fe4a7b0 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -145,10 +145,9 @@ const char *common_hal_os_path_abspath(const char *path) { } void common_hal_os_chdir(const char *path) { - MP_STATE_VM(cwd_path) = common_hal_os_path_abspath(path); + const char *new_cwd = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_dir_path(MP_STATE_VM(cwd_path), &path_out); - MP_STATE_VM(vfs_cur) = vfs; + mp_vfs_mount_t *vfs = lookup_dir_path(new_cwd, &path_out); if (vfs == MP_VFS_ROOT) { // If we change to the root dir and a VFS is mounted at the root then // we must change that VFS's current dir to the root dir so that any @@ -163,6 +162,8 @@ void common_hal_os_chdir(const char *path) { } else { mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &path_out); } + MP_STATE_VM(cwd_path) = new_cwd; + MP_STATE_VM(vfs_cur) = vfs; } mp_obj_t common_hal_os_getcwd(void) { diff --git a/shared-module/warnings/__init__.c b/shared-module/warnings/__init__.c index ad2f14b1c5b..9961c6caa7f 100644 --- a/shared-module/warnings/__init__.c +++ b/shared-module/warnings/__init__.c @@ -21,9 +21,8 @@ void common_hal_warnings_warn(const char *message, const mp_obj_type_t *category return; } if (action == WARNINGS_ERROR) { - mp_raise_msg_str(category, message); - // Doesn't get here - return; + nlr_raise(mp_call_function_1(MP_OBJ_FROM_PTR(category), + mp_obj_new_str(message, strlen(message)))); } mp_printf(MICROPY_ERROR_PRINTER, "%q: %s\n", category->name, message); }