Fix crash when UART construct fails

After the script stops with the exception thrown the final gc_sweep
will call any finalizers and they usually call deinit. deinit on
invalid objects can wreak havoc by changing random memory or
(hopefully) crashing. This fixes ensures the object is deinited
until initialization succeeds and the object is valid.

Do the same fix for I2C and SPI too.

Fixes #4700 and fixes #5005
This commit is contained in:
Scott Shawcroft 2021-07-20 17:08:22 -07:00
parent ce7301527a
commit fece0fb432
No known key found for this signature in database
GPG Key ID: 0DFD512649C052DA
4 changed files with 25 additions and 6 deletions

View File

@ -143,6 +143,10 @@ msgstr ""
msgid "%q must be between %d and %d" msgid "%q must be between %d and %d"
msgstr "" msgstr ""
#: ports/atmel-samd/common-hal/busio/UART.c
msgid "%q must be power of 2"
msgstr ""
#: py/argcheck.c #: py/argcheck.c
msgid "%q must of type %q" msgid "%q must of type %q"
msgstr "" msgstr ""
@ -389,6 +393,7 @@ msgstr ""
msgid "All event channels in use" msgid "All event channels in use"
msgstr "" msgstr ""
#: ports/raspberrypi/common-hal/pulseio/PulseIn.c
#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c
msgid "All state machines in use" msgid "All state machines in use"
msgstr "" msgstr ""
@ -973,7 +978,7 @@ msgstr ""
msgid "Expected an alarm" msgid "Expected an alarm"
msgstr "" msgstr ""
#: shared-module/_pixelbuf/PixelBuf.c #: shared-module/adafruit_pixelbuf/PixelBuf.c
#, c-format #, c-format
msgid "Expected tuple of length %d, got %d" msgid "Expected tuple of length %d, got %d"
msgstr "" msgstr ""
@ -1295,7 +1300,7 @@ msgstr ""
msgid "Invalid buffer size" msgid "Invalid buffer size"
msgstr "" msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c #: shared-bindings/adafruit_pixelbuf/PixelBuf.c
msgid "Invalid byteorder string" msgid "Invalid byteorder string"
msgstr "" msgstr ""
@ -1501,7 +1506,7 @@ msgstr ""
msgid "Missing first_set_pin. Instruction %d sets pin(s)" msgid "Missing first_set_pin. Instruction %d sets pin(s)"
msgstr "" msgstr ""
#: shared-bindings/displayio/Group.c #: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c
msgid "Must be a %q subclass." msgid "Must be a %q subclass."
msgstr "" msgstr ""
@ -2348,7 +2353,7 @@ msgstr ""
msgid "Unknown system firmware error: %04x" msgid "Unknown system firmware error: %04x"
msgstr "" msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c #: shared-bindings/adafruit_pixelbuf/PixelBuf.c
#, c-format #, c-format
msgid "Unmatched number of items on RHS (expected %d, got %d)." msgid "Unmatched number of items on RHS (expected %d, got %d)."
msgstr "" msgstr ""
@ -2631,7 +2636,7 @@ msgstr ""
msgid "buttons must be digitalio.DigitalInOut" msgid "buttons must be digitalio.DigitalInOut"
msgstr "" msgstr ""
#: shared-bindings/_pixelbuf/PixelBuf.c #: shared-bindings/adafruit_pixelbuf/PixelBuf.c
msgid "byteorder is not a string" msgid "byteorder is not a string"
msgstr "" msgstr ""
@ -2681,7 +2686,7 @@ msgid "can't cancel self"
msgstr "" msgstr ""
#: py/obj.c py/objint.c shared-bindings/i2cperipheral/I2CPeripheral.c #: py/obj.c py/objint.c shared-bindings/i2cperipheral/I2CPeripheral.c
#: shared-module/_pixelbuf/PixelBuf.c #: shared-module/adafruit_pixelbuf/PixelBuf.c
msgid "can't convert %q to %q" msgid "can't convert %q to %q"
msgstr "" msgstr ""

View File

@ -71,6 +71,9 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) {
uint8_t sercom_index; uint8_t sercom_index;
uint32_t sda_pinmux, scl_pinmux; uint32_t sda_pinmux, scl_pinmux;
// Ensure the object starts in its deinit state.
self->sda_pin = NO_PIN;
Sercom *sercom = samd_i2c_get_sercom(scl, sda, &sercom_index, &sda_pinmux, &scl_pinmux); Sercom *sercom = samd_i2c_get_sercom(scl, sda, &sercom_index, &sda_pinmux, &scl_pinmux);
if (sercom == NULL) { if (sercom == NULL) {
mp_raise_ValueError(translate("Invalid pins")); mp_raise_ValueError(translate("Invalid pins"));

View File

@ -92,6 +92,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
uint8_t miso_pad = 0; uint8_t miso_pad = 0;
uint8_t dopo = 255; uint8_t dopo = 255;
// Ensure the object starts in its deinit state.
self->clock_pin = NO_PIN;
// Special case for SAMR21 boards. (feather_radiofruit_zigbee) // Special case for SAMR21 boards. (feather_radiofruit_zigbee)
#if defined(PIN_PC19F_SERCOM4_PAD0) #if defined(PIN_PC19F_SERCOM4_PAD0)
if (miso == &pin_PC19) { if (miso == &pin_PC19) {

View File

@ -71,6 +71,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
uint32_t tx_pinmux = 0; uint32_t tx_pinmux = 0;
uint8_t tx_pad = 255; // Unset pad uint8_t tx_pad = 255; // Unset pad
// Set state so the object is deinited to start.
self->rx_pin = NO_PIN;
self->tx_pin = NO_PIN;
if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL) || (rs485_invert)) { if ((rts != NULL) || (cts != NULL) || (rs485_dir != NULL) || (rs485_invert)) {
mp_raise_ValueError(translate("RTS/CTS/RS485 Not yet supported on this device")); mp_raise_ValueError(translate("RTS/CTS/RS485 Not yet supported on this device"));
} }
@ -85,6 +89,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
mp_raise_ValueError(translate("tx and rx cannot both be None")); mp_raise_ValueError(translate("tx and rx cannot both be None"));
} }
if (have_rx && receiver_buffer_size > 0 && (receiver_buffer_size & (receiver_buffer_size - 1)) != 0) {
mp_raise_ValueError_varg(translate("%q must be power of 2"), MP_QSTR_receiver_buffer_size);
}
self->baudrate = baudrate; self->baudrate = baudrate;
self->character_bits = bits; self->character_bits = bits;
self->timeout_ms = timeout * 1000; self->timeout_ms = timeout * 1000;