From 4fad263db72b6e675e82c84b56d81333240a7475 Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 26 Mar 2000 15:02:09 +0000 Subject: [PATCH] + Bugfixes: @@ -1,13 +1,26 @@ uadns (0.8) BETA; urgency=low + Bugfixes: * Spurious `server failure on unidentifiable query' warning suppressed. - * install-sh (from autoconf 2.12 Debian r13) included. * adnslogres: cast chars to unsigned char before using ctype.h macros. + * In _beforeselect, global failure now means zero timeout, and in + tcp_events, really never try to do anything with the TCP connection if + act is zero. This might possibly cause an infinite delay (ie, lockup) + if things go badly wrong *and* a really unlikely race happens. + * Test suite `lines of syscall left' value is correct; !0 is failure. + + Portability fixes: + * install-sh (from autoconf 2.12 Debian r13) included. + + Documentation improvements: * Security/performance note added, about local nameservers and DNSSEC. * Documented that adns_rr_info _rr_hostaddr ( ) for address list means permanent failure, and ? means temporary failure. * Typo (*now for now in _beforeselect description) in adns.h fixed. - * In _beforeselect, global system failure now produces zero timeout. + + Changes to produce more defensive code: + * In adns_wait, assert that the timeout is not infinite. + * Make qu->id start out as -2 when initially allocated. -- --- changelog | 17 +++++++++++++++-- regress/hplayback.c.m4 | 1 + regress/r1test | 13 ++++++++++--- src/event.c | 24 +++++++++++++++++------- src/internal.h | 8 ++++---- src/query.c | 2 +- 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/changelog b/changelog index a6fe195..d7868bb 100644 --- a/changelog +++ b/changelog @@ -1,13 +1,26 @@ uadns (0.8) BETA; urgency=low + Bugfixes: * Spurious `server failure on unidentifiable query' warning suppressed. - * install-sh (from autoconf 2.12 Debian r13) included. * adnslogres: cast chars to unsigned char before using ctype.h macros. + * In _beforeselect, global failure now means zero timeout, and in + tcp_events, really never try to do anything with the TCP connection if + act is zero. This might possibly cause an infinite delay (ie, lockup) + if things go badly wrong *and* a really unlikely race happens. + * Test suite `lines of syscall left' value is correct; !0 is failure. + + Portability fixes: + * install-sh (from autoconf 2.12 Debian r13) included. + + Documentation improvements: * Security/performance note added, about local nameservers and DNSSEC. * Documented that adns_rr_info _rr_hostaddr ( ) for address list means permanent failure, and ? means temporary failure. * Typo (*now for now in _beforeselect description) in adns.h fixed. - * In _beforeselect, global system failure now produces zero timeout. + + Changes to produce more defensive code: + * In adns_wait, assert that the timeout is not infinite. + * Make qu->id start out as -2 when initially allocated. -- diff --git a/regress/hplayback.c.m4 b/regress/hplayback.c.m4 index 97e951a..01e60db 100644 --- a/regress/hplayback.c.m4 +++ b/regress/hplayback.c.m4 @@ -78,6 +78,7 @@ static void Tensureinputfile(void) { fd= atoi(fdstr); Tinputfile= fdopen(fd,"r"); if (!Tinputfile) Tfailed("fdopen ADNS_TEST_IN_FD"); } + setvbuf(Tinputfile,0,_IONBF,0); if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); diff --git a/regress/r1test b/regress/r1test index de8db69..4315bf8 100755 --- a/regress/r1test +++ b/regress/r1test @@ -42,13 +42,20 @@ do then : else - failed=true + failwhy="$failwhy WRONG OUTPUT" fi done -if $failed +cat >"$ocase.leftover" +if egrep . /dev/null "$ocase.leftover" then - echo >&2 "FAILED $case - WRONG OUTPUT - lines of syscall remaining `wc -l`" + failwhy="$failwhy EXITED EARLY" +fi + +if [ "x$failwhy" != x ] +then + scremain="`wc -l <\"$ocase.leftover\"`" + echo >&2 "FAILED $case -$failwhy - lines of syscall remaining $scremain" mrc=2 exit fi diff --git a/src/event.c b/src/event.c index 7c610c7..885ab81 100644 --- a/src/event.c +++ b/src/event.c @@ -143,6 +143,17 @@ void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, return; } +static void inter_immed(struct timeval **tv_io, struct timeval *tvbuf) { + struct timeval *rbuf; + + if (!tv_io) return; + + rbuf= *tv_io; + if (!rbuf) { *tv_io= rbuf= tvbuf; } + + timerclear(rbuf); +} + static void inter_maxto(struct timeval **tv_io, struct timeval *tvbuf, struct timeval maxto) { struct timeval *rbuf; @@ -185,12 +196,7 @@ static void timeouts_queue(adns_state ads, int act, if (!timercmp(&now,&qu->timeout,>)) { inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); } else { - if (!act) { - tvbuf->tv_sec= 0; - tvbuf->tv_usec= 0; - *tv_io= tvbuf; - return; - } + if (!act) { inter_immed(tv_io,tvbuf); return; } LIST_UNLINK(*queue,qu); if (qu->state != query_tosend) { adns__query_fail(qu,adns_s_timeout); @@ -210,6 +216,7 @@ static void tcp_events(adns_state ads, int act, for (;;) { switch (ads->tcpstate) { case server_broken: + if (!act) { inter_immed(tv_io,tvbuf); return; } for (qu= ads->tcpw.head; qu; qu= nqu) { nqu= qu->next; assert(qu->state == query_tcpw); @@ -221,6 +228,7 @@ static void tcp_events(adns_state ads, int act, ads->tcpstate= server_disconnected; case server_disconnected: /* fall through */ if (!ads->tcpw.head) return; + if (!act) { inter_immed(tv_io,tvbuf); return; } adns__tcp_tryconnect(ads,now); break; case server_ok: @@ -231,7 +239,7 @@ static void tcp_events(adns_state ads, int act, timevaladd(&ads->tcptimeout,TCPIDLEMS); } case server_connecting: /* fall through */ - if (!timercmp(&now,&ads->tcptimeout,>)) { + if (!act || !timercmp(&now,&ads->tcptimeout,>)) { inter_maxtoabs(tv_io,tvbuf,now,ads->tcptimeout); return; } { @@ -253,6 +261,7 @@ static void tcp_events(adns_state ads, int act, abort(); } } + return; } void adns__timeouts(adns_state ads, int act, @@ -665,6 +674,7 @@ int adns_wait(adns_state ads, maxfd= 0; tvp= 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); adns_beforeselect(ads,&maxfd,&readfds,&writefds,&exceptfds,&tvp,&tvbuf,0); + assert(tvp); rsel= select(maxfd,&readfds,&writefds,&exceptfds,tvp); if (rsel==-1) { if (errno == EINTR) { diff --git a/src/internal.h b/src/internal.h index 643b86f..c766738 100644 --- a/src/internal.h +++ b/src/internal.h @@ -289,10 +289,10 @@ struct adns__state { server_ok, server_broken } tcpstate; struct timeval tcptimeout; - /* This will have tv_sec==0 if it is not valid. - * It will always be valid if tcpstate _connecting. - * When _ok, it will be nonzero if we are idle - * (ie, tcpw queue is empty) and counting down. + /* This will have tv_sec==0 if it is not valid. It will always be + * valid if tcpstate _connecting. When _ok, it will be nonzero if + * we are idle (ie, tcpw queue is empty), in which case it is the + * absolute time when we will close the connection. */ struct sigaction stdsigpipe; sigset_t stdsigmask; diff --git a/src/query.c b/src/query.c index a8423d7..aaadb21 100644 --- a/src/query.c +++ b/src/query.c @@ -66,7 +66,7 @@ static adns_query query_alloc(adns_state ads, const typeinfo *typei, adns__vbuf_init(&qu->search_vb); qu->search_origlen= qu->search_pos= qu->search_doneabs= 0; - qu->id= 0; + qu->id= -2; /* will be overwritten with real id before we leave adns */ qu->flags= flags; qu->retries= 0; qu->udpnextserver= 0; -- 2.30.2