diff --git a/features/frameworks/mbed-coap/CHANGELOG.md b/features/frameworks/mbed-coap/CHANGELOG.md index 5e33144cc4..e47bf91450 100644 --- a/features/frameworks/mbed-coap/CHANGELOG.md +++ b/features/frameworks/mbed-coap/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## [v4.7.1](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.7.1) + +- Fix CoAP stored blockwise message release and list continue + Add re-scan routine goto if message is caused user callback + This will fix hard fault when blockwise message sending timeouts. This happens cause same list is manipulated through rx callback. + +-[Full Changelog](https://github.com/ARMmbed/mbed-coap/compare/v4.7.0...v4.7.1) + ## [v4.7.0](https://github.com/ARMmbed/mbed-coap/releases/tag/v4.7.0) - Add function that can be used to clear the received blockwise payloads for example in the case of a connection error. diff --git a/features/frameworks/mbed-coap/module.json b/features/frameworks/mbed-coap/module.json index dc9aabcf0d..0e3d536135 100644 --- a/features/frameworks/mbed-coap/module.json +++ b/features/frameworks/mbed-coap/module.json @@ -1,6 +1,6 @@ { "name": "mbed-coap", - "version": "4.7.0", + "version": "4.7.1", "description": "COAP library", "keywords": [ "coap", diff --git a/features/frameworks/mbed-coap/source/sn_coap_protocol.c b/features/frameworks/mbed-coap/source/sn_coap_protocol.c index fcd9abd10b..8122660f4e 100644 --- a/features/frameworks/mbed-coap/source/sn_coap_protocol.c +++ b/features/frameworks/mbed-coap/source/sn_coap_protocol.c @@ -1561,9 +1561,11 @@ static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct c static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) { /* Loop all outgoing blockwise messages */ + /* foreach_safe isn't sufficient because callback routine could remove messages. */ +rescan: ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) { if ((handle->system_time - removed_blocwise_msg_ptr->timestamp) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) { - + bool callback_called = false; // Item must be removed from the list before calling the rx_callback function. // Callback could actually clear the list and free the item and cause a use after free when callback returns. ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr); @@ -1576,6 +1578,7 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id; sn_coap_protocol_delete_retransmission(handle, removed_blocwise_msg_ptr->msg_id); handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param); + callback_called = true; } handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr); @@ -1583,6 +1586,12 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle) } handle->sn_coap_protocol_free(removed_blocwise_msg_ptr); + + if (callback_called) { + /* Callback routine could have wiped the list already */ + /* Be super cautious and rescan from the start */ + goto rescan; + } } }