Skip to content

Commit 5f21094

Browse files
committed
Fix a memory leak of port service name (strdup but not freed)
1 parent 8b34652 commit 5f21094

File tree

2 files changed

+49
-38
lines changed

2 files changed

+49
-38
lines changed

portlist.cc

+45-36
Original file line numberDiff line numberDiff line change
@@ -84,33 +84,39 @@ Port::Port() {
8484
state_reason_init(&reason);
8585
}
8686

87-
void Port::freeService(bool del_service) {
88-
if (service != NULL) {
89-
std::vector<char *>::iterator it;
90-
91-
if (service->name)
92-
free(service->name);
93-
if (service->product)
94-
free(service->product);
95-
if (service->version)
96-
free(service->version);
97-
if (service->extrainfo)
98-
free(service->extrainfo);
99-
if (service->hostname)
100-
free(service->hostname);
101-
if (service->ostype)
102-
free(service->ostype);
103-
if (service->devicetype)
104-
free(service->devicetype);
105-
if (service->service_fp)
106-
free(service->service_fp);
107-
for (it = service->cpe.begin(); it != service->cpe.end(); it++)
108-
free(*it);
109-
service->cpe.clear();
110-
111-
if (del_service)
112-
delete service;
113-
}
87+
void serviceDeductions::erase() {
88+
std::vector<char *>::iterator it;
89+
90+
if (this->product)
91+
free(this->product);
92+
if (this->version)
93+
free(this->version);
94+
if (this->extrainfo)
95+
free(this->extrainfo);
96+
if (this->hostname)
97+
free(this->hostname);
98+
if (this->ostype)
99+
free(this->ostype);
100+
if (this->devicetype)
101+
free(this->devicetype);
102+
if (this->service_fp)
103+
free(this->service_fp);
104+
// For now, always free CPE strings
105+
for (it = this->cpe.begin(); it != this->cpe.end(); it++)
106+
free(*it);
107+
this->cpe.clear();
108+
109+
this->name = NULL;
110+
this->name_confidence = 0;
111+
this->product = NULL;
112+
this->version = NULL;
113+
this->extrainfo = NULL;
114+
this->hostname = NULL;
115+
this->ostype = NULL;
116+
this->devicetype = NULL;
117+
this->service_tunnel = SERVICE_TUNNEL_NONE;
118+
this->service_fp = NULL;
119+
this->dtype = SERVICE_DETECTION_TABLE;
114120
}
115121

116122
void Port::freeScriptResults(void)
@@ -253,7 +259,6 @@ void serviceDeductions::populateFullVersionString(char *buf, size_t n) const {
253259
// pass in an allocated struct serviceDeductions (don't worry about
254260
// initializing, and you don't have to free any internal ptrs. See the
255261
// serviceDeductions definition for the fields that are populated.
256-
// Returns 0 if at least a name is available.
257262
void PortList::getServiceDeductions(u16 portno, int protocol, struct serviceDeductions *sd) const {
258263
const Port *port;
259264

@@ -265,7 +270,7 @@ void PortList::getServiceDeductions(u16 portno, int protocol, struct serviceDedu
265270
*sd = serviceDeductions();
266271
service = nmap_getservbyport(portno, IPPROTO2STR(protocol));
267272
if (service != NULL)
268-
sd->name = strdup(service->s_name);
273+
sd->name = service->s_name;
269274
else
270275
sd->name = NULL;
271276
sd->name_confidence = 3;
@@ -315,6 +320,8 @@ void PortList::setServiceProbeResults(u16 portno, int protocol,
315320
port = createPort(portno, protocol);
316321
if (port->service == NULL)
317322
port->service = new serviceDeductions;
323+
else
324+
port->service->erase();
318325

319326
if (sres == PROBESTATE_FINISHED_HARDMATCHED
320327
|| sres == PROBESTATE_FINISHED_SOFTMATCHED) {
@@ -341,10 +348,8 @@ void PortList::setServiceProbeResults(u16 portno, int protocol,
341348
// port->serviceprobe_results = sres;
342349
port->service->service_tunnel = tunnel;
343350

344-
port->freeService(false);
345-
346351
if (sname)
347-
port->service->name = strdup(sname);
352+
port->service->name = sname;
348353
else
349354
port->service->name = NULL;
350355

@@ -426,10 +431,14 @@ PortList::~PortList() {
426431
for(proto=0; proto < PORTLIST_PROTO_MAX; proto++) { // for every protocol
427432
if(port_list[proto]) {
428433
for(i=0; i < port_list_count[proto]; i++) { // free every Port
429-
if(port_list[proto][i]) {
430-
port_list[proto][i]->freeService(true);
431-
port_list[proto][i]->freeScriptResults();
432-
delete port_list[proto][i];
434+
Port *port = port_list[proto][i];
435+
if(port) {
436+
if (port->service) {
437+
port->service->erase();
438+
delete port->service;
439+
}
440+
port->freeScriptResults();
441+
delete port;
433442
}
434443
}
435444
free(port_list[proto]);

portlist.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,11 @@ void random_port_cheat(u16 *ports, int portcount);
115115

116116
struct serviceDeductions {
117117
serviceDeductions();
118+
// Free any strings that need to be freed and set all pointers to null.
119+
void erase();
118120
void populateFullVersionString(char *buf, size_t n) const;
119121

120-
char *name; // will be NULL if can't determine
122+
const char *name; // will be NULL if can't determine
121123
// Confidence is a number from 0 (least confident) to 10 (most
122124
// confident) expressing how accurate the service detection is
123125
// likely to be.
@@ -236,7 +238,7 @@ class PortList {
236238

237239
// pass in an allocated struct serviceDeductions (don't worry about initializing, and
238240
// you don't have to free any internal ptrs. See the serviceDeductions definition for
239-
// the fields that are populated. Returns 0 if at least a name is available.
241+
// the fields that are populated.
240242
void getServiceDeductions(u16 portno, int protocol, struct serviceDeductions *sd) const;
241243

242244
#ifndef NOLUA

0 commit comments

Comments
 (0)