@@ -1561,9 +1561,11 @@ static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct c
1561
1561
static void sn_coap_protocol_handle_blockwise_timout (struct coap_s * handle )
1562
1562
{
1563
1563
/* Loop all outgoing blockwise messages */
1564
+ /* foreach_safe isn't sufficient because callback routine could remove messages. */
1565
+ rescan :
1564
1566
ns_list_foreach_safe (coap_blockwise_msg_s , removed_blocwise_msg_ptr , & handle -> linked_list_blockwise_sent_msgs ) {
1565
1567
if ((handle -> system_time - removed_blocwise_msg_ptr -> timestamp ) > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED ) {
1566
-
1568
+ bool callback_called = false;
1567
1569
// Item must be removed from the list before calling the rx_callback function.
1568
1570
// Callback could actually clear the list and free the item and cause a use after free when callback returns.
1569
1571
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)
1576
1578
removed_blocwise_msg_ptr -> coap_msg_ptr -> msg_id = removed_blocwise_msg_ptr -> msg_id ;
1577
1579
sn_coap_protocol_delete_retransmission (handle , removed_blocwise_msg_ptr -> msg_id );
1578
1580
handle -> sn_coap_rx_callback (removed_blocwise_msg_ptr -> coap_msg_ptr , NULL , removed_blocwise_msg_ptr -> param );
1581
+ callback_called = true;
1579
1582
}
1580
1583
1581
1584
handle -> sn_coap_protocol_free (removed_blocwise_msg_ptr -> coap_msg_ptr -> payload_ptr );
1582
1585
sn_coap_parser_release_allocated_coap_msg_mem (handle , removed_blocwise_msg_ptr -> coap_msg_ptr );
1583
1586
}
1584
1587
1585
1588
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
+ }
1586
1595
}
1587
1596
}
1588
1597
0 commit comments