On Tue, Jul 03, 2001 at 04:51:45PM +0200, Miklos Szeredi wrote:
> There seems to be a leak in pcap_compile(): the allocation in
> pcap_ether_aton() is never freed, not even in pcap_freecode.
"pcap_freecode()" is handed only a pointer to a "struct bpf_program",
and that structure contains only a count of BPF instructions and a
pointer to a list of that many BPF instructions - it has no knowledge of
the Ethernet addresses used when the list of instructions was generated,
so it cannot free them.
Nor is it its job to free them; that should be done by the code
generator as soon as it's done with them.
It turns out that there is a similar leak for "pcap_ether_hostton()";
the attached patch was checked in to the CVS tree, and should fix both
of those memory leaks (it did in some tests I ran, with fprintfs logging
allocation and freeing of the memory).
Index: gencode.c
===================================================================
RCS file: /tcpdump/master/libpcap/gencode.c,v
retrieving revision 1.156
diff -c -r1.156 gencode.c
*** gencode.c 2001/06/20 07:12:38 1.156
--- gencode.c 2001/07/03 19:11:32
***************
*** 2922,2942 ****
if (eaddr == NULL)
bpf_error(
"unknown ether host '%s'", name);
! return gen_ehostop(eaddr, dir);
case DLT_FDDI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
bpf_error(
"unknown FDDI host '%s'", name);
! return gen_fhostop(eaddr, dir);
case DLT_IEEE802:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
bpf_error(
"unknown token ring host '%s'", name);
! return gen_thostop(eaddr, dir);
default:
bpf_error(
--- 2922,2948 ----
if (eaddr == NULL)
bpf_error(
"unknown ether host '%s'", name);
! b = gen_ehostop(eaddr, dir);
! free(eaddr);
! return b;
case DLT_FDDI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
bpf_error(
"unknown FDDI host '%s'", name);
! b = gen_fhostop(eaddr, dir);
! free(eaddr);
! return b;
case DLT_IEEE802:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
bpf_error(
"unknown token ring host '%s'", name);
! b = gen_thostop(eaddr, dir);
! free(eaddr);
! return b;
default:
bpf_error(
***************
*** 3070,3076 ****
alist = pcap_nametoaddr(name);
if (alist == NULL || *alist == NULL)
bpf_error("unknown host '%s'", name);
! return gen_gateway(eaddr, alist, proto, dir);
#else
bpf_error("'gateway' not supported in this configuration");
#endif /*INET6*/
--- 3076,3084 ----
alist = pcap_nametoaddr(name);
if (alist == NULL || *alist == NULL)
bpf_error("unknown host '%s'", name);
! b = gen_gateway(eaddr, alist, proto, dir);
! free(eaddr);
! return b;
#else
bpf_error("'gateway' not supported in this configuration");
#endif /*INET6*/
Index: grammar.y
===================================================================
RCS file: /tcpdump/master/libpcap/grammar.y,v
retrieving revision 1.70
diff -c -r1.70 grammar.y
*** grammar.y 2001/05/10 14:48:03 1.70
--- grammar.y 2001/07/03 19:11:33
***************
*** 188,195 ****
"in this configuration");
#endif /*INET6*/
}
! | EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
! | AID { $$.b = gen_acode($1, $$.q = $<blk>0.q); }
| not id { gen_not($2.b); $$ = $2; }
;
not: '!' { $$ = $<blk>0; }
--- 188,211 ----
"in this configuration");
#endif /*INET6*/
}
! | EID {
! $$.b = gen_ecode($1, $$.q = $<blk>0.q);
! /*
! * $1 was allocated by "pcap_ether_aton()",
! * so we must free it now that we're done
! * with it.
! */
! free($1);
! }
! | AID {
! $$.b = gen_acode($1, $$.q = $<blk>0.q);
! /*
! * $1 was allocated by "pcap_ether_aton()",
! * so we must free it now that we're done
! * with it.
! */
! free($1);
! }
| not id { gen_not($2.b); $$ = $2; }
;
not: '!' { $$ = $<blk>0; }