From 70ad7a2a18f5371981c377d0c1938e7b0a970655 Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 12 Oct 1999 19:51:08 +0000 Subject: [PATCH] Do not invoke __autosys indirectly from __procdgram. --- changelog | 6 ++++-- src/check.c | 4 +++- src/dlist.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/event.c | 34 +++++++++++++++++++------------- src/internal.h | 30 ++++++---------------------- src/query.c | 2 +- src/setup.c | 1 + 7 files changed, 88 insertions(+), 42 deletions(-) create mode 100644 src/dlist.h diff --git a/changelog b/changelog index b2a249e..f24e3c3 100644 --- a/changelog +++ b/changelog @@ -13,12 +13,14 @@ adns (0.5) unstable; urgency=medium * Better usage messages (and no default query domain) for adnstest. Bugfixes: + * Do not invoke __autosys indirectly from __procdgram (result: coredump + usually in memmove, unless adns_if_noautosys was used). + * Do not scramble innards when a query on the output queue is cancelled. * Mailboxes containing spaces in their names are quoted. * adns_rr_hostaddr naddrs is -1 on temporary failure (as documented). * Reject TXT RRs with no strings. - * Do not scramble innards when a query on the output queue is cancelled. * Correct error messages for qname CNAME foo, foo CNAME bar. - * Fixed typo in adns.h. + * Fixed typos in adns.h. General improvements: * Promise not to change fds in adns_beforepoll (if now is specified). diff --git a/src/check.c b/src/check.c index 25de10d..4d5e031 100644 --- a/src/check.c +++ b/src/check.c @@ -83,11 +83,13 @@ static void checkc_global(adns_state ads) { case server_connecting: assert(ads->tcpsocket >= 0); case server_disconnected: /* fall through */ - assert(!ads->tcprecv.used); assert(!ads->tcpsend.used); + assert(!ads->tcprecv.used); + assert(!ads->tcprecv_skip); break; case server_ok: assert(ads->tcpsocket >= 0); + assert(ads->tcprecv_skip <= ads->tcprecv.used); break; default: assert(!"ads->tcpstate value"); diff --git a/src/dlist.h b/src/dlist.h new file mode 100644 index 0000000..de0268f --- /dev/null +++ b/src/dlist.h @@ -0,0 +1,53 @@ +/* + * dlist.h + * - macros for handling doubly linked lists + */ +/* + * This file is + * Copyright (C) 1997-1999 Ian Jackson + * + * It is part of adns, which is + * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1999 Tony Finch + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef ADNS_DLIST_H_INCLUDED +#define ADNS_DLIST_H_INCLUDED + +#define LIST_INIT(list) ((list).head= (list).tail= 0) +#define LINK_INIT(link) ((link).next= (link).back= 0) + +#define LIST_UNLINK_PART(list,node,part) \ + do { \ + if ((node)->part back) (node)->part back->part next= (node)->part next; \ + else (list).head= (node)->part next; \ + if ((node)->part next) (node)->part next->part back= (node)->part back; \ + else (list).tail= (node)->part back; \ + } while(0) + +#define LIST_LINK_TAIL_PART(list,node,part) \ + do { \ + (node)->part next= 0; \ + (node)->part back= (list).tail; \ + if ((list).tail) (list).tail->part next= (node); else (list).head= (node); \ + (list).tail= (node); \ + } while(0) + +#define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,) +#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,) + +#endif diff --git a/src/event.c b/src/event.c index fc8aa81..6ddf492 100644 --- a/src/event.c +++ b/src/event.c @@ -48,7 +48,7 @@ void adns__tcp_closenext(adns_state ads) { serv= ads->tcpserver; close(ads->tcpsocket); ads->tcpstate= server_disconnected; - ads->tcprecv.used= ads->tcpsend.used= 0; + ads->tcprecv.used= ads->tcprecv_skip= ads->tcpsend.used= 0; ads->tcpserver= (serv+1)%ads->nservers; } @@ -97,6 +97,7 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { assert(ads->tcpstate == server_disconnected); assert(!ads->tcpsend.used); assert(!ads->tcprecv.used); + assert(!ads->tcprecv_skip); proto= getprotobyname("tcp"); if (!proto) { adns__diag(ads,-1,0,"unable to find protocol no. for TCP !"); return; } @@ -240,7 +241,7 @@ int adns__pollfds(adns_state ads, struct pollfd pollfds_buf[MAX_POLLFDS]) { } int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { - int skip, want, dgramlen, r, udpaddrlen, serv; + int want, dgramlen, r, udpaddrlen, serv, old_skip; byte udpbuf[DNS_MAXUDP]; struct sockaddr_in udpaddr; @@ -252,22 +253,26 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { break; case server_ok: if (fd != ads->tcpsocket) break; - skip= 0; + assert(!ads->tcprecv_skip); for (;;) { - if (ads->tcprecv.usedtcprecv.buf[skip]<<8) | ads->tcprecv.buf[skip+1]; - if (ads->tcprecv.usedtcprecv.used >= ads->tcprecv_skip+2) { + dgramlen= ((ads->tcprecv.buf[ads->tcprecv_skip]<<8) | + ads->tcprecv.buf[ads->tcprecv_skip+1]); + if (ads->tcprecv.used >= ads->tcprecv_skip+2+dgramlen) { + old_skip= ads->tcprecv_skip; + ads->tcprecv_skip += 2+dgramlen; + adns__procdgram(ads, ads->tcprecv.buf+old_skip+2, + dgramlen, ads->tcpserver, 1,*now); + continue; } else { - adns__procdgram(ads,ads->tcprecv.buf+skip+2,dgramlen,ads->tcpserver,1,*now); - skip+= 2+dgramlen; continue; + want= 2+dgramlen; } + } else { + want= 2; } - ads->tcprecv.used -= skip; - memmove(ads->tcprecv.buf,ads->tcprecv.buf+skip,ads->tcprecv.used); - skip= 0; + ads->tcprecv.used -= ads->tcprecv_skip; + memmove(ads->tcprecv.buf,ads->tcprecv.buf+ads->tcprecv_skip,ads->tcprecv.used); + ads->tcprecv_skip= 0; if (!adns__vbuf_ensure(&ads->tcprecv,want)) { r= ENOMEM; goto xit; } assert(ads->tcprecv.used <= ads->tcprecv.avail); if (ads->tcprecv.used == ads->tcprecv.avail) continue; @@ -345,6 +350,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { case server_connecting: if (fd != ads->tcpsocket) break; assert(ads->tcprecv.used==0); + assert(ads->tcprecv_skip==0); for (;;) { if (!adns__vbuf_ensure(&ads->tcprecv,1)) { r= ENOMEM; goto xit; } r= read(ads->tcpsocket,&ads->tcprecv.buf,1); diff --git a/src/internal.h b/src/internal.h index 89327ec..5fdea89 100644 --- a/src/internal.h +++ b/src/internal.h @@ -43,6 +43,7 @@ typedef unsigned char byte; #include #include "adns.h" +#include "dlist.h" /* Configuration and constants */ @@ -279,7 +280,7 @@ struct adns__state { adns_query forallnext; int nextid, udpsocket, tcpsocket; vbuf tcpsend, tcprecv; - int nservers, nsortlist, nsearchlist, searchndots, tcpserver; + int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip; enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate; struct timeval tcptimeout; struct sigaction stdsigpipe; @@ -631,7 +632,10 @@ void adns__tcp_closenext(adns_state ads); void adns__tcp_tryconnect(adns_state ads, struct timeval now); void adns__autosys(adns_state ads, struct timeval now); -/* Make all the system calls we want to if the application wants us to. */ +/* Make all the system calls we want to if the application wants us to. + * Must not be called from within adns internal processing functions, + * lest we end up in recursive descent ! + */ void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, struct timeval *tv_buf); @@ -680,28 +684,6 @@ static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; } (( ((sz)+sizeof(union maxalign)-1) / sizeof(union maxalign) ) \ * sizeof(union maxalign) ) -#define LIST_INIT(list) ((list).head= (list).tail= 0) -#define LINK_INIT(link) ((link).next= (link).back= 0) - -#define LIST_UNLINK_PART(list,node,part) \ - do { \ - if ((node)->part back) (node)->part back->part next= (node)->part next; \ - else (list).head= (node)->part next; \ - if ((node)->part next) (node)->part next->part back= (node)->part back; \ - else (list).tail= (node)->part back; \ - } while(0) - -#define LIST_LINK_TAIL_PART(list,node,part) \ - do { \ - (node)->part next= 0; \ - (node)->part back= (list).tail; \ - if ((list).tail) (list).tail->part next= (node); else (list).head= (node); \ - (list).tail= (node); \ - } while(0) - -#define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,) -#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,) - #define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff) #define GET_B(cb,tv) ((tv)= GETIL_B((cb))) #define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv)) diff --git a/src/query.c b/src/query.c index 53eecd9..b9e6d4d 100644 --- a/src/query.c +++ b/src/query.c @@ -105,7 +105,6 @@ static void query_submit(adns_state ads, adns_query qu, memcpy(qu->query_dgram,qu->vb.buf,qu->vb.used); adns__query_send(qu,now); - adns__autosys(ads,now); } adns_status adns__internal_submit(adns_state ads, adns_query *query_r, @@ -243,6 +242,7 @@ int adns_submit(adns_state ads, } query_simple(ads,qu, owner,ol, typei,flags, now); } + adns__autosys(ads,now); adns__consistency(ads,qu,cc_entex); return 0; diff --git a/src/setup.c b/src/setup.c index 8604f8e..0e3e7da 100644 --- a/src/setup.c +++ b/src/setup.c @@ -469,6 +469,7 @@ static int init_begin(adns_state *ads_r, adns_initflags flags, FILE *diagfile) { ads->udpsocket= ads->tcpsocket= -1; adns__vbuf_init(&ads->tcpsend); adns__vbuf_init(&ads->tcprecv); + ads->tcprecv_skip= 0; ads->nservers= ads->nsortlist= ads->nsearchlist= ads->tcpserver= 0; ads->searchndots= 1; ads->tcpstate= server_disconnected; -- 2.30.2