On Jun 20, 2013, at 1:05 PM, Nadav Vinik <nadav...@gmail.com> wrote:

> 
> 
> On 20 June 2013 22:47, Guy Harris <g...@alum.mit.edu> wrote:
> 
> On Jun 20, 2013, at 12:36 PM, Nadav Vinik <nadav...@gmail.com> wrote:
> 
> > Hoever if I change to pcap_close(&handle) I get the following error:
> 
> Because code that passes a pointer to a pointer to a pcap_t, rather than a 
> pointer to a pcap_t, to pcap_close() is erroneous code.
> 
> You cannot arrange that libpcap somehow make a pcap_t or a pointer to it 
> detectably invalid when you close the handle; if you want to know whether a 
> pcap_t has been closed, you will have to make your code explicitly mark it as 
> such.  For example, replace all occurrences of
> 
>         pcap_close(handle);
> 
> in your code with
> 
>         pcap_close(handle);
>         handle = NULL;
> 
> Back to the original question.
> 
> Is there a way to check if handle is already free?

No.  If it's freed, what that does to it depends on the implementation of 
free() on your platform.

However:

> my problem is that it become free even before it reach to pcap_close.

Are you certain that's really the case?

> see:
> https://mail.gnome.org/archives/vala-list/2013-June/msg00022.html

Which says:

> tmp18_ = pcap_next (_tmp16_, &_tmp17_);
>      (&header);
>     header = _tmp17_;
>     _tmp19_ = _tmp18_;
>     _tmp19__length1 = -1;
>     *//_tmp19_ = (g_free (_tmp19_), NULL);*

If that first line was really

        _tmp18_ = pcap_next (_tmp16_, &_tmp17_);

then that g_free() call is *WRONG WRONG WRONG*.  The return value of 
pcap_next() is *NOT* allocated by the pcap_next() call, it may well be a 
pointer into the *MIDDLE* of a buffer allocated by libpcap, or might be a 
pointer to a buffer that libpcap allocated for its own purposes and will use in 
future calls, and you *MUST NOT EVER EVER EVER EVER EVER EVER EVER EVER EVER 
EVER EVER* call free() or g_free() or anything else that frees memory on it; 
you must leave it up to libpcap to free whatever memory it's contained in.

In addition, you must not assume a pointer returned by the Nth call to 
pcap_next() will be valid after the N+1st call to pcap_next().

If that code was generated by the Vala compiler, either the compiler, or 
whatever file caused the compiler to generate code that hands the result of 
pcap_next() to g_free(), need to be fixed.

As for printing "handle is null", well, let's look at _pcap_close0():

> #define _pcap_close0(var) ((var == NULL) ? NULL : (var = (pcap_close (var),
> NULL)))

That code will set var to NULL if it's not already null; if it's not NULL, it 
will set it to the result of the C expression

        (pcap_close (var), NULL)

which evaluates to NULL with a side-effect of pcap_close() being called on its 
previous value.

I.e., _pcap_close0() does the exact "explicitly mark it as such" I was talking 
about.

On Linux, when libpcap uses the "turbopacket" (memory-mapped) mechanism to 
receive packets (which it does by default), pcap_next() copies the packet from 
the memory-mapped buffer into a buffer it allocated (because that's the only 
way to make sure it'll remain valid after the call that returns it, due to the 
way the memory-mapped mechanism works), and pcap_close() frees that buffer.

If something bogusly frees that buffer before pcap_close() is called, 
pcap_close() will attempt to free it, and get a double free error.

The *ONLY* correct way to fix this is *NEVER* to free the result of 
pcap_next().  I don't know how, in Vala, you say "this function returns a 
pointer to an array of Uint8s, but you must not ever free that what that 
pointer points to", but if that needs to be specified in the Vala code for 
pcap_next, and it's not being done, it needs to be done, and if it *is* being 
done, the Vala compiler is broken.
_______________________________________________
tcpdump-workers mailing list
tcpdump-workers@lists.tcpdump.org
https://lists.sandelman.ca/mailman/listinfo/tcpdump-workers

Reply via email to