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; }

Reply via email to