@@ -1561,9 +1561,11 @@ static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct c
15611561static void sn_coap_protocol_handle_blockwise_timout (struct coap_s * handle )
15621562{
15631563 /* Loop all outgoing blockwise messages */
1564+ /* foreach_safe isn't sufficient because callback routine could remove messages. */
1565+ rescan :
15641566 ns_list_foreach_safe (coap_blockwise_msg_s , removed_blocwise_msg_ptr , & handle -> linked_list_blockwise_sent_msgs ) {
15651567 if ((handle -> system_time - removed_blocwise_msg_ptr -> timestamp ) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED ) {
1566-
1568+ bool callback_called = false;
15671569 // Item must be removed from the list before calling the rx_callback function.
15681570 // Callback could actually clear the list and free the item and cause a use after free when callback returns.
15691571 ns_list_remove (& handle -> linked_list_blockwise_sent_msgs , removed_blocwise_msg_ptr );
@@ -1576,13 +1578,20 @@ static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle)
15761578 removed_blocwise_msg_ptr -> coap_msg_ptr -> msg_id = removed_blocwise_msg_ptr -> msg_id ;
15771579 sn_coap_protocol_delete_retransmission (handle , removed_blocwise_msg_ptr -> msg_id );
15781580 handle -> sn_coap_rx_callback (removed_blocwise_msg_ptr -> coap_msg_ptr , NULL , removed_blocwise_msg_ptr -> param );
1581+ callback_called = true;
15791582 }
15801583
15811584 handle -> sn_coap_protocol_free (removed_blocwise_msg_ptr -> coap_msg_ptr -> payload_ptr );
15821585 sn_coap_parser_release_allocated_coap_msg_mem (handle , removed_blocwise_msg_ptr -> coap_msg_ptr );
15831586 }
15841587
15851588 handle -> sn_coap_protocol_free (removed_blocwise_msg_ptr );
1589+
1590+ if (callback_called ) {
1591+ /* Callback routine could have wiped the list already */
1592+ /* Be super cautious and rescan from the start */
1593+ goto rescan ;
1594+ }
15861595 }
15871596 }
15881597
0 commit comments