If blockdata_expand() fails, it frees the existing block chain
and returns zero. Each call to blockdata_expand() checks for the zero return,
and calls blockdata_free() as part of its clean-up, resulting in
a double-free and crash.
Thanks to fallrig for finding this.
This was functionally correct, but every call
malloced a new buffer and freed the previous one, rather
than only doing that when the buffer needed expansion.
I am attaching an incremental git-am ready patch to go on top your Git HEAD,
to fix all sorts of issues and make this conforming C99 with default
options set,
and fix another load of warnings you receive when setting the compiler
to pick the nits,
-pedantic-errors -std=c99 (or c11, c18, c2x).
It changes many void * to uint8_t * to make the "increment by bytes"
explicit.
You can't do:
void *foo;
// ...
foo += 2.
Timeouts for TCP connections to non-responive servers are very long.
This in not appropriate for DNS connections.
Set timeouts for connection setup, sending data and recieving data.
The timeouts for connection setup and sending data are set at 5 seconds.
For recieving the reply this is doubled, to take into account the
time for usptream to actually get the answer.
Thanks to Petr Menšík for pointing out this problem, and finding a better
and more portable solution than the one in place heretofore.
For ease of implementaion, dnsmasq has always forked a new process to
handle each incoming TCP connection. A side-effect of this is that any
DNS queries answered from TCP connections are not cached: when TCP
connections were rare, this was not a problem. With the coming of
DNSSEC, it's now the case that some DNSSEC queries have answers which
spill to TCP, and if, for instance, this applies to the keys for the
root then those never get cached, and performance is very bad. This
fix passes cache entries back from the TCP child process to the main
server process, and fixes the problem.