Skip to content

Commit c732402

Browse files
committed
Double-Free in _handle_async_event()
[pull request 112](me-no-dev#112)
1 parent 9c4145b commit c732402

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

src/AsyncTCP.cpp

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -103,48 +103,63 @@ static inline bool _init_async_event_queue(){
103103
return true;
104104
}
105105

106-
static inline bool _send_async_event(lwip_event_packet_t ** e){
107-
return _async_queue && xQueueSend(_async_queue, e, portMAX_DELAY) == pdPASS;
106+
static inline bool _send_async_event(lwip_event_packet_t ** e_buf){
107+
return _async_queue && xQueueSend(_async_queue, e_buf, portMAX_DELAY) == pdPASS;
108108
}
109109

110-
static inline bool _prepend_async_event(lwip_event_packet_t ** e){
111-
return _async_queue && xQueueSendToFront(_async_queue, e, portMAX_DELAY) == pdPASS;
110+
static inline bool _prepend_async_event(lwip_event_packet_t ** e_buf){
111+
return _async_queue && xQueueSendToFront(_async_queue, e_buf, portMAX_DELAY) == pdPASS;
112112
}
113113

114-
static inline bool _get_async_event(lwip_event_packet_t ** e){
115-
return _async_queue && xQueueReceive(_async_queue, e, portMAX_DELAY) == pdPASS;
114+
static inline bool _get_async_event(lwip_event_packet_t ** e_buf){
115+
return _async_queue && xQueueReceive(_async_queue, e_buf, portMAX_DELAY) == pdPASS;
116116
}
117117

118-
static bool _remove_events_with_arg(void * arg){
118+
// Removes (from the _async_queue) and also frees the associated memory of
119+
// any event packages where the void *arg struct member is identical
120+
// to the one of the input event packet by pointer stored in e_buf.
121+
//
122+
// This always iterates over the whole queue and adds everything back
123+
// in the same order except for the removed elements
124+
//
125+
// The event package pointer in the input e_buf is NULLed and can/must be freed later
126+
static bool _remove_events_with_arg(lwip_event_packet_t ** e_buf){
127+
lwip_event_packet_t * packet_in = *e_buf;
119128
lwip_event_packet_t * first_packet = NULL;
120129
lwip_event_packet_t * packet = NULL;
121130

122-
if(!_async_queue){
131+
if(!_async_queue || !packet_in){
123132
return false;
133+
} else {
134+
// Nullifying the event packet pointer so that it is safe to call
135+
// free() later even if there are duplicate events in the queue
136+
*e_buf = NULL;
124137
}
125-
//figure out which is the first packet so we can keep the order
138+
int arg_in = reinterpret_cast<int>(packet_in->arg);
139+
// Figure out which is the first packet so we can keep the order
126140
while(!first_packet){
127141
if(xQueueReceive(_async_queue, &first_packet, 0) != pdPASS){
128142
return false;
129143
}
130-
//discard packet if matching
131-
if((int)first_packet->arg == (int)arg){
144+
// Packet was already removed from the queue, so if matching, it is
145+
// not added back but discarded, and also its memory is freed.
146+
if(reinterpret_cast<int>(first_packet->arg) == arg_in){
132147
free(first_packet);
133148
first_packet = NULL;
134-
//return first packet to the back of the queue
135-
} else if(xQueueSend(_async_queue, &first_packet, portMAX_DELAY) != pdPASS){
149+
// If not matching, return packet back to the end of the queue and continue
150+
} else if(xQueueSendToBack(_async_queue, &first_packet, portMAX_DELAY) != pdPASS){
136151
return false;
137152
}
138153
}
139-
154+
// Same for all othes until arriving back again at the front (first_packet)
140155
while(xQueuePeek(_async_queue, &packet, 0) == pdPASS && packet != first_packet){
141156
if(xQueueReceive(_async_queue, &packet, 0) != pdPASS){
142157
return false;
143158
}
144-
if((int)packet->arg == (int)arg){
159+
if(reinterpret_cast<int>(packet->arg) == arg_in){
145160
free(packet);
146161
packet = NULL;
147-
} else if(xQueueSend(_async_queue, &packet, portMAX_DELAY) != pdPASS){
162+
} else if(xQueueSendToBack(_async_queue, &packet, portMAX_DELAY) != pdPASS){
148163
return false;
149164
}
150165
}
@@ -156,7 +171,7 @@ static void _handle_async_event(lwip_event_packet_t * e){
156171
// do nothing when arg is NULL
157172
//ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb);
158173
} else if(e->event == LWIP_TCP_CLEAR){
159-
_remove_events_with_arg(e->arg);
174+
_remove_events_with_arg(&e);
160175
} else if(e->event == LWIP_TCP_RECV){
161176
//ets_printf("-R: 0x%08x\n", e->recv.pcb);
162177
AsyncClient::_s_recv(e->arg, e->recv.pcb, e->recv.pb, e->recv.err);
@@ -182,7 +197,7 @@ static void _handle_async_event(lwip_event_packet_t * e){
182197
//ets_printf("D: 0x%08x %s = %s\n", e->arg, e->dns.name, ipaddr_ntoa(&e->dns.addr));
183198
AsyncClient::_s_dns_found(e->dns.name, &e->dns.addr, e->arg);
184199
}
185-
free((void*)(e));
200+
free(e);
186201
}
187202

188203
static void _async_service_task(void *pvParameters){

0 commit comments

Comments
 (0)