Memory leak if libzt events aren't consumed by user app
If arg is not enqueued by Events, then treat as if ownership has NOT
been transferred and caller of Events->enqueue is responsible for freeing
This commit is contained in:
Brenton Bostick
2023-08-21 11:50:05 -04:00
parent f5ffc062e9
commit ee5047b59a
4 changed files with 90 additions and 17 deletions

View File

@@ -93,11 +93,18 @@ void Events::run()
}
}
void Events::enqueue(unsigned int event_code, const void* arg, int len)
bool Events::enqueue(unsigned int event_code, const void* arg, int len)
{
if (! _enabled) {
return;
return false;
}
if (_callbackMsgQueue.size_approx() > 1024) {
/* Rate-limit number of events. This value should only grow if the
user application isn't returning from the event handler in a timely manner.
For most applications it should hover around 1 to 2 */
return false;
}
zts_event_msg_t* msg = new zts_event_msg_t();
msg->event_code = event_code;
@@ -132,15 +139,12 @@ void Events::enqueue(unsigned int event_code, const void* arg, int len)
msg->cache = (void*)arg;
msg->len = len;
}
if (msg && _callbackMsgQueue.size_approx() > 1024) {
/* Rate-limit number of events. This value should only grow if the
user application isn't returning from the event handler in a timely manner.
For most applications it should hover around 1 to 2 */
destroy(msg);
}
else {
_callbackMsgQueue.enqueue(msg);
}
//
// ownership of arg is now transferred
//
_callbackMsgQueue.enqueue(msg);
return true;
}
void Events::destroy(zts_event_msg_t* msg)

View File

@@ -115,8 +115,12 @@ class Events {
/**
* Enqueue an event to be sent to the user application
*
* Returns true if arg was enqueued.
* If enqueued, then ownership of arg has been transferred.
* If NOT enqueued, then ownership of arg has NOT been transferred.
*/
void enqueue(unsigned int event_code, const void* arg, int len = 0);
bool enqueue(unsigned int event_code, const void* arg, int len = 0);
/**
* Send callback message to user application

View File

@@ -957,13 +957,17 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
void* objptr = NULL;
zts_node_info_t* nd;
zts_net_info_t* nt;
zts_peer_info_t* pr;
switch (zt_event_code) {
case ZTS_EVENT_NODE_UP:
case ZTS_EVENT_NODE_ONLINE:
case ZTS_EVENT_NODE_OFFLINE:
case ZTS_EVENT_NODE_DOWN:
case ZTS_EVENT_NODE_FATAL_ERROR: {
zts_node_info_t* nd = new zts_node_info_t;
nd = new zts_node_info_t;
nd->node_id = _nodeId;
nd->ver_major = ZEROTIER_ONE_VERSION_MAJOR;
nd->ver_minor = ZEROTIER_ONE_VERSION_MINOR;
@@ -980,7 +984,7 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
case ZTS_EVENT_NETWORK_ACCESS_DENIED:
case ZTS_EVENT_NETWORK_DOWN: {
NetworkState* ns = (NetworkState*)obj;
zts_net_info_t* nt = new zts_net_info_t();
nt = new zts_net_info_t();
nt->net_id = ns->config.nwid;
objptr = (void*)nt;
break;
@@ -990,7 +994,7 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
case ZTS_EVENT_NETWORK_READY_IP6:
case ZTS_EVENT_NETWORK_OK: {
NetworkState* ns = (NetworkState*)obj;
zts_net_info_t* nt = new zts_net_info_t();
nt = new zts_net_info_t();
nt->net_id = ns->config.nwid;
nt->mac = ns->config.mac;
strncpy(nt->name, ns->config.name, sizeof(ns->config.name));
@@ -1051,7 +1055,7 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
case ZTS_EVENT_PEER_UNREACHABLE:
case ZTS_EVENT_PEER_PATH_DISCOVERED:
case ZTS_EVENT_PEER_PATH_DEAD: {
zts_peer_info_t* pr = new zts_peer_info_t();
pr = new zts_peer_info_t();
ZT_Peer* peer = (ZT_Peer*)obj;
memcpy(pr, peer, sizeof(zts_peer_info_t));
for (unsigned int j = 0; j < peer->pathCount; j++) {
@@ -1067,7 +1071,64 @@ void NodeService::sendEventToUser(unsigned int zt_event_code, const void* obj, u
// Send event
if (objptr) {
_events->enqueue(zt_event_code, objptr, len);
if (!_events->enqueue(zt_event_code, objptr, len)) {
//
// ownership of objptr was NOT transferred, so delete any news from above
//
switch (zt_event_code) {
case ZTS_EVENT_NODE_UP:
case ZTS_EVENT_NODE_ONLINE:
case ZTS_EVENT_NODE_OFFLINE:
case ZTS_EVENT_NODE_DOWN:
case ZTS_EVENT_NODE_FATAL_ERROR: {
delete nd;
break;
}
case ZTS_EVENT_NETWORK_NOT_FOUND:
case ZTS_EVENT_NETWORK_CLIENT_TOO_OLD:
case ZTS_EVENT_NETWORK_REQ_CONFIG:
case ZTS_EVENT_NETWORK_ACCESS_DENIED:
case ZTS_EVENT_NETWORK_DOWN: {
delete nt;
break;
}
case ZTS_EVENT_NETWORK_UPDATE:
case ZTS_EVENT_NETWORK_READY_IP4:
case ZTS_EVENT_NETWORK_READY_IP6:
case ZTS_EVENT_NETWORK_OK: {
delete nt;
break;
}
case ZTS_EVENT_ADDR_ADDED_IP4:
break;
case ZTS_EVENT_ADDR_ADDED_IP6:
break;
case ZTS_EVENT_ADDR_REMOVED_IP4:
break;
case ZTS_EVENT_ADDR_REMOVED_IP6:
break;
case ZTS_EVENT_STORE_IDENTITY_PUBLIC:
break;
case ZTS_EVENT_STORE_IDENTITY_SECRET:
break;
case ZTS_EVENT_STORE_PLANET:
break;
case ZTS_EVENT_STORE_PEER:
break;
case ZTS_EVENT_STORE_NETWORK:
break;
case ZTS_EVENT_PEER_DIRECT:
case ZTS_EVENT_PEER_RELAY:
case ZTS_EVENT_PEER_UNREACHABLE:
case ZTS_EVENT_PEER_PATH_DISCOVERED:
case ZTS_EVENT_PEER_PATH_DEAD: {
delete pr;
break;
}
default:
break;
}
}
}
}

View File

@@ -312,6 +312,10 @@ static void zts_main_lwip_driver_loop(void* arg)
zts_util_delay(LWIP_DRIVER_LOOP_INTERVAL);
}
_has_exited = true;
//
// no need to check if event was enqueued since NULL is being passed
//
zts_events->enqueue(ZTS_EVENT_STACK_DOWN, NULL);
}