Fix semantics of std::unique() to actually remove duplicates (hidden memory leak?)

This commit is contained in:
Adam Ierymenko 2015-06-29 10:21:28 -07:00
parent 3f71afd0fb
commit dbee1b38b3
9 changed files with 63 additions and 9 deletions

View File

@ -389,7 +389,7 @@ NetworkController::ResultCode SqliteNetworkController::doNetworkConfigRequest(co
allowedEtherTypes.push_back(et); allowedEtherTypes.push_back(et);
} }
std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end()); std::sort(allowedEtherTypes.begin(),allowedEtherTypes.end());
std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()); allowedEtherTypes.erase(std::unique(allowedEtherTypes.begin(),allowedEtherTypes.end()),allowedEtherTypes.end());
std::string allowedEtherTypesCsv; std::string allowedEtherTypesCsv;
for(std::vector<int>::const_iterator i(allowedEtherTypes.begin());i!=allowedEtherTypes.end();++i) { for(std::vector<int>::const_iterator i(allowedEtherTypes.begin());i!=allowedEtherTypes.end();++i) {
if (allowedEtherTypesCsv.length()) if (allowedEtherTypesCsv.length())

View File

@ -140,7 +140,7 @@ void CertificateOfMembership::fromString(const char *s)
} }
std::sort(_qualifiers.begin(),_qualifiers.end()); std::sort(_qualifiers.begin(),_qualifiers.end());
std::unique(_qualifiers.begin(),_qualifiers.end()); _qualifiers.erase(std::unique(_qualifiers.begin(),_qualifiers.end()),_qualifiers.end());
} }
bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const

View File

@ -273,6 +273,39 @@ InetAddress InetAddress::broadcast() const
return r; return r;
} }
bool InetAddress::isNetwork() const
throw()
{
switch(ss_family) {
case AF_INET: {
unsigned int bits = netmaskBits();
if (bits <= 0)
return false;
if (bits >= 32)
return false;
uint32_t ip = Utils::ntoh((uint32_t)reinterpret_cast<const struct sockaddr_in *>(this)->sin_addr.s_addr);
return ((ip & (0xffffffff >> bits)) == 0);
}
case AF_INET6: {
unsigned int bits = netmaskBits();
if (bits <= 0)
return false;
if (bits >= 128)
return false;
const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
unsigned int p = bits / 8;
if ((ip[p++] & (0xff >> (bits % 8))) != 0)
return false;
while (p < 16) {
if (ip[p++])
return false;
}
return true;
}
}
return false;
}
bool InetAddress::operator==(const InetAddress &a) const bool InetAddress::operator==(const InetAddress &a) const
throw() throw()
{ {

View File

@ -343,6 +343,17 @@ struct InetAddress : public sockaddr_storage
*/ */
inline void zero() throw() { memset(this,0,sizeof(InetAddress)); } inline void zero() throw() { memset(this,0,sizeof(InetAddress)); }
/**
* Check whether this is a network/route rather than an IP assignment
*
* A network is an IP/netmask where everything after the netmask is
* zero e.g. 10.0.0.0/8.
*
* @return True if everything after netmask bits is zero
*/
bool isNetwork() const
throw();
/** /**
* @return True if address family is non-zero * @return True if address family is non-zero
*/ */

View File

@ -502,7 +502,7 @@ std::vector<MulticastGroup> Network::_allMulticastGroups() const
if ((_config)&&(_config->enableBroadcast())) if ((_config)&&(_config->enableBroadcast()))
mgs.push_back(Network::BROADCAST); mgs.push_back(Network::BROADCAST);
std::sort(mgs.begin(),mgs.end()); std::sort(mgs.begin(),mgs.end());
std::unique(mgs.begin(),mgs.end()); mgs.erase(std::unique(mgs.begin(),mgs.end()),mgs.end());
return mgs; return mgs;
} }

View File

@ -132,10 +132,18 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
case AF_INET: case AF_INET:
if ((!addr.netmaskBits())||(addr.netmaskBits() > 32)) if ((!addr.netmaskBits())||(addr.netmaskBits() > 32))
continue; continue;
else if (addr.isNetwork()) {
// TODO: add route to network -- this is a route without an IP assignment
continue;
}
break; break;
case AF_INET6: case AF_INET6:
if ((!addr.netmaskBits())||(addr.netmaskBits() > 128)) if ((!addr.netmaskBits())||(addr.netmaskBits() > 128))
continue; continue;
else if (addr.isNetwork()) {
// TODO: add route to network -- this is a route without an IP assignment
continue;
}
break; break;
default: // ignore unrecognized address types or junk/empty fields default: // ignore unrecognized address types or junk/empty fields
continue; continue;
@ -143,9 +151,9 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
_staticIps.push_back(addr); _staticIps.push_back(addr);
} }
if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES) if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES)
throw std::invalid_argument("too many ZT-assigned IP addresses"); throw std::invalid_argument("too many ZT-assigned IP addresses or routes");
std::sort(_staticIps.begin(),_staticIps.end()); std::sort(_staticIps.begin(),_staticIps.end());
std::unique(_staticIps.begin(),_staticIps.end()); _staticIps.erase(std::unique(_staticIps.begin(),_staticIps.end()),_staticIps.end());
std::vector<std::string> gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","","")); std::vector<std::string> gatewaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_GATEWAYS,"").c_str(),",","",""));
for(std::vector<std::string>::const_iterator gwstr(gatewaysSplit.begin());gwstr!=gatewaysSplit.end();++gwstr) { for(std::vector<std::string>::const_iterator gwstr(gatewaysSplit.begin());gwstr!=gatewaysSplit.end();++gwstr) {
@ -163,7 +171,7 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
} }
} }
std::sort(_activeBridges.begin(),_activeBridges.end()); std::sort(_activeBridges.begin(),_activeBridges.end());
std::unique(_activeBridges.begin(),_activeBridges.end()); _activeBridges.erase(std::unique(_activeBridges.begin(),_activeBridges.end()),_activeBridges.end());
std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","","")); std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) { for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) {
@ -177,7 +185,7 @@ void NetworkConfig::_fromDictionary(const Dictionary &d)
} }
} }
std::sort(_relays.begin(),_relays.end()); std::sort(_relays.begin(),_relays.end());
std::unique(_relays.begin(),_relays.end()); _relays.erase(std::unique(_relays.begin(),_relays.end()),_relays.end());
_com.fromString(d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP,std::string())); _com.fromString(d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP,std::string()));
} }

View File

@ -78,9 +78,11 @@ namespace ZeroTier {
#define ZT_NETWORKCONFIG_DICT_KEY_DESC "d" #define ZT_NETWORKCONFIG_DICT_KEY_DESC "d"
// IP/bits[,IP/bits,...] // IP/bits[,IP/bits,...]
// Note that IPs that end in all zeroes are routes with no assignment in them.
#define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC "v4s"
// IP/bits[,IP/bits,...] // IP/bits[,IP/bits,...]
// Note that IPs that end in all zeroes are routes with no assignment in them.
#define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s" #define ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC "v6s"
// serialized CertificateOfMembership // serialized CertificateOfMembership

View File

@ -251,7 +251,7 @@ ZT1_ResultCode Node::processBackgroundTasks(uint64_t now,volatile uint64_t *next
// Attempt to contact network preferred relays that we don't have direct links to // Attempt to contact network preferred relays that we don't have direct links to
std::sort(networkRelays.begin(),networkRelays.end()); std::sort(networkRelays.begin(),networkRelays.end());
std::unique(networkRelays.begin(),networkRelays.end()); networkRelays.erase(std::unique(networkRelays.begin(),networkRelays.end()),networkRelays.end());
for(std::vector< std::pair<Address,InetAddress> >::const_iterator nr(networkRelays.begin());nr!=networkRelays.end();++nr) { for(std::vector< std::pair<Address,InetAddress> >::const_iterator nr(networkRelays.begin());nr!=networkRelays.end();++nr) {
if (nr->second) { if (nr->second) {
SharedPtr<Peer> rp(RR->topology->getPeer(nr->first)); SharedPtr<Peer> rp(RR->topology->getPeer(nr->first));

View File

@ -864,7 +864,7 @@ public:
for(unsigned int i=0;i<nwc->assignedAddressCount;++i) for(unsigned int i=0;i<nwc->assignedAddressCount;++i)
newAssignedIps.push_back(InetAddress(nwc->assignedAddresses[i])); newAssignedIps.push_back(InetAddress(nwc->assignedAddresses[i]));
std::sort(newAssignedIps.begin(),newAssignedIps.end()); std::sort(newAssignedIps.begin(),newAssignedIps.end());
std::unique(newAssignedIps.begin(),newAssignedIps.end()); newAssignedIps.erase(std::unique(newAssignedIps.begin(),newAssignedIps.end()),newAssignedIps.end());
for(std::vector<InetAddress>::iterator ip(newAssignedIps.begin());ip!=newAssignedIps.end();++ip) { for(std::vector<InetAddress>::iterator ip(newAssignedIps.begin());ip!=newAssignedIps.end();++ip) {
if (!std::binary_search(assignedIps.begin(),assignedIps.end(),*ip)) if (!std::binary_search(assignedIps.begin(),assignedIps.end(),*ip))
t->second->addIp(*ip); t->second->addIp(*ip);