From: Ian Jackson Date: Thu, 11 Jun 2020 14:47:17 +0000 (+0100) Subject: changelog: Document changes in 1.6.0 and finalise version number X-Git-Tag: adns-1.6.0^0 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=adns.git;a=commitdiff_plain;h=HEAD;hp=baa953c9d9107b862f8f66ac014c95b965e686e1 changelog: Document changes in 1.6.0 and finalise version number Signed-off-by: Ian Jackson --- diff --git a/.gitignore b/.gitignore index 973a480..89b05ff 100644 --- a/.gitignore +++ b/.gitignore @@ -29,12 +29,24 @@ client/adnsresfilter client/adnsresfilter_s dynamic/Makefile dynamic/libadns.so.* +regress/fuzzcat.d regress/Makefile regress/*_record regress/*_playback +regress/*_fuzz +regress/*_fuzzraw regress/output-*.* +regress/fuzz-* +regress/fuzzraw-* regress/pipe.out regress/pipe.err +regress/harness.h +regress/hcommon.c +regress/hplayback.c +regress/hrecord.c +regress/hfuzzraw.c +regress/hredirect.h +regress/hsyscalls.h src/Makefile src/config.h web diff --git a/INSTALL b/INSTALL index c4bdbf9..c360d89 100644 --- a/INSTALL +++ b/INSTALL @@ -67,7 +67,8 @@ containing tsearch, such as the GNU C library. It is best if tsearch uses an automatically-balancing tree algorithm, like the glibc version does. Simple binary trees may perform badly. -If you change the m4 input files in regress/ you may need GNU m4. +You will need an m4 that supports: -P, -I, patsubst, ifelse, include, +translit, and len. You will probably find that GNU Make is required. Please do not report this as a bug; install GNU Make instead. @@ -97,11 +98,10 @@ DNSSEC cryptographic signature checking. COPYRIGHT This file, INSTALL, contains installation instructions and other -details for adns. It is - Copyright (C) 1997-2000 Ian Jackson +details for adns. adns is - Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson Copyright (C) 2014 Mark Wooding Copyright (C) 1999-2000,2003,2006 Tony Finch [1] Copyright (C) 1991 Massachusetts Institute of Technology [2] diff --git a/Makefile.in b/Makefile.in index 9510b7b..976a159 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ # Makefile[.in] - top-level Makefile # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology @@ -24,7 +24,7 @@ include ./common.make # Remember to change ADNS_VERSION_STRING in client/client.h too, and # possibly library soname (MAJOR and MINOR in common.make.in). -DISTVERSION= 1.5.0 +DISTVERSION= 1.6.0 srcdir= @srcdir@ VPATH= @srcdir@ diff --git a/NEWS b/NEWS index 4cb9630..ce0e44e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +For later changes, please see the file `changelog' in the +source code toplevel. + + + +Changes in adns 1.5.2, since adns 1.5.1, are: + + Important security fixes, and other bugfixes. See changelog. + Changes in adns 1.5.1, since adns 1.5.0, are: Bugfixes. See changelog. diff --git a/README b/README index c045cae..26450aa 100644 --- a/README +++ b/README @@ -120,9 +120,9 @@ References and related projects Copyright and licensing - adns is Copyright 1997-2000,2003,2006,2014-2016 Ian Jackson, Copyright - 2014 Mark Wooding, Copyright 1999-2000,2003,2006 Tony Finch, and - Copyright (C) 1991 Massachusetts Institute of Technology. + adns is Copyright 1997-2000,2003,2006,2014-2016,2020 Ian Jackson, + Copyright 2014 Mark Wooding, Copyright 1999-2000,2003,2006 Tony Finch, + and Copyright 1991 Massachusetts Institute of Technology. adns 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 diff --git a/README.html b/README.html index 07123cd..d2048f1 100644 --- a/README.html +++ b/README.html @@ -187,9 +187,9 @@ replies to adns's queries.

Copyright and licensing

-adns is Copyright 1997-2000,2003,2006,2014-2016 Ian Jackson, -Copyright 2014 Mark Wooding, Copyright 1999-2000,2003,2006 Tony Finch, -and Copyright (C) 1991 Massachusetts Institute of Technology. +adns is Copyright 1997-2000,2003,2006,2014-2016,2020 Ian +Jackson, Copyright 2014 Mark Wooding, Copyright 1999-2000,2003,2006 +Tony Finch, and Copyright 1991 Massachusetts Institute of Technology.

diff --git a/RELEASE-CHECKLIST b/RELEASE-CHECKLIST index cdd3461..e38d55c 100755 --- a/RELEASE-CHECKLIST +++ b/RELEASE-CHECKLIST @@ -3,7 +3,6 @@ # # * Maybe rerun autoconf # * Ensure changelog reflects changes -# * Ensure NEWS reflects changes # * Maybe update copyright dates # * Maybe update MAJOR and/or MINOR in common.make.in # * Update DISTVERSION in Makefile.in diff --git a/acconfig.h b/acconfig.h index c3ed43d..bf65d57 100644 --- a/acconfig.h +++ b/acconfig.h @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/aclocal.m4 b/aclocal.m4 index 4a4d074..c23a005 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,7 +1,7 @@ # aclocal.m4 - package-specific macros for autoconf # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..14efa37 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,4 @@ +#!/bin/sh +set -e +autoheader +autoconf diff --git a/changelog b/changelog index f4886ea..aa09bd0 100644 --- a/changelog +++ b/changelog @@ -1,4 +1,81 @@ -adns (1.5.1~~) UPSTREAM; urgency=low +adns (1.6.0) UPSTREAM; urgency=medium + + Bugfixes: + * adnshost: Support --reverse in -f mode input stream + * timeout robustness against clock skew: track query start time and + duration. Clock instability may now only cause spurious timeouts + rather than indefinite hangs or even assertion failures. + + New features: + * adnshost: Offer ability to set adns checkc flags + * adnslogres: Honour --checkc-freq (if it comes first) + * adnsresfilter: Honour --checkc-freq and --checkc-entex + * time handling: Support use of CLOCK_MONOTONIC via an init flag. + * adns_str* etc.: Improve robustness; more allowable inputs values. + + Build system improvements: + * clean targets: Delete $(TARGETS) too! + * Remove all m4 output files from the distributed source tree. + * Support DESTDIR=/some/absolute/path on `make install'. + * Provide autogen.sh. + * Rerun autoheader and autoconf (2.69). + + Internal changes: + * adnshost: adh-opts.c: Whitespace adjustments to option table + + Tests: + * New tests for fixes in 1.5.3. + * Fixes to test harness to avoid false positives during fuzzing. + * Other changes to support use with AFL. + * Many supporting improvements and refactorings. + * Fix skipped tests ($$ reference in Makefile) + + + -- Ian Jackson Thu, 11 Jun 2020 15:49:39 +0100 + +adns (1.5.2) UPSTREAM; urgency=medium + + * Important security fixes: + CVE-2017-9103 CVE-2017-9104 CVE-2017-9105 CVE-2017-9109: + Vulnerable applications: all adns callers. + Exploitable by: the local recursive resolver. + Likely worst case: Remote code execution. + CVE-2017-9106: + Vulnerable applications: those that make SOA queries. + Exploitable by: upstream DNS data sources. + Likely worst case: DoS (crash of the adns-using application) + CVE-2017-9107: + Vulnerable applications: those that use adns_qf_quoteok_query. + Exploitable by: sources of query domain names. + Likely worst case: DoS (crash of the adns-using application) + CVE-2017-9108: + Vulnerable applications: adnshost. + Exploitable by: code responsible for framing the input. + Likely worst case: DoS (adnshost crashes at EOF). + All found by AFL 2.35b. Thanks to the University of Cambridge + Department of Applied Mathematics for computing facilities. + + Bugfixes: + * Do not include spurious external symbol `data' (fixes GCC10 build). + * If server sends TC flag over TCP, bail rather than retrying. + * Do not crash on certain strange resolv.conf contents. + * Fix various crashes if a global system failure occurs, or + adns_finish is called with outstanding queries. + * Correct a parsing error message very slightly. + * DNS packet parsing: Slight fix when packet is truncated. + * Fix ABI compatibility in string conversion of certain RR types. + * internal.h: Use `unsigned' for nextid; fixes theoretical C UB. + + Portability fix: + * common.make.in: add -Wno-unused-value. Fixes build with GCC9. + + Internal changes: + * Additional comments describing some internal code restrions. + * Robustness assert() against malfunctioning write() system call. + + -- Ian Jackson Thu, 11 Jun 2020 15:48:12 +0100 + +adns (1.5.1) UPSTREAM; urgency=medium * Portability fix for systems where socklen_t is bigger than int. * Fix for malicious optimisation of memcpy in test suite, which @@ -17,7 +94,7 @@ adns (1.5.1~~) UPSTREAM; urgency=low * Properly include harness.h in adnstest.c in regress/. Suppresses a couple of compiler warnings (implicit declaration of Texit, etc.) - -- + -- Ian Jackson Fri, 12 Aug 2016 22:53:59 +0100 adns (1.5.0) UPSTREAM; urgency=low diff --git a/client/Makefile.in b/client/Makefile.in index fa3a002..6264482 100644 --- a/client/Makefile.in +++ b/client/Makefile.in @@ -1,7 +1,7 @@ # client/Makefile - client program(s) Makefile # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/client/addrtext.c b/client/addrtext.c index 212dece..6f893b1 100644 --- a/client/addrtext.c +++ b/client/addrtext.c @@ -22,7 +22,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/client/adh-main.c b/client/adh-main.c index 9709be2..0d1d57e 100644 --- a/client/adh-main.c +++ b/client/adh-main.c @@ -5,7 +5,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -129,7 +129,7 @@ void of_type(const struct optioninfo *oi, const char *arg, const char *arg2) { static void process_optarg(const char *arg, const char *const **argv_p, - const char *value) { + char *value) { const struct optioninfo *oip; const char *arg2; int invert; @@ -148,9 +148,17 @@ static void process_optarg(const char *arg, if (!arg) usageerr("option --%s requires a value argument",oip->lopt); arg2= 0; } else if (oip->type == ot_funcarg2) { - assert(argv_p); - arg= *++(*argv_p); - arg2= arg ? *++(*argv_p) : 0; + if (argv_p) { + arg= *++(*argv_p); + arg2= arg ? *++(*argv_p) : 0; + } else if (value) { + arg= value; + char *space= strchr(value,' '); + if (space) *space++= 0; + arg2= space; + } else { + arg= 0; + } if (!arg || !arg2) usageerr("option --%s requires two more arguments", oip->lopt); } else { @@ -206,7 +214,7 @@ static void read_stdin(void) { if (r == 0) { if (used) { /* fake up final newline */ - buf[used++]= '\n'; + buf[used]= '\n'; r= 1; } else { ov_pipe= 0; diff --git a/client/adh-opts.c b/client/adh-opts.c index 2f1f183..590fce4 100644 --- a/client/adh-opts.c +++ b/client/adh-opts.c @@ -5,7 +5,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -32,6 +32,7 @@ int ov_verbose= 0; adns_rrtype ov_type= adns_r_none; int ov_search=0, ov_qc_query=0, ov_qc_anshost=0, ov_qc_cname=1; int ov_tcp=0, ov_cname=0, ov_afflags=0, ov_v6map=0, ov_format=fmt_default; +int ov_checkc=0; char *ov_id= 0; struct perqueryflags_remember ov_pqfr = { 1,1,1, tm_none }; @@ -45,11 +46,11 @@ static const struct optioninfo global_options[]= { "a", "asynch", &ov_asynch, 1 }, { ot_desconly, "answer/error output format and destination (see below):" }, - { ot_value, "Answers to stdout, errors as messages to stderr (default)", + { ot_value, "Answers to stdout, errors as messages to stderr (default)", "Fs", "fmt-simple", &ov_format, fmt_simple }, - { ot_value, "Answers and errors both to stdout in parseable format", + { ot_value, "Answers and errors both to stdout in parseable format", "Fi", "fmt-inline", &ov_format, fmt_inline }, - { ot_value, "Fully-parseable output format (default for --asynch)", + { ot_value, "Fully-parseable output format (default for --asynch)", "Fa", "fmt-asynch", &ov_format, fmt_asynch }, { ot_desconly, "global verbosity level:" }, @@ -59,6 +60,13 @@ static const struct optioninfo global_options[]= { "Vn", "no-quiet", &ov_verbose, 0 }, { ot_value, "Debugging mode", "Vd", "debug", &ov_verbose, adns_if_debug }, + + { ot_value, "Do not do for-developer consistency checks", + 0, "no-checkc", &ov_checkc, 0 }, + { ot_value, "Do for-developer consistency checks", + 0, "checkc", &ov_checkc, adns_if_checkc_freq }, + { ot_value, "Do for-developer consistency checks very often", + 0, "checkc-freq", &ov_checkc, adns_if_checkc_freq }, { ot_desconly, "other global options:" }, { ot_funcarg, "Configuration to use instead of /etc/resolv.conf", @@ -127,7 +135,7 @@ static const struct optioninfo perquery_options[]= { { ot_desconly, "asynchronous/pipe mode options:" }, { ot_funcarg, "Set , default is decimal sequence starting 0", 0, "asynch-id", 0,0, &of_asynch_id, "id" }, - { ot_funcarg, "Cancel the query with id (no error if not found)", + { ot_funcarg, "Cancel the query with id (no error if not found)", 0, "cancel-id", 0,0, &of_cancel_id, "id" }, { ot_end } diff --git a/client/adh-query.c b/client/adh-query.c index 03f97b1..f24c573 100644 --- a/client/adh-query.c +++ b/client/adh-query.c @@ -5,7 +5,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -40,7 +40,7 @@ void ensure_adns_init(void) { if (signal(SIGPIPE,SIG_IGN) == SIG_ERR) sysfail("ignore SIGPIPE",errno); - initflags= adns_if_noautosys|adns_if_nosigpipe|ov_verbose; + initflags= adns_if_noautosys|adns_if_nosigpipe|ov_verbose|ov_checkc; if (!ov_env) initflags |= adns_if_noenv; if (config_text) { diff --git a/client/adnsheloex.c b/client/adnsheloex.c index 5c0befe..93e3b91 100644 --- a/client/adnsheloex.c +++ b/client/adnsheloex.c @@ -7,7 +7,7 @@ * Copyright (C) 2004 Tony Finch * * It is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/client/adnshost.h b/client/adnshost.h index e68ecb7..fd2d80d 100644 --- a/client/adnshost.h +++ b/client/adnshost.h @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -82,6 +82,7 @@ extern int ov_verbose; extern adns_rrtype ov_type; extern int ov_search, ov_qc_query, ov_qc_anshost, ov_qc_cname; extern int ov_tcp, ov_cname, ov_afflags, ov_v6map, ov_format; +extern int ov_checkc; extern char *ov_id; extern struct perqueryflags_remember ov_pqfr; diff --git a/client/adnslogres.c b/client/adnslogres.c index 4ab81ee..750a198 100644 --- a/client/adnslogres.c +++ b/client/adnslogres.c @@ -5,10 +5,10 @@ /* * This file is * Copyright (C) 1999-2000 Tony Finch - * Copyright (C) 1999-2000 Ian Jackson + * Copyright (C) 1999-2000,2020 Ian Jackson * * It is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -61,6 +61,7 @@ /* option flags */ #define OPT_DEBUG 1 #define OPT_POLL 2 +#define OPT_CHECKC 4 static const char *const progname= "adnslogres"; static const char *config_text; @@ -170,7 +171,8 @@ static void proclog(FILE *inf, FILE *outf, int maxpending, int opts) { logline *head, *tail, *line; adns_initflags initflags; - initflags= (opts & OPT_DEBUG) ? adns_if_debug : 0; + initflags= (((opts & OPT_DEBUG) ? adns_if_debug : 0) | + ((opts & OPT_CHECKC) ? adns_if_checkc_entex : 0)); if (config_text) { errno= adns_init_strcfg(&adns, initflags, stderr, config_text); } else { @@ -238,6 +240,13 @@ int main(int argc, char *argv[]) { extern char *optarg; FILE *inf; + opts= 0; + + if (argv[1] && !strcmp(argv[1],"--checkc-freq")) { + opts|= OPT_CHECKC; + argv++; argc--; + } + if (argv[1] && !strncmp(argv[1],"--",2)) { if (!strcmp(argv[1],"--help")) { printhelp(stdout); @@ -251,7 +260,6 @@ int main(int argc, char *argv[]) { } maxpending= DEFMAXPENDING; - opts= 0; while ((c= getopt(argc, argv, "c:C:dp")) != -1) switch (c) { case 'c': diff --git a/client/adnsresfilter.c b/client/adnsresfilter.c index f3244b9..2303f6f 100644 --- a/client/adnsresfilter.c +++ b/client/adnsresfilter.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -171,6 +171,10 @@ static void parseargs(const char *const *argv) { config_text= arg; } else if (!strcmp(arg,"--debug")) { initflags |= adns_if_debug; + } else if (!strcmp(arg,"--checkc-freq")) { + initflags |= adns_if_checkc_freq; + } else if (!strcmp(arg,"--checkc-entex")) { + initflags |= adns_if_checkc_entex; } else if (!strcmp(arg,"--help")) { usage(); quitnow(0); } else if (!strcmp(arg,"--version")) { diff --git a/client/adnstest.c b/client/adnstest.c index faba1bc..2198ebc 100644 --- a/client/adnstest.c +++ b/client/adnstest.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/client/client.h b/client/client.h index 6e6fd8c..908d54a 100644 --- a/client/client.h +++ b/client/client.h @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -27,10 +27,10 @@ #ifndef CLIENT_H_INCLUDED #define CLIENT_H_INCLUDED -#define ADNS_VERSION_STRING "1.5.0" +#define ADNS_VERSION_STRING "1.6.0" #define COPYRIGHT_MESSAGE \ - "Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson\n" \ + "Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson\n" \ "Copyright (C) 2014 Mark Wooding\n" \ "Copyright (C) 1999-2000,2003,2006 Tony Finch\n" \ "Copyright (C) 1991 Massachusetts Institute of Technology\n" \ diff --git a/client/fanftest.c b/client/fanftest.c index 6d6964b..2d9e6fb 100644 --- a/client/fanftest.c +++ b/client/fanftest.c @@ -8,7 +8,7 @@ * Copyright (C) 1999-2000 Ian Jackson * * It is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/common.make.in b/common.make.in index baced41..d5188d9 100644 --- a/common.make.in +++ b/common.make.in @@ -2,7 +2,7 @@ # used by autoconf/configure to generate settings.make # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology @@ -22,7 +22,7 @@ # along with this program; if not, write to the Free Software Foundation. MAJOR= 1 -MINOR= 5 +MINOR= 6 SHLIBFILE= @SHLIBFILE@ SHLIBSONAME= @SHLIBSONAME@ SHLIBFORLINK= @SHLIBFORLINK@ @@ -33,7 +33,7 @@ LDFLAGS= $(AUTOLDFLAGS) $(DIRLDFLAGS) $(XLDFLAGS) LDLIBS= @LIBS@ $(XLIBS) AUTOCFLAGS= @CFLAGS@ AUTOLDFLAGS= @LDFLAGS@ -WARNS= @WARNS@ +WARNS= @WARNS@ -Wno-unused-value #WERROR= -Werror M4= m4 @@ -45,11 +45,22 @@ MKSHLIB_1= @MKSHLIB_1@ MKSHLIB_2= @MKSHLIB_2@ MKSHLIB_3= @MKSHLIB_3@ -prefix= @prefix@ -exec_prefix= @exec_prefix@ -bindir= @bindir@ -libdir= @libdir@ -includedir= @includedir@ +prefix := @prefix@ +exec_prefix := @exec_prefix@ +bindir := @bindir@ +libdir := @libdir@ +includedir := @includedir@ + +ifneq ($(DESTDIR),) +# autoconf likes to define some of these in terms of each other +# so if we want to add a prefix to each one we have to do it this way: +destdir_prefix=$(DESTDIR)/ +prefix := ${destdir_prefix}${prefix} +exec_prefix := ${destdir_prefix}${exec_prefix} +bindir := ${destdir_prefix}${bindir} +libdir := ${destdir_prefix}${libdir} +includedir := ${destdir_prefix}${includedir} +endif AC_INSTALL= @INSTALL@ ifeq ($(AC_INSTALL),./install-sh -c) diff --git a/configure b/configure index 825233c..b229e68 100755 --- a/configure +++ b/configure @@ -664,6 +664,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -735,6 +736,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' @@ -987,6 +989,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1124,7 +1135,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1277,6 +1288,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] diff --git a/configure.in b/configure.in index 712572e..2894cf9 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ # configure.in - input to autoconf # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/dynamic/Makefile.in b/dynamic/Makefile.in index 0784e6a..0083e1d 100644 --- a/dynamic/Makefile.in +++ b/dynamic/Makefile.in @@ -1,7 +1,7 @@ # dynamic/Makefile - dynamic library Makefile # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/regress/Makefile.in b/regress/Makefile.in index 21e7156..993c1af 100644 --- a/regress/Makefile.in +++ b/regress/Makefile.in @@ -1,7 +1,7 @@ # regress/Makefile[.in] - regression test Makefile # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology @@ -27,19 +27,23 @@ PROGS_SYSDEP= @PROGS_HAVE_TSEARCH@ CLIENTS= adnstest adnshost adnslogres $(PROGS_SYSDEP) AUTOCHDRS= harness.h hsyscalls.h hredirect.h -AUTOCSRCS= hrecord.c hplayback.c hcommon.c +AUTOCSRCS= hrecord.c hplayback.c hcommon.c hfuzzraw.c include ../settings.make include $(srcdir)/../src/adns.make DIRCFLAGS= -I../src -I$(srcdir) -I$(srcdir)/../src HCPPFLAGS= -DADNS_REGRESS_TEST -I. +#HCPPFLAGS+= -DFUZZRAW_SYNC REDIRLIBOBJS= $(addsuffix _d.o, $(basename $(LIBOBJS))) HARNLOBJS= hcommon.o $(REDIRLIBOBJS) -TARGETS= $(addsuffix _record, $(CLIENTS)) $(addsuffix _playback, $(CLIENTS)) +TARGETS= $(addsuffix _record, $(CLIENTS)) \ + $(addsuffix _playback, $(CLIENTS)) \ + $(addsuffix _fuzz, $(CLIENTS)) \ + $(addsuffix _fuzzraw, $(CLIENTS)) ADH_OBJS= adh-main_c.o adh-opts_c.o adh-query_c.o -ALL_OBJS= $(HARNLOBJS) dtest.o hrecord.o hplayback.o +ALL_OBJS= $(HARNLOBJS) dtest.o hrecord.o hplayback.o hnonfuzz.o hfuzz.o .PRECIOUS: $(AUTOCSRCS) $(AUTOCHDRS) @@ -51,15 +55,53 @@ check: $(TARGETS) $(addprefix check-,$(ALL_TESTS)) @echo @echo 'all tests passed or maybe skipped.' +checkfuzz: $(TARGETS) \ + $(addprefix checkfuzz-,$(ALL_TESTS)) \ + $(addprefix checkfuzzraw-,$(ALL_TESTS)) + @echo + @echo 'all fuzzes passed or maybe skipped.' +# this target is mostly useful as prep work for running the fuzzer; +# it doesn't really test any of adns + +fuzzcat.d: checkfuzz + $(srcdir)/categorisefuzz $(ALL_TESTS) + perl -ne 'print $$1,"\n" while m/\"([^"% ]{2,})\"/g' \ + $(srcdir)/../src/*.[ch] $(srcdir)/../client/*.[ch] \ + | sort -u >fuzzcat.d/dictionary + perl -p -e 'chomp;' \ + -e 's/[^0-9a-z-_]/sprintf "\\x%02x", ord $$&/ige;' \ + -e 's/^/l$$.="/; ' \ + -e 's/$$/"\n/;' \ + fuzzcat.d/dictionary >fuzzcat.d/dictionary.afl + check-%: case-%.sys - @srcdir=$(srcdir) $(srcdir)/r1test $* || test $? = 5 + @srcdir=$(srcdir) $(srcdir)/r1test $* || test $$? = 5 + +fuzz-%: case-%.sys $(TARGETS) make1fuzz shlib + srcdir=$(srcdir) $(srcdir)/make1fuzz $* + +fuzzraw-%: fuzz-% + +.PRECIOUS: fuzz-% + +checkfuzz-%: fuzz-% $(TARGETS) + @srcdir=$(srcdir) $(srcdir)/check1fuzz $< + +checkfuzzraw-%: fuzz-% $(TARGETS) + @srcdir=$(srcdir) $(srcdir)/check1fuzz $< LINK_CMD= $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ -%_record: %_c.o hrecord.o $(HARNLOBJS) +%_record: %_c.o hrecord.o hnonfuzz.o $(HARNLOBJS) $(LINK_CMD) -%_playback: %_c.o hplayback.o $(HARNLOBJS) +%_playback: %_c.o hplayback.o hnonfuzz.o $(HARNLOBJS) + $(LINK_CMD) + +%_fuzz: %_c.o hplayback.o hfuzz.o $(HARNLOBJS) + $(LINK_CMD) + +%_fuzzraw: %_c.o hfuzzraw.o hfuzz.o $(HARNLOBJS) $(LINK_CMD) .SECONDARY: $(addsuffix _c.o, $(filter-out adnshost, $(CLIENTS))) @@ -72,7 +114,13 @@ LINK_CMD= $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ # # See also Savannah #29620, http://savannah.gnu.org/bugs/index.php?29620 -adnshost_%: $(ADH_OBJS) h%.o $(HARNLOBJS) +adnshost_%: $(ADH_OBJS) h%.o hnonfuzz.o $(HARNLOBJS) + $(LINK_CMD) + +adnshost_fuzz: $(ADH_OBJS) hplayback.o hfuzz.o $(HARNLOBJS) + $(LINK_CMD) + +adnshost_fuzzraw: $(ADH_OBJS) hfuzzraw.o hfuzz.o $(HARNLOBJS) $(LINK_CMD) %_d.o: $(srcdir)/../src/%.c hredirect.h diff --git a/regress/addcases b/regress/addcases index 3da3aa3..e4fc73d 100755 --- a/regress/addcases +++ b/regress/addcases @@ -2,7 +2,7 @@ # usage: ./addcases ... # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/regress/case-adh-reverse-pipe.err b/regress/case-adh-reverse-pipe.err new file mode 100644 index 0000000..e2a64b2 --- /dev/null +++ b/regress/case-adh-reverse-pipe.err @@ -0,0 +1,4 @@ +adns debug: using nameserver 172.18.45.6 +1.0.0.127.in-addr.arpa has no TXT record +Error during DNS PTR lookup for 1.0.0.127.zen.spamhaus.org: Domain invalid for particular DNS query type +1.0.0.127.zen.spamhaus.org does not exist diff --git a/regress/case-adh-reverse-pipe.out b/regress/case-adh-reverse-pipe.out new file mode 100644 index 0000000..3d19c6a --- /dev/null +++ b/regress/case-adh-reverse-pipe.out @@ -0,0 +1,2 @@ +1.0.0.127.in-addr.arpa PTR localhost +rc=0 diff --git a/regress/case-adh-reverse-pipe.sys b/regress/case-adh-reverse-pipe.sys new file mode 100644 index 0000000..128817c --- /dev/null +++ b/regress/case-adh-reverse-pipe.sys @@ -0,0 +1,136 @@ +./adnshost default +-f + start 1481332828.558221 + socket domain=AF_INET type=SOCK_DGRAM + socket=6 + +0.000159 + fcntl fd=6 cmd=F_GETFL + fcntl=~O_NONBLOCK&... + +0.000051 + fcntl fd=6 cmd=F_SETFL O_NONBLOCK|... + fcntl=OK + +0.000035 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +12.-81227 + read fd=0 buflen=40 + read=OK + 2d2d7265 76657273 65203132 372e302e 302e3120 696e2d61 6464722e 61727061 + 0a. + +0.000148 + sendto fd=6 addr=172.18.45.6:53 + 311f0100 00010000 00000000 01310130 01300331 32370769 6e2d6164 64720461 + 72706100 00100001. + sendto=40 + +0.000190 + select max=7 rfds=[0,6] wfds=[] efds=[] to=1.999810 + select=1 rfds=[6] wfds=[] efds=[] + +1.-429555 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 311f8580 00010000 00010000 01310130 01300331 32370769 6e2d6164 64720461 + 72706100 00100001 c0120006 00010009 3a800026 096c6f63 616c686f 73740004 + 726f6f74 c0340000 00010009 3a800001 51800024 ea000009 3a80. + +0.000152 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000032 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +5.124113 + read fd=0 buflen=40 + read=OK + 2d742070 74720a. + +0.000126 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +1.658805 + read fd=0 buflen=40 + read=OK + 2d2d7265 76657273 65203132 372e302e 302e3120 696e2d61 6464722e 61727061 + 0a. + +0.000135 + sendto fd=6 addr=172.18.45.6:53 + 31200100 00010000 00000000 01310130 01300331 32370769 6e2d6164 64720461 + 72706100 000c0001. + sendto=40 + +0.000207 + select max=7 rfds=[0,6] wfds=[] efds=[] to=1.999793 + select=1 rfds=[6] wfds=[] efds=[] + +0.010520 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31208580 00010001 00010001 01310130 01300331 32370769 6e2d6164 64720461 + 72706100 000c0001 c00c000c 00010009 3a80000b 096c6f63 616c686f 737400c0 + 12000200 0100093a 800002c0 34c03400 01000100 093a8000 047f0000 01. + +0.000147 + sendto fd=6 addr=172.18.45.6:53 + 31210100 00010000 00000000 096c6f63 616c686f 73740000 010001. + sendto=27 + +0.000109 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000035 + select max=7 rfds=[0,6] wfds=[] efds=[] to=1.999709 + select=1 rfds=[6] wfds=[] efds=[] + +0.003062 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31218580 00010001 00010000 096c6f63 616c686f 73740000 010001c0 0c000100 + 0100093a 8000047f 000001c0 0c000200 0100093a 800002c0 0c. + +0.000130 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000035 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +7.-587512 + read fd=0 buflen=40 + read=OK + 2d2d7265 76657273 65203132 372e302e 302e3120 7a656e2e 7370616d 68617573 + 2e6f7267 0a. + +0.000112 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +2.190400 + read fd=0 buflen=40 + read=OK + 2d742070 74722d0a. + +0.000091 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +1.091179 + read fd=0 buflen=40 + read=OK + 2d2d7265 76657273 65203132 372e302e 302e3120 7a656e2e 7370616d 68617573 + 2e6f7267 0a. + +0.000125 + sendto fd=6 addr=172.18.45.6:53 + 31230100 00010000 00000000 01310130 01300331 3237037a 656e0873 70616d68 + 61757303 6f726700 000c0001. + sendto=44 + +0.000157 + select max=7 rfds=[0,6] wfds=[] efds=[] to=1.999843 + select=1 rfds=[6] wfds=[] efds=[] + +0.084632 + recvfrom fd=6 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31238183 00010000 00010000 01310130 01300331 3237037a 656e0873 70616d68 + 61757303 6f726700 000c0001 c0160006 00010000 000a0034 046e6565 6402746f + 046b6e6f 77046f6e 6c79000a 686f7374 6d617374 6572c01a 6016b217 00000e10 + 00000258 00069780 0000000a. + +0.000163 + recvfrom fd=6 buflen=512 + recvfrom=EAGAIN + +0.000032 + select max=7 rfds=[0,6] wfds=[] efds=[] to=null + select=1 rfds=[0] wfds=[] efds=[] + +10.-109673 + read fd=0 buflen=40 + read=OK + . + +0.000095 + close fd=6 + close=OK + +0.000060 + exit 6 diff --git a/regress/case-monotonic.err b/regress/case-monotonic.err new file mode 100644 index 0000000..e69de29 diff --git a/regress/case-monotonic.out b/regress/case-monotonic.out new file mode 100644 index 0000000..a55f101 --- /dev/null +++ b/regress/case-monotonic.out @@ -0,0 +1,32 @@ +adns debug [2264]: using nameserver 172.18.45.6 +v4.chiark.greenend.org.uk flags 0 type 1 A(-) submitted +v4.chiark.greenend.org.uk flags 0 type 2 NS(raw) submitted +v4.chiark.greenend.org.uk flags 0 type 5 CNAME(-) submitted +v4.chiark.greenend.org.uk flags 0 type 6 SOA(raw) submitted +v4.chiark.greenend.org.uk flags 0 type 12 PTR(raw) submitted +v4.chiark.greenend.org.uk flags 0 type 13 HINFO(-) submitted +v4.chiark.greenend.org.uk flags 0 type 15 MX(raw) submitted +v4.chiark.greenend.org.uk flags 0 type 16 TXT(-) submitted +v4.chiark.greenend.org.uk flags 0 type 17 RP(raw) submitted +v4.chiark.greenend.org.uk flags 0 type 65537 A(addr) submitted +v4.chiark.greenend.org.uk flags 0 type 65538 NS(+addr) submitted +v4.chiark.greenend.org.uk flags 0 type 65548 PTR(checked) submitted +v4.chiark.greenend.org.uk flags 0 type 65551 MX(+addr) submitted +v4.chiark.greenend.org.uk flags 0 type 131078 SOA(822) submitted +v4.chiark.greenend.org.uk flags 0 type 131089 RP(822) submitted +v4.chiark.greenend.org.uk flags 0 type PTR(checked): Domain invalid for particular DNS query type; nrrs=0; cname=$; owner=$; ttl=-1499395200 +v4.chiark.greenend.org.uk flags 0 type A(-): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type NS(raw): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type CNAME(-): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type SOA(raw): No such domain; nrrs=0; cname=$; owner=$; ttl=-1500000000 +v4.chiark.greenend.org.uk flags 0 type PTR(raw): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type HINFO(-): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type MX(raw): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type TXT(-): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type RP(raw): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type MX(+addr): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type NS(+addr): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type RP(822): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +v4.chiark.greenend.org.uk flags 0 type SOA(822): No such domain; nrrs=0; cname=$; owner=$; ttl=-1500000000 +v4.chiark.greenend.org.uk flags 0 type A(addr): No such domain; nrrs=0; cname=$; owner=$; ttl=-1499999700 +rc=0 diff --git a/regress/case-monotonic.sys b/regress/case-monotonic.sys new file mode 100644 index 0000000..ff56db1 --- /dev/null +++ b/regress/case-monotonic.sys @@ -0,0 +1,219 @@ +./adnstest default -0x0080 +v4.chiark.greenend.org.uk + start 1590336601.672124 + socket domain=AF_INET type=SOCK_DGRAM + socket=7 + +0.000038 + fcntl fd=7 cmd=F_GETFL + fcntl=~O_NONBLOCK&... + +0.000013 + fcntl fd=7 cmd=F_SETFL O_NONBLOCK|... + fcntl=OK + +0.000009 + sendto fd=7 addr=172.18.45.6:53 + 311f0100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 010001. + sendto=43 + +0.000084 + sendto fd=7 addr=172.18.45.6:53 + 31200100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 020001. + sendto=43 + +0.000068 + sendto fd=7 addr=172.18.45.6:53 + 31210100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 050001. + sendto=43 + +0.000055 + sendto fd=7 addr=172.18.45.6:53 + 31220100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 060001. + sendto=43 + +0.000041 + sendto fd=7 addr=172.18.45.6:53 + 31230100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0c0001. + sendto=43 + +0.000041 + sendto fd=7 addr=172.18.45.6:53 + 31240100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0d0001. + sendto=43 + +0.000070 + sendto fd=7 addr=172.18.45.6:53 + 31250100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0f0001. + sendto=43 + +0.000053 + sendto fd=7 addr=172.18.45.6:53 + 31260100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 100001. + sendto=43 + +0.000042 + sendto fd=7 addr=172.18.45.6:53 + 31270100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 110001. + sendto=43 + +0.000041 + sendto fd=7 addr=172.18.45.6:53 + 31290100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 010001. + sendto=43 + +0.000045 + sendto fd=7 addr=172.18.45.6:53 + 312a0100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 1c0001. + sendto=43 + +0.000026 + sendto fd=7 addr=172.18.45.6:53 + 312b0100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 020001. + sendto=43 + +0.000041 + sendto fd=7 addr=172.18.45.6:53 + 312d0100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0f0001. + sendto=43 + +0.000055 + sendto fd=7 addr=172.18.45.6:53 + 312e0100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 060001. + sendto=43 + +0.000040 + sendto fd=7 addr=172.18.45.6:53 + 312f0100 00010000 00000000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 110001. + sendto=43 + +0.000040 + select max=8 rfds=[7] wfds=[] efds=[] to=1.999258 + select=1 rfds=[7] wfds=[] efds=[] + +0.003052 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 311f8583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 010001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000055 + recvfrom fd=7 buflen=512 + recvfrom=EAGAIN + +0.000011 + select max=8 rfds=[7] wfds=[] efds=[] to=1.996224 + select=1 rfds=[7] wfds=[] efds=[] + +0.001024 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31208583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 020001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000049 + recvfrom fd=7 buflen=512 + recvfrom=EAGAIN + +0.000030 + select max=8 rfds=[7] wfds=[] efds=[] to=1.995189 + select=1 rfds=[7] wfds=[] efds=[] + +0.000586 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31218583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 050001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000036 + recvfrom fd=7 buflen=512 + recvfrom=EAGAIN + +0.000010 + select max=8 rfds=[7] wfds=[] efds=[] to=1.994612 + select=1 rfds=[7] wfds=[] efds=[] + +0.002366 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31228583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 060001c0 16000600 01000000 00002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000037 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31238583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0c0001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31248583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0d0001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31258583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0f0001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31268583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 100001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000027 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31278583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 110001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 31298583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 010001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000029 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 312d8583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 0f0001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000027 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 312b8583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 020001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 312a8583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 1c0001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 312f8583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 110001c0 16000600 01000001 2c002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000028 + recvfrom fd=7 buflen=512 + recvfrom=OK addr=172.18.45.6:53 + 312e8583 00010000 00010000 02763406 63686961 726b0867 7265656e 656e6403 + 6f726702 756b0000 060001c0 16000600 01000000 00002a03 736f6102 6e73c00f + 0a686f73 746d6173 746572c0 16ee6b28 85000070 8000001c 2000093a 80000151 + 80. + +0.000027 + recvfrom fd=7 buflen=512 + recvfrom=EAGAIN + +0.000022 + close fd=7 + close=OK + +0.000114 diff --git a/regress/categorisefuzz b/regress/categorisefuzz new file mode 100755 index 0000000..2208906 --- /dev/null +++ b/regress/categorisefuzz @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +out=fuzzcat.d + +rm -rf "$out" +mkdir "$out" + +categ () { + fuzz=$1 + exec <"$fuzz" + read nargs + read arg0len + read program + program="${program##*/}" + mkdir -p "$out/$program" + ln "$fuzz" "$out/$program"/. +} + +for case in "$@"; do + categ "fuzz-$case" + categ "fuzzraw-$case" +done diff --git a/regress/check1fuzz b/regress/check1fuzz new file mode 100755 index 0000000..5f1a0b2 --- /dev/null +++ b/regress/check1fuzz @@ -0,0 +1,52 @@ +#!/bin/sh +# usage: check1fuzz +# fuzz check script, for checking that one fuzz input works + +set -e +: ${srcdir=.} +. "$srcdir"/shlib + +fuzzfile="$1" + +exec <"$fuzzfile" + +case "$fuzzfile" in +fuzz-*) kind=f; case="${fuzzfile#fuzz-}" ;; +fuzzraw-*) kind=r; case="${fuzzfile#fuzzraw-}" ;; +*) printf >&2 '\nWRONG-FUZZ-%s\n' $fuzzfile; exit 1 ;; +esac + +desc="$case.$kind" + +read nargs +if [ "$nargs" = 0 ]; then printf "SKIPPED-$desc "; exit 5; fi + +read arg1len +read program + +case "$program" in +*/*) ;; +*) program="./$program" ;; +esac + +exec 3>output-$desc.trouble + +set +e +${program} <"$fuzzfile" >output-$desc.out.tmp 2>&3 +rc=$? +set -e + +if [ $rc = 0 ]; then + set +e + diff -u output-$desc.out.tmp case-$case.out >&3 + rc=$? + set -e +fi + +if [ $rc != 0 ]; then + printf >&2 '\nFAIL-%s\n' $desc + exit $rc +fi + +printf '%s ' "$desc" +rm -f output-$desc.trouble diff --git a/regress/checkall b/regress/checkall index a404fa8..169e317 100755 --- a/regress/checkall +++ b/regress/checkall @@ -3,7 +3,7 @@ # runs all test cases # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/regress/harness.h b/regress/harness.h deleted file mode 100644 index 85a936b..0000000 --- a/regress/harness.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef HARNESS_H_INCLUDED -#define HARNESS_H_INCLUDED -#include "internal.h" -#include "hsyscalls.h" -/* There is a Q function (Q for Question) for each such syscall; - * it constructs a string representing the call, and calls Q_str - * on it, or constructs it in vb and calls Q_vb; - */ -void Qselect( int max , const fd_set *rfds , const fd_set *wfds , const fd_set *efds , struct timeval *to ); -#ifdef HAVE_POLL -void Qpoll( const struct pollfd *fds , int nfds , int timeout ); -#endif -void Qsocket( int domain , int type ); -void Qfcntl( int fd , int cmd , long arg ); -void Qconnect( int fd , const struct sockaddr *addr , int addrlen ); -void Qbind( int fd , const struct sockaddr *addr , int addrlen ); -void Qlisten( int fd , int backlog ); -void Qclose( int fd ); -void Qsendto( int fd , const void *msg , int msglen , const struct sockaddr *addr , int addrlen ); -void Qrecvfrom( int fd , int buflen , int addrlen ); -void Qread( int fd , size_t buflen ); -void Qwrite( int fd , const void *buf , size_t len ); -void Q_vb(void); -extern void Tshutdown(void); -/* General help functions */ -void Tfailed(const char *why); -void Toutputerr(void); -void Tnomem(void); -void Tfsyscallr(const char *fmt, ...) PRINTFFORMAT(1,2); -void Tensurerecordfile(void); -void Tmust(const char *call, const char *arg, int cond); -void Tvbf(const char *fmt, ...) PRINTFFORMAT(1,2); -void Tvbvf(const char *fmt, va_list al); -void Tvbfdset(int max, const fd_set *set); -void Tvbpollfds(const struct pollfd *fds, int nfds); -void Tvbaddr(const struct sockaddr *addr, int addrlen); -void Tvbbytes(const void *buf, int len); -void Tvberrno(int e); -void Tvba(const char *str); -/* Shared globals */ -extern vbuf vb; -extern struct timeval currenttime; -extern const struct Terrno { const char *n; int v; } Terrnos[]; -/* Special cases */ -void Texit(int rv) NONRETURNING; -#endif diff --git a/regress/harness.h.m4 b/regress/harness.h.m4 index 5d17ca3..aa56184 100644 --- a/regress/harness.h.m4 +++ b/regress/harness.h.m4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - function and other declarations m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -39,6 +39,7 @@ hm_create_proto_q m4_define(`hm_syscall', `void Q$1(hm_args_massage($3,void));') m4_define(`hm_specsyscall', `') m4_include(`hsyscalls.i4') +hm_stdsyscall_close void Q_vb(void); @@ -50,7 +51,7 @@ void Tfailed(const char *why); void Toutputerr(void); void Tnomem(void); void Tfsyscallr(const char *fmt, ...) PRINTFFORMAT(1,2); -void Tensurerecordfile(void); +void Tensuresetup(void); void Tmust(const char *call, const char *arg, int cond); void Tvbf(const char *fmt, ...) PRINTFFORMAT(1,2); @@ -67,9 +68,15 @@ void Tvba(const char *str); extern vbuf vb; extern struct timeval currenttime; extern const struct Terrno { const char *n; int v; } Terrnos[]; +extern const int Tnerrnos; /* Special cases */ void Texit(int rv) NONRETURNING; +void Tcommonshutdown(void); +void Tmallocshutdown(void); +int Ttestinputfd(void); +void T_gettimeofday_hook(void); + #endif diff --git a/regress/hcommon.c b/regress/hcommon.c deleted file mode 100644 index 0aa3ffb..0000000 --- a/regress/hcommon.c +++ /dev/null @@ -1,314 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "harness.h" -#include "internal.h" -vbuf vb; -FILE *Toutputfile= 0; -struct timeval currenttime; -const struct Terrno Terrnos[]= { - { "EBADF", EBADF }, - { "EAGAIN", EAGAIN }, - { "EINPROGRESS", EINPROGRESS }, - { "EINTR", EINTR }, - { "EINVAL", EINVAL }, - { "EMSGSIZE", EMSGSIZE }, - { "ENOBUFS", ENOBUFS }, - { "ENOENT", ENOENT }, - { "ENOPROTOOPT", ENOPROTOOPT }, - { "ENOSPC", ENOSPC }, - { "EWOULDBLOCK", EWOULDBLOCK }, - { "EHOSTUNREACH", EHOSTUNREACH }, - { "ECONNRESET", ECONNRESET }, - { "ECONNREFUSED", ECONNREFUSED }, - { "EPIPE", EPIPE }, - { "ENOTSOCK", ENOTSOCK }, - { 0, 0 } -}; -static vbuf vbw; -int Hgettimeofday(struct timeval *tv, struct timezone *tz) { - Tensurerecordfile(); - Tmust("gettimeofday","tz",!tz); - *tv= currenttime; - return 0; -} -int Hwritev(int fd, const struct iovec *vector, size_t count) { - size_t i; - vbw.used= 0; - for (i=0; iiov_base,vector->iov_len)) Tnomem(); - } - return Hwrite(fd,vbw.buf,vbw.used); -} -void Qselect( int max , const fd_set *rfds , const fd_set *wfds , const fd_set *efds , struct timeval *to ) { - vb.used= 0; - Tvba("select"); - Tvbf(" max=%d",max); - Tvbf(" rfds="); Tvbfdset(max,rfds); - Tvbf(" wfds="); Tvbfdset(max,wfds); - Tvbf(" efds="); Tvbfdset(max,efds); - if (to) Tvbf(" to=%ld.%06ld",(long)to->tv_sec,(long)to->tv_usec); - else Tvba(" to=null"); - Q_vb(); -} -#ifdef HAVE_POLL -void Qpoll( const struct pollfd *fds , int nfds , int timeout ) { - vb.used= 0; - Tvba("poll"); - Tvbf(" fds="); Tvbpollfds(fds,nfds); - Tvbf(" timeout=%d",timeout); - Q_vb(); -} -#endif -void Qsocket( int domain , int type ) { - vb.used= 0; - Tvba("socket"); - Tvbf(domain==AF_INET ? " domain=AF_INET" : - domain==AF_INET6 ? " domain=AF_INET6" : - " domain=AF_???"); - Tvbf(type==SOCK_STREAM ? " type=SOCK_STREAM" : " type=SOCK_DGRAM"); - Q_vb(); -} -void Qfcntl( int fd , int cmd , long arg ) { - vb.used= 0; - Tvba("fcntl"); - Tvbf(" fd=%d",fd); - if (cmd == F_SETFL) { - Tvbf(" cmd=F_SETFL %s",arg & O_NONBLOCK ? "O_NONBLOCK|..." : "~O_NONBLOCK&..."); - } else if (cmd == F_GETFL) { - Tvba(" cmd=F_GETFL"); - } else { - Tmust("cmd","F_GETFL/F_SETFL",0); - } - Q_vb(); -} -void Qconnect( int fd , const struct sockaddr *addr , int addrlen ) { - vb.used= 0; - Tvba("connect"); - Tvbf(" fd=%d",fd); - Tvba(" addr="); Tvbaddr(addr,addrlen); - Q_vb(); -} -void Qbind( int fd , const struct sockaddr *addr , int addrlen ) { - vb.used= 0; - Tvba("bind"); - Tvbf(" fd=%d",fd); - Tvba(" addr="); Tvbaddr(addr,addrlen); - Q_vb(); -} -void Qlisten( int fd , int backlog ) { - vb.used= 0; - Tvba("listen"); - Tvbf(" fd=%d",fd); - Tvbf(" backlog=%d",backlog); - Q_vb(); -} -void Qclose( int fd ) { - vb.used= 0; - Tvba("close"); - Tvbf(" fd=%d",fd); - Q_vb(); -} -void Qsendto( int fd , const void *msg , int msglen , const struct sockaddr *addr , int addrlen ) { - vb.used= 0; - Tvba("sendto"); - Tvbf(" fd=%d",fd); - Tvba(" addr="); Tvbaddr(addr,addrlen); - Tvbbytes(msg,msglen); - Q_vb(); -} -void Qrecvfrom( int fd , int buflen , int addrlen ) { - vb.used= 0; - Tvba("recvfrom"); - Tvbf(" fd=%d",fd); - Tvbf(" buflen=%lu",(unsigned long)buflen); - Q_vb(); -} -void Qread( int fd , size_t buflen ) { - vb.used= 0; - Tvba("read"); - Tvbf(" fd=%d",fd); - Tvbf(" buflen=%lu",(unsigned long)buflen); - Q_vb(); -} -void Qwrite( int fd , const void *buf , size_t len ) { - vb.used= 0; - Tvba("write"); - Tvbf(" fd=%d",fd); - Tvbbytes(buf,len); - Q_vb(); -} -void Tvbaddr(const struct sockaddr *addr, int len) { - char buf[ADNS_ADDR2TEXT_BUFLEN]; - int err, port; - int sz= sizeof(buf); - err= adns_addr2text(addr, 0, buf,&sz, &port); - assert(!err); - Tvbf(strchr(buf, ':') ? "[%s]:%d" : "%s:%d", buf,port); -} -void Tvbbytes(const void *buf, int len) { - const byte *bp; - int i; - if (!len) { Tvba("\n ."); return; } - for (i=0, bp=buf; i0) { - Tvba(comma); - Tvbf("{fd=%d, events=",fds->fd); - Tvbpollevents(fds->events); - Tvba(", revents="); - Tvbpollevents(fds->revents); - Tvba("}"); - comma= ", "; - nfds--; fds++; - } - Tvba("]"); -} -void Tvberrno(int e) { - const struct Terrno *te; - for (te= Terrnos; te->n && te->v != e; te++); - assert(te->n); - Tvba(te->n); -} -void Tvba(const char *str) { - if (!adns__vbuf_appendstr(&vb,str)) Tnomem(); -} -void Tvbvf(const char *fmt, va_list al) { - char buf[1000]; - buf[sizeof(buf)-2]= '\t'; - vsnprintf(buf,sizeof(buf),fmt,al); - assert(buf[sizeof(buf)-2] == '\t'); - Tvba(buf); -} -void Tvbf(const char *fmt, ...) { - va_list al; - va_start(al,fmt); - Tvbvf(fmt,al); - va_end(al); -} -void Tmust(const char *call, const char *arg, int cond) { - if (cond) return; - fprintf(stderr,"adns test harness: case not handled: system call %s, arg %s",call,arg); - exit(-1); -} -void Tfailed(const char *why) { - fprintf(stderr,"adns test harness: failure: %s: %s\n",why,strerror(errno)); - exit(-1); -} -void Tnomem(void) { - Tfailed("unable to malloc/realloc"); -} -void Toutputerr(void) { - Tfailed("write error on test harness output"); -} -struct malloced { - struct malloced *next, *back; - size_t sz; - unsigned long count; - struct { double d; long ul; void *p; void (*fp)(void); } data; -}; -static unsigned long malloccount, mallocfailat; -static struct { struct malloced *head, *tail; } mallocedlist; -#define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head) -void *Hmalloc(size_t sz) { - struct malloced *newnode; - const char *mfavar; - char *ep; - assert(sz); - newnode= malloc(MALLOCHSZ + sz); if (!newnode) Tnomem(); - LIST_LINK_TAIL(mallocedlist,newnode); - newnode->sz= sz; - newnode->count= ++malloccount; - if (!mallocfailat) { - mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT"); - if (mfavar) { - mallocfailat= strtoul(mfavar,&ep,10); - if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value"); - } else { - mallocfailat= ~0UL; - } - } - assert(newnode->count != mallocfailat); - memset(&newnode->data,0xc7,sz); - return &newnode->data; -} -void Hfree(void *ptr) { - struct malloced *oldnode; - if (!ptr) return; - oldnode= (void*)((char*)ptr - MALLOCHSZ); - LIST_UNLINK(mallocedlist,oldnode); - memset(&oldnode->data,0x38,oldnode->sz); - free(oldnode); -} -void *Hrealloc(void *op, size_t nsz) { - struct malloced *oldnode; - void *np; - size_t osz; - if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; } - np= Hmalloc(nsz); - if (osz) memcpy(np,op, osz>nsz ? nsz : osz); - Hfree(op); - return np; -} -void Texit(int rv) { - struct malloced *loopnode; - Tshutdown(); - adns__vbuf_free(&vb); - adns__vbuf_free(&vbw); - if (mallocedlist.head) { - fprintf(stderr,"adns test harness: memory leaked:"); - for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next) - fprintf(stderr," %lu",loopnode->count); - putc('\n',stderr); - if (ferror(stderr)) exit(-1); - } - exit(rv); -} -void Hexit(int rv) { - vb.used= 0; - Tvbf("exit %d", rv); - Q_vb(); - Texit(0); -} -pid_t Hgetpid(void) { - return 2264; /* just some number */ -} diff --git a/regress/hcommon.c.m4 b/regress/hcommon.c.m4 index 6f29b41..74811a7 100644 --- a/regress/hcommon.c.m4 +++ b/regress/hcommon.c.m4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - routines used for both record and playback m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -36,6 +36,7 @@ m4_include(hmacros.i4) #include #include +#include #include "harness.h" #include "internal.h" @@ -64,14 +65,28 @@ const struct Terrno Terrnos[]= { { 0, 0 } }; +const int Tnerrnos= sizeof(Terrnos)/sizeof(Terrnos[0]) - 1; + static vbuf vbw; int Hgettimeofday(struct timeval *tv, struct timezone *tz) { - Tensurerecordfile(); + Tensuresetup(); Tmust("gettimeofday","tz",!tz); + T_gettimeofday_hook(); *tv= currenttime; return 0; } +int Hclock_gettime(clockid_t clk, struct timespec *ts) { + Tensuresetup(); + ts->tv_sec = currenttime.tv_sec; + ts->tv_nsec = currenttime.tv_usec * 1000 + 666; + switch (clk) { + case CLOCK_MONOTONIC: ts->tv_sec -= 1500000000; break; + case CLOCK_REALTIME: break; + default: Tmust("clock_gettime","clk",0); + } + return 0; +} int Hwritev(int fd, const struct iovec *vector, size_t count) { size_t i; @@ -132,6 +147,8 @@ m4_define(`hm_specsyscall', `') m4_include(`hsyscalls.i4') +hm_stdsyscall_close + void Tvbaddr(const struct sockaddr *addr, int len) { char buf[ADNS_ADDR2TEXT_BUFLEN]; int err, port; @@ -250,84 +267,8 @@ void Toutputerr(void) { Tfailed("write error on test harness output"); } -struct malloced { - struct malloced *next, *back; - size_t sz; - unsigned long count; - struct { double d; long ul; void *p; void (*fp)(void); } data; -}; - -static unsigned long malloccount, mallocfailat; -static struct { struct malloced *head, *tail; } mallocedlist; - -#define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head) - -void *Hmalloc(size_t sz) { - struct malloced *newnode; - const char *mfavar; - char *ep; - - assert(sz); - - newnode= malloc(MALLOCHSZ + sz); if (!newnode) Tnomem(); - - LIST_LINK_TAIL(mallocedlist,newnode); - newnode->sz= sz; - newnode->count= ++malloccount; - if (!mallocfailat) { - mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT"); - if (mfavar) { - mallocfailat= strtoul(mfavar,&ep,10); - if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value"); - } else { - mallocfailat= ~0UL; - } - } - assert(newnode->count != mallocfailat); - memset(&newnode->data,0xc7,sz); - return &newnode->data; -} - -void Hfree(void *ptr) { - struct malloced *oldnode; - - if (!ptr) return; - - oldnode= (void*)((char*)ptr - MALLOCHSZ); - LIST_UNLINK(mallocedlist,oldnode); - memset(&oldnode->data,0x38,oldnode->sz); - free(oldnode); -} - -void *Hrealloc(void *op, size_t nsz) { - struct malloced *oldnode; - void *np; - size_t osz; - - if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; } - np= Hmalloc(nsz); - if (osz) memcpy(np,op, osz>nsz ? nsz : osz); - Hfree(op); - return np; -} - -void Texit(int rv) { - struct malloced *loopnode; - - Tshutdown(); - adns__vbuf_free(&vb); - adns__vbuf_free(&vbw); - if (mallocedlist.head) { - fprintf(stderr,"adns test harness: memory leaked:"); - for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next) - fprintf(stderr," %lu",loopnode->count); - putc('\n',stderr); - if (ferror(stderr)) exit(-1); - } - exit(rv); -} - void Hexit(int rv) { + Tensuresetup(); vb.used= 0; Tvbf("exit %d", rv); Q_vb(); @@ -338,3 +279,9 @@ pid_t Hgetpid(void) { return 2264; /* just some number */ } +void Tcommonshutdown(void) { + Tshutdown(); + adns__vbuf_free(&vb); + adns__vbuf_free(&vbw); + Tmallocshutdown(); +} diff --git a/regress/hfuzz.c b/regress/hfuzz.c new file mode 100644 index 0000000..5d23368 --- /dev/null +++ b/regress/hfuzz.c @@ -0,0 +1,138 @@ +/* nfuzz.c + * (part of complex test harness, not of the library) + * - routines used for fuzzing (a kind of playback) + * + * This file is part of adns, which is + * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 2014 Mark Wooding + * Copyright (C) 1999-2000,2003,2006 Tony Finch + * Copyright (C) 1991 Massachusetts Institute of Technology + * (See the file INSTALL for full details.) + * + * 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 3, 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. + * + */ +/* + * We read from stdin: + * - command line arguments + * - syscall stream + * - stdin + */ + +#include + +#include "harness.h" + +extern int Hmain(int argc, char **argv); + +FILE *Hfopen(const char *path, const char *mode) { + /* we do not allow adns to open any files */ + errno = EPERM; + return 0; +} + +static int t_argc; +static char **t_argv; + +static FILE *t_stdin, *stdoutcopy; +static int t_sys_fd; + +static int bail(const char *msg) { + fprintf(stderr,"adns fuzz client: %s\n", msg); + exit(-1); +} +static int baile(const char *msg) { + fprintf(stderr,"adns fuzz client: %s: %s\n", msg, strerror(errno)); + exit(-1); +} + +static void chkin(void) { + if (ferror(stdin)) baile("read stdin"); + if (feof(stdin)) bail("eof on stdin"); +} + +static int getint(int max) { + int val; + char c; + chkin(); + int r = scanf("%d%c", &val, &c); + chkin(); + if (r != 2 || c != '\n') bail("bad input format: not integer"); + if (val < 0 || val > max) bail("bad input format: wrong value"); + return val; +} + +static void getnl(void) { + chkin(); + int c = getchar(); + chkin(); + if (c != '\n') bail("bad input format: expected newline"); +} + +int Ttestinputfd(void) { + return t_sys_fd; +} + +void Texit(int rv) { + fprintf(stdoutcopy,"rc=%d\n",rv); + if (ferror(stdoutcopy) || fclose(stdoutcopy)) baile("flush rc msg"); + Tcommonshutdown(); + exit(0); +} + +int main(int argc, char **argv) { + int i, l; + + if (argc!=1) + bail("usage: *_fuzz (no arguments)"); + + int stdoutcopyfd= dup(1); + if (stdoutcopyfd<0) baile("dup 1 again"); + stdoutcopy= fdopen(stdoutcopyfd,"w"); + if (!stdoutcopy) baile("fdopen 1 again"); + + t_argc = getint(50); + if (!t_argc) bail("too few arguments"); + t_argv = calloc(t_argc+1, sizeof(*t_argv)); + for (i=0; i0) { + int c = getchar(); + if (c==EOF) break; + fputc(c, t_stdin); + l--; + } + getnl(); + if (ferror(t_stdin) || fflush(t_stdin)) baile("write/flush t_stdin"); + if (fseek(stdin, 0, SEEK_CUR)) baile("seek-flush stdin"); + t_sys_fd = dup(0); if (t_sys_fd < 0) baile("dup stdin"); + if (dup2(fileno(t_stdin), 0)) baile("dup2 t_stdin"); + if (fseek(stdin, 0, SEEK_SET)) baile("rewind t_stdin"); + + int estatus = Hmain(t_argc, t_argv); + Texit(estatus); +} + +void Tmallocshutdown(void) { } +void *Hmalloc(size_t s) { assert(s); return malloc(s); } +void *Hrealloc(void *p, size_t s) { assert(s); return realloc(p,s); } +void Hfree(void *p) { free(p); } diff --git a/regress/hfuzzraw.c.m4 b/regress/hfuzzraw.c.m4 new file mode 100644 index 0000000..fa54c53 --- /dev/null +++ b/regress/hfuzzraw.c.m4 @@ -0,0 +1,349 @@ +m4_dnl hfuzzraw.c.m4 +m4_dnl (part of complex test harness, not of the library) +m4_dnl - routines for fuzzing + +m4_dnl This file is part of adns, which is +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 2014 Mark Wooding +m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch +m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology +m4_dnl (See the file INSTALL for full details.) +m4_dnl +m4_dnl This program is free software; you can redistribute it and/or modify +m4_dnl it under the terms of the GNU General Public License as published by +m4_dnl the Free Software Foundation; either version 3, or (at your option) +m4_dnl any later version. +m4_dnl +m4_dnl This program is distributed in the hope that it will be useful, +m4_dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +m4_dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +m4_dnl GNU General Public License for more details. +m4_dnl +m4_dnl You should have received a copy of the GNU General Public License +m4_dnl along with this program; if not, write to the Free Software Foundation. + +m4_include(hmacros.i4) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include "harness.h" + +static vbuf fdtab; +#define FDF_OPEN 001u +#define FDF_NONBLOCK 002u + +static FILE *Tinputfile, *traceout; +static int traceprint; + +static void Tflushtrace( void) { + if (fflush(traceout)) Toutputerr(); +} + +void Tensuresetup(void) { + static int done; + + if (done) return; + done++; + + int fd; + + fd = Ttestinputfd(); + assert(fd >= 0); + Tinputfile= fdopen(fd,"rb"); + if (!Tinputfile) Tfailed("fdopen record fd"); + + while (fdtab.used < 3) { + const char fdfstd = FDF_OPEN; + if (!adns__vbuf_append(&fdtab,&fdfstd,1)) Tnomem(); + } + + const char *traceprintstr= getenv("ADNS_TEST_FUZZRAW_TRACEPRINT"); + if (traceprintstr) { + traceprint= atoi(traceprintstr); + int tracefd= dup(2); + if (tracefd<0) Tfailed("dup for tracefd"); + traceout= fdopen(tracefd,"w"); + if (!traceout) Tfailed("fdopen for traceout"); + } +} + +void Q_vb(void) { + if (!traceprint) return; /* hcommon.c.m4 can call Q_vb directly */ + if (!adns__vbuf_append(&vb,"",1)) Tnomem(); + if (fprintf(traceout," %s\n",vb.buf) == EOF) Toutputerr(); + Tflushtrace(); +} + +static void Pformat(const char *what) { + fprintf(stderr,"adns test harness: format error in raw log input file: %s\n",what); + exit(-1); +} + +extern void Tshutdown(void) { + if (!Tinputfile) return; + int c= fgetc(Tinputfile); + if (c!=EOF) Pformat("unwanted additional syscall reply data"); + if (ferror(Tinputfile)) Tfailed("read test log input (at end)"); +} + +static void Pcheckinput(void) { + if (ferror(Tinputfile)) Tfailed("read test log input file"); + if (feof(Tinputfile)) Pformat("eof at syscall reply"); +} + +static void P_read_dump(const unsigned char *p0, size_t count, ssize_t d) { + fputs(" | ",traceout); + while (count) { + fprintf(traceout,"%02x", *p0); + p0 += d; + count--; + } +} + +static void P_read(void *p, size_t sz, const char *what) { + long pos = ftell(Tinputfile); + ssize_t got = fread(p,1,sz,Tinputfile); + Pcheckinput(); + assert(got==sz); + if (traceprint>1 && sz) { + fprintf(traceout,"%8lx %8s:",pos,what); + P_read_dump(p, sz, +1); + if (sz<=16) { + P_read_dump((const unsigned char *)p+sz-1, sz, -1); + } + fputs(" |\n",traceout); + Tflushtrace(); + } +} + +#define P_READ(x) (P_read(&(x), sizeof((x)), #x)) + +static unsigned P_fdf(int fd) { + assert(fd>=0 && fd=sizeof(buf)-1) Pformat("bad addr len"); + P_read(buf,al,"addrtext"); + buf[al]= 0; + P_READ(port); + r= adns_text2addr(buf,port, adns_qf_addrlit_scope_numeric, addr, &sl); + if (r==EINVAL) Pformat("bad addr text"); + assert(r==0 || r==ENOSPC); + *lenr = sl; +} + +static int Pbytes(byte *buf, int maxlen) { + int bl; + P_READ(bl); + if (bl<0 || bl>maxlen) Pformat("bad byte block len"); + P_read(buf, bl, "bytes"); + return bl; +} + +static void Pfdset(fd_set *set, int max, int *r_io) { + uint16_t fdmap; + int fd, nfdmap=0; + + if (!set) + return; + + for (fd=max-1; fd>=0; fd--) { + if (nfdmap==0) { + P_READ(fdmap); + nfdmap= 16; + } + _Bool y = fdmap & 1u; + fdmap >>= 1; + nfdmap--; + + if (!FD_ISSET(fd,set)) continue; + + P_fdf(fd); + + if (y) { + (*r_io)++; + } else { + FD_CLR(fd,set); + } + } +} + +#ifdef FUZZRAW_SYNC +static void Psync(const char *exp, char *got, size_t sz, const char *what) { + P_read(got,sz,"syscall"); + if (memcmp(exp,got,sz)) Pformat(what); +} +#endif +m4_define(`syscall_sync',` +#ifdef FUZZRAW_SYNC + hm_fr_syscall_ident($'`1) + static char sync_got[sizeof(sync_expect)]; + Psync(sync_expect, sync_got, sizeof(sync_got), "sync lost: program did $1"); +#endif +') + +#ifdef HAVE_POLL +static void Ppollfds(struct pollfd *fds, int nfds, int *r_io) { + int fd; + for (fd=0; fd0) { + errno= e; + return -1; + } else if (e) { + Pformat("wrong errno value"); + } + return 0; +} + +m4_define(`hm_syscall', ` + hm_create_proto_h +int H$1(hm_args_massage($3,void)) { + int r; + hm_create_nothing + $2 + + hm_create_hqcall_vars + $3 + + hm_create_hqcall_init($1) + $3 + + Tensuresetup(); + + if (traceprint) { + hm_create_hqcall_args + Q$1(hm_args_massage($3)); + } + + syscall_sync($'`1) + + m4_define(`hm_rv_succfail',` + r= P_succfail(); + if (r<0) return r; + ') + + m4_define(`hm_rv_any',` + hm_rv_succfail + if (!r) { + P_READ(r); + if (r<0) Pformat("negative nonerror syscall return"); + } + ') + m4_define(`hm_rv_len',` + hm_rv_succfail + ') + m4_define(`hm_rv_must',` + r= 0; + ') + m4_define(`hm_rv_select',`hm_rv_succfail') + m4_define(`hm_rv_poll',`hm_rv_succfail') + m4_define(`hm_rv_fcntl',` + unsigned flg = P_fdf(fd); + if (cmd == F_GETFL) { + r= (flg & FDF_NONBLOCK) ? O_NONBLOCK : 0; + } else if (cmd == F_SETFL) { + flg &= ~FDF_NONBLOCK; + if (arg & O_NONBLOCK) + flg |= FDF_NONBLOCK; + fdtab.buf[fd]= flg; + r= 0; + } else { + abort(); + } + ') + m4_define(`hm_rv_fd',` + hm_rv_succfail + if (!r) { + int newfd; + P_READ(newfd); + if (newfd<0 || newfd>1000) Pformat("new fd out of range"); + adns__vbuf_ensure(&fdtab, newfd+1); + if (fdtab.used <= newfd) { + memset(fdtab.buf+fdtab.used, 0, newfd+1-fdtab.used); + fdtab.used= newfd+1; + } + if (fdtab.buf[newfd]) Pformat("new fd already in use"); + fdtab.buf[newfd] |= FDF_OPEN; + r= newfd; + } + ') + m4_define(`hm_rv_wlen',` + hm_rv_any + if (r>$'`1) Pformat("write return value too large"); + ') + $2 + + hm_create_nothing + m4_define(`hm_arg_fdset_io',`Pfdset($'`1,$'`2,&r);') + m4_define(`hm_arg_pollfds_io',`Ppollfds($'`1,$'`2,&r);') + m4_define(`hm_arg_addr_out',`Paddr($'`1,$'`2);') + $3 + + hm_create_nothing + m4_define(`hm_arg_bytes_out',`r= Pbytes($'`2,$'`4);') + $3 + + hm_create_nothing + m4_define(`hm_rv_selectpoll',` + if (($'`1) && !r) Pformat("select/poll returning 0 but infinite timeout"); + ') + m4_define(`hm_rv_select',`hm_rv_selectpoll(!to)') + m4_define(`hm_rv_poll',`hm_rv_selectpoll(timeout<0)') + $2 + + return r; +} +') + +m4_define(`hm_specsyscall', `') + +m4_include(`hsyscalls.i4') + +int Hclose(int fd) { + syscall_sync(close) + P_fdf(fd); + fdtab.buf[fd]= 0; + return P_succfail(); +} diff --git a/regress/hmacros.i4 b/regress/hmacros.i4 index 123b8a3..3119f27 100644 --- a/regress/hmacros.i4 +++ b/regress/hmacros.i4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - common macros m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -54,6 +54,15 @@ m4_define(`hm_create_nothing', ` m4_define(`hm_arg_bytes_in', `') m4_define(`hm_arg_bytes_out', `') m4_define(`hm_arg_addr_out', `') + m4_define(`hm_rv_must', `') + m4_define(`hm_rv_any', `') + m4_define(`hm_rv_fd', `') + m4_define(`hm_rv_succfail', `') + m4_define(`hm_rv_len', `') + m4_define(`hm_rv_wlen', `hm_rv_any') + m4_define(`hm_rv_fcntl', `') + m4_define(`hm_rv_select', `hm_rv_any') + m4_define(`hm_rv_poll', `hm_rv_any') ') m4_define(`hm_create_proto_h',` @@ -103,7 +112,7 @@ m4_define(`hm_create_hqcall_init',` m4_define(`hm_arg_fcntl_cmd_arg',` Tmust("$1","$'`1",$'`1==F_SETFL || $'`1==F_GETFL); if ($'`1 == F_SETFL) { - va_start(al,$'`1); $'`2= va_arg(al,long); va_end(al); + va_start(al,$'`1); $'`2= va_arg(al,int); va_end(al); } else { $'`2= 0; }') @@ -138,3 +147,7 @@ m4_define(`hm_create_hqcall_args',` m4_define(`hm_arg_bytes_out', `$'`4') m4_define(`hm_arg_addr_out', `*$'`2') ') + +m4_define(`hm_fr_syscall_ident',` + static const char sync_expect[sizeof("$1")]= "$1\xee"; +') diff --git a/regress/hnonfuzz.c b/regress/hnonfuzz.c new file mode 100644 index 0000000..eff569e --- /dev/null +++ b/regress/hnonfuzz.c @@ -0,0 +1,116 @@ +/* nhonfuzz.c + * (part of complex test harness, not of the library) + * - routines used for record and playback but not for fuzzing + * + * This file is part of adns, which is + * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 2014 Mark Wooding + * Copyright (C) 1999-2000,2003,2006 Tony Finch + * Copyright (C) 1991 Massachusetts Institute of Technology + * (See the file INSTALL for full details.) + * + * 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 3, 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. + */ + +#include + +#include "harness.h" + +extern int Hmain(int argc, char **argv); +int main(int argc, char **argv) { return Hmain(argc, argv); } + +FILE *Hfopen(const char *path, const char *mode) { return fopen(path,mode); } + +void Texit(int rv) { + Tcommonshutdown(); + exit(rv); +} + +int Ttestinputfd(void) { + const char *fdstr= getenv("ADNS_TEST_IN_FD"); + if (!fdstr) return -1; + return atoi(fdstr); +} + +struct malloced { + struct malloced *next, *back; + size_t sz; + unsigned long count; + struct { double d; long ul; void *p; void (*fp)(void); } data; +}; + +static unsigned long malloccount, mallocfailat; +static struct { struct malloced *head, *tail; } mallocedlist; + +#define MALLOCHSZ ((char*)&mallocedlist.head->data - (char*)mallocedlist.head) + +void *Hmalloc(size_t sz) { + struct malloced *newnode; + const char *mfavar; + char *ep; + + assert(sz); + + newnode= malloc(MALLOCHSZ + sz); if (!newnode) Tnomem(); + + LIST_LINK_TAIL(mallocedlist,newnode); + newnode->sz= sz; + newnode->count= ++malloccount; + if (!mallocfailat) { + mfavar= getenv("ADNS_REGRESS_MALLOCFAILAT"); + if (mfavar) { + mallocfailat= strtoul(mfavar,&ep,10); + if (!mallocfailat || *ep) Tfailed("ADNS_REGRESS_MALLOCFAILAT bad value"); + } else { + mallocfailat= ~0UL; + } + } + assert(newnode->count != mallocfailat); + memset(&newnode->data,0xc7,sz); + return &newnode->data; +} + +void Hfree(void *ptr) { + struct malloced *oldnode; + + if (!ptr) return; + + oldnode= (void*)((char*)ptr - MALLOCHSZ); + LIST_UNLINK(mallocedlist,oldnode); + memset(&oldnode->data,0x38,oldnode->sz); + free(oldnode); +} + +void *Hrealloc(void *op, size_t nsz) { + struct malloced *oldnode; + void *np; + size_t osz; + + if (op) { oldnode= (void*)((char*)op - MALLOCHSZ); osz= oldnode->sz; } else { osz= 0; } + np= Hmalloc(nsz); + if (osz) memcpy(np,op, osz>nsz ? nsz : osz); + Hfree(op); + return np; +} + +void Tmallocshutdown(void) { + struct malloced *loopnode; + if (mallocedlist.head) { + fprintf(stderr,"adns test harness: memory leaked:"); + for (loopnode=mallocedlist.head; loopnode; loopnode=loopnode->next) + fprintf(stderr," %lu",loopnode->count); + putc('\n',stderr); + if (ferror(stderr)) exit(-1); + } +} diff --git a/regress/hplayback.c b/regress/hplayback.c deleted file mode 100644 index ed23542..0000000 --- a/regress/hplayback.c +++ /dev/null @@ -1,598 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "harness.h" -static FILE *Tinputfile, *Treportfile; -static vbuf vb2; -extern void Tshutdown(void) { - adns__vbuf_free(&vb2); -} -static void Tensurereportfile(void) { - const char *fdstr; - int fd; - if (Treportfile) return; - Treportfile= stderr; - fdstr= getenv("ADNS_TEST_REPORT_FD"); if (!fdstr) return; - fd= atoi(fdstr); - Treportfile= fdopen(fd,"a"); if (!Treportfile) Tfailed("fdopen ADNS_TEST_REPORT_FD"); -} -static void Psyntax(const char *where) { - fprintf(stderr,"adns test harness: syntax error in test log input file: %s\n",where); - exit(-1); -} -static void Pcheckinput(void) { - if (ferror(Tinputfile)) Tfailed("read test log input file"); - if (feof(Tinputfile)) Psyntax("eof at syscall reply"); -} -void Tensurerecordfile(void) { - const char *fdstr; - int fd; - int chars; - unsigned long sec, usec; - if (Tinputfile) return; - Tinputfile= stdin; - fdstr= getenv("ADNS_TEST_IN_FD"); - if (fdstr) { - 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(); - chars= -1; - sscanf(vb2.buf," start %lu.%lu%n",&sec,&usec,&chars); - if (chars==-1) Psyntax("start time invalid"); - currenttime.tv_sec= sec; - currenttime.tv_usec= usec; - if (vb2.buf[chars] != '\n') Psyntax("not newline after start time"); -} -static void Parg(const char *argname) { - int l; - if (vb2.buf[vb2.used++] != ' ') Psyntax("not a space before argument"); - l= strlen(argname); - if (memcmp(vb2.buf+vb2.used,argname,l)) Psyntax("argument name wrong"); - vb2.used+= l; - if (vb2.buf[vb2.used++] != '=') Psyntax("not = after argument name"); -} -static int Pstring_maybe(const char *string) { - int l; - l= strlen(string); - if (memcmp(vb2.buf+vb2.used,string,l)) return 0; - vb2.used+= l; - return 1; -} -static void Pstring(const char *string, const char *emsg) { - if (Pstring_maybe(string)) return; - Psyntax(emsg); -} -static int Perrno(const char *stuff) { - const struct Terrno *te; - int r; - char *ep; - for (te= Terrnos; te->n && strcmp(te->n,stuff); te++); - if (te->n) return te->v; - r= strtoul(stuff+2,&ep,10); - if (*ep) Psyntax("errno value not recognised, not numeric"); - return r; -} -static void P_updatetime(void) { - int chars; - unsigned long sec, usec; - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - chars= -1; - sscanf(vb2.buf," +%lu.%lu%n",&sec,&usec,&chars); - if (chars==-1) Psyntax("update time invalid"); - currenttime.tv_sec+= sec; - currenttime.tv_usec+= usec; - if (currenttime.tv_usec > 1000000) { - currenttime.tv_sec++; - currenttime.tv_usec -= 1000000; - } - if (vb2.buf[chars] != '\n') Psyntax("not newline after update time"); -} -static void Pfdset(fd_set *set, int max) { - int r, c; - char *ep; - if (!set) { - Pstring("null","null fdset pointer"); - return; - } - if (vb2.buf[vb2.used++] != '[') Psyntax("fd set start not ["); - FD_ZERO(set); - if (vb2.buf[vb2.used] == ']') { vb2.used++; return; } - for (;;) { - r= strtoul(vb2.buf+vb2.used,&ep,10); - if (r>=max) Psyntax("fd set member > max"); - if (ep == (char*)vb2.buf+vb2.used) Psyntax("empty entry in fd set"); - FD_SET(r,set); - vb2.used= ep - (char*)vb2.buf; - c= vb2.buf[vb2.used++]; - if (c == ']') break; - if (c != ',') Psyntax("fd set separator not ,"); - } -} -#ifdef HAVE_POLL -static int Ppollfdevents(void) { - int events; - if (Pstring_maybe("0")) return 0; - events= 0; - if (Pstring_maybe("POLLIN")) { - events |= POLLIN; - if (!Pstring_maybe("|")) return events; - } - if (Pstring_maybe("POLLOUT")) { - events |= POLLOUT; - if (!Pstring_maybe("|")) return events; - } - Pstring("POLLPRI","pollfdevents PRI?"); - return events; -} -static void Ppollfds(struct pollfd *fds, int nfds) { - int i; - char *ep; - const char *comma= ""; - if (vb2.buf[vb2.used++] != '[') Psyntax("pollfds start not ["); - for (i=0; ifd= strtoul(vb2.buf+vb2.used,&ep,10); - vb2.used= ep - (char*)vb2.buf; - Pstring(", events=",", events= in pollfds"); - fds->events= Ppollfdevents(); - Pstring(", revents=",", revents= in pollfds"); - fds->revents= Ppollfdevents(); - Pstring("}","} in pollfds"); - Pstring(comma,"separator in pollfds"); - comma= ", "; - } - if (vb2.buf[vb2.used++] != ']') Psyntax("pollfds end not ]"); -} -#endif -static void Paddr(struct sockaddr *addr, int *lenr) { - adns_rr_addr a; - char *p, *q, *ep; - int err; - unsigned long ul; - p= vb2.buf+vb2.used; - if (*p!='[') { - q= strchr(p,':'); - if (!q) Psyntax("missing :"); - *q++= 0; - } else { - p++; - q= strchr(p,']'); - if (!q) Psyntax("missing ]"); - *q++= 0; - if (*q!=':') Psyntax("expected : after ]"); - q++; - } - ul= strtoul(q,&ep,10); - if (*ep && *ep != ' ') Psyntax("invalid port (bad syntax)"); - if (ul >= 65536) Psyntax("port too large"); - a.len= sizeof(a.addr); - err= adns_text2addr(p, (int)ul, 0, &a.addr.sa,&a.len); - if (err) Psyntax("invalid address"); - assert(*lenr >= a.len); - memcpy(addr, &a.addr, a.len); - *lenr= a.len; - vb2.used= ep - (char*)vb2.buf; -} -static int Pbytes(byte *buf, int maxlen) { - static const char hexdigits[]= "0123456789abcdef"; - int c, v, done; - const char *pf; - done= 0; - for (;;) { - c= getc(Tinputfile); Pcheckinput(); - if (c=='\n' || c==' ' || c=='\t') continue; - if (c=='.') break; - pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid first hex digit"); - v= (pf-hexdigits)<<4; - c= getc(Tinputfile); Pcheckinput(); - pf= strchr(hexdigits,c); if (!pf) Psyntax("invalid second hex digit"); - v |= (pf-hexdigits); - if (maxlen<=0) Psyntax("buffer overflow in bytes"); - *buf++= v; - maxlen--; done++; - } - for (;;) { - c= getc(Tinputfile); Pcheckinput(); - if (c=='\n') return done; - } -} -void Q_vb(void) { - const char *nl; - Tensurerecordfile(); - if (!adns__vbuf_ensure(&vb2,vb.used+2)) Tnomem(); - fread(vb2.buf,1,vb.used+2,Tinputfile); - if (feof(Tinputfile)) { - fprintf(stderr,"adns test harness: input ends prematurely; program did:\n %.*s\n", - vb.used,vb.buf); - exit(-1); - } - Pcheckinput(); - if (vb2.buf[0] != ' ') Psyntax("not space before call"); - if (memcmp(vb.buf,vb2.buf+1,vb.used) || - vb2.buf[vb.used+1] != '\n') { - fprintf(stderr, - "adns test harness: program did unexpected:\n %.*s\n" - "was expecting:\n %.*s\n", - vb.used,vb.buf, vb.used,vb2.buf+1); - exit(1); - } - Tensurereportfile(); - nl= memchr(vb.buf,'\n',vb.used); - fprintf(Treportfile," %.*s\n", (int)(nl ? nl - (const char*)vb.buf : vb.used), vb.buf); -} -int Hselect( int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to ) { - int r, amtread; - char *ep; - Qselect( max , rfds , wfds , efds , to ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," select=",8)) Psyntax("syscall reply mismatch"); - if (vb2.buf[8] == 'E') { - int e; - e= Perrno(vb2.buf+8); - P_updatetime(); - errno= e; - return -1; - } - r= strtoul(vb2.buf+8,&ep,10); - if (*ep && *ep!=' ') Psyntax("return value not E* or positive number"); - vb2.used= ep - (char*)vb2.buf; - Parg("rfds"); Pfdset(rfds,max); - Parg("wfds"); Pfdset(wfds,max); - Parg("efds"); Pfdset(efds,max); - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -#ifdef HAVE_POLL -int Hpoll( struct pollfd *fds , int nfds , int timeout ) { - int r, amtread; - char *ep; - Qpoll( fds , nfds , timeout ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," poll=",6)) Psyntax("syscall reply mismatch"); - if (vb2.buf[6] == 'E') { - int e; - e= Perrno(vb2.buf+6); - P_updatetime(); - errno= e; - return -1; - } - r= strtoul(vb2.buf+6,&ep,10); - if (*ep && *ep!=' ') Psyntax("return value not E* or positive number"); - vb2.used= ep - (char*)vb2.buf; - Parg("fds"); Ppollfds(fds,nfds); - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -#endif -int Hsocket( int domain , int type , int protocol ) { - int r, amtread; - char *ep; - Tmust("socket","domain",domain==AF_INET || domain==AF_INET6); - Tmust("socket","type",type==SOCK_STREAM || type==SOCK_DGRAM); - Qsocket( domain , type ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," socket=",8)) Psyntax("syscall reply mismatch"); - if (vb2.buf[8] == 'E') { - int e; - e= Perrno(vb2.buf+8); - P_updatetime(); - errno= e; - return -1; - } - r= strtoul(vb2.buf+8,&ep,10); - if (*ep && *ep!=' ') Psyntax("return value not E* or positive number"); - vb2.used= ep - (char*)vb2.buf; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hfcntl( int fd , int cmd , ... ) { - int r, amtread; - va_list al; long arg; - Tmust("fcntl","cmd",cmd==F_SETFL || cmd==F_GETFL); - if (cmd == F_SETFL) { - va_start(al,cmd); arg= va_arg(al,long); va_end(al); - } else { - arg= 0; - } - Qfcntl( fd , cmd , arg ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," fcntl=",7)) Psyntax("syscall reply mismatch"); - if (vb2.buf[7] == 'E') { - int e; - e= Perrno(vb2.buf+7); - P_updatetime(); - errno= e; - return -1; - } - r= 0; - if (cmd == F_GETFL) { - if (!memcmp(vb2.buf+7,"O_NONBLOCK|...",14)) { - r= O_NONBLOCK; - vb2.used= 7+14; - } else if (!memcmp(vb2.buf+7,"~O_NONBLOCK&...",15)) { - vb2.used= 7+15; - } else { - Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&..."); - } - } else if (cmd == F_SETFL) { - if (memcmp(vb2.buf+7,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 7+2; - r= 0; - } else { - Psyntax("fcntl not F_GETFL or F_SETFL"); - } - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hconnect( int fd , const struct sockaddr *addr , int addrlen ) { - int r, amtread; - Qconnect( fd , addr , addrlen ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," connect=",9)) Psyntax("syscall reply mismatch"); - if (vb2.buf[9] == 'E') { - int e; - e= Perrno(vb2.buf+9); - P_updatetime(); - errno= e; - return -1; - } - if (memcmp(vb2.buf+9,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 9+2; - r= 0; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hbind( int fd , const struct sockaddr *addr , int addrlen ) { - int r, amtread; - Qbind( fd , addr , addrlen ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," bind=",6)) Psyntax("syscall reply mismatch"); - if (vb2.buf[6] == 'E') { - int e; - e= Perrno(vb2.buf+6); - P_updatetime(); - errno= e; - return -1; - } - if (memcmp(vb2.buf+6,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 6+2; - r= 0; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hlisten( int fd , int backlog ) { - int r, amtread; - Qlisten( fd , backlog ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," listen=",8)) Psyntax("syscall reply mismatch"); - if (vb2.buf[8] == 'E') { - int e; - e= Perrno(vb2.buf+8); - P_updatetime(); - errno= e; - return -1; - } - if (memcmp(vb2.buf+8,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 8+2; - r= 0; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hclose( int fd ) { - int r, amtread; - Qclose( fd ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," close=",7)) Psyntax("syscall reply mismatch"); - if (vb2.buf[7] == 'E') { - int e; - e= Perrno(vb2.buf+7); - P_updatetime(); - errno= e; - return -1; - } - if (memcmp(vb2.buf+7,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 7+2; - r= 0; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hsendto( int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen ) { - int r, amtread; - char *ep; - Tmust("sendto","flags",flags==0); - Qsendto( fd , msg , msglen , addr , addrlen ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," sendto=",8)) Psyntax("syscall reply mismatch"); - if (vb2.buf[8] == 'E') { - int e; - e= Perrno(vb2.buf+8); - P_updatetime(); - errno= e; - return -1; - } - r= strtoul(vb2.buf+8,&ep,10); - if (*ep && *ep!=' ') Psyntax("return value not E* or positive number"); - vb2.used= ep - (char*)vb2.buf; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} -int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen ) { - int r, amtread; - Tmust("recvfrom","flags",flags==0); - Tmust("recvfrom","*addrlen",*addrlen>=sizeof(struct sockaddr_in)); - Qrecvfrom( fd , buflen , *addrlen ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," recvfrom=",10)) Psyntax("syscall reply mismatch"); - if (vb2.buf[10] == 'E') { - int e; - e= Perrno(vb2.buf+10); - P_updatetime(); - errno= e; - return -1; - } - if (memcmp(vb2.buf+10,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 10+2; - r= 0; - Parg("addr"); Paddr(addr,addrlen); - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - r= Pbytes(buf,buflen); - P_updatetime(); - return r; -} -int Hread( int fd , void *buf , size_t buflen ) { - int r, amtread; - Qread( fd , buflen ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," read=",6)) Psyntax("syscall reply mismatch"); - if (vb2.buf[6] == 'E') { - int e; - e= Perrno(vb2.buf+6); - P_updatetime(); - errno= e; - return -1; - } - if (memcmp(vb2.buf+6,"OK",2)) Psyntax("success/fail not E* or OK"); - vb2.used= 6+2; - r= 0; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - r= Pbytes(buf,buflen); - P_updatetime(); - return r; -} -int Hwrite( int fd , const void *buf , size_t len ) { - int r, amtread; - char *ep; - Qwrite( fd , buf , len ); - if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); - fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); - fprintf(Treportfile,"%s",vb2.buf); - amtread= strlen(vb2.buf); - if (amtread<=0 || vb2.buf[--amtread]!='\n') - Psyntax("badly formed line"); - vb2.buf[amtread]= 0; - if (memcmp(vb2.buf," write=",7)) Psyntax("syscall reply mismatch"); - if (vb2.buf[7] == 'E') { - int e; - e= Perrno(vb2.buf+7); - P_updatetime(); - errno= e; - return -1; - } - r= strtoul(vb2.buf+7,&ep,10); - if (*ep && *ep!=' ') Psyntax("return value not E* or positive number"); - vb2.used= ep - (char*)vb2.buf; - assert(vb2.used <= amtread); - if (vb2.used != amtread) Psyntax("junk at end of line"); - P_updatetime(); - return r; -} diff --git a/regress/hplayback.c.m4 b/regress/hplayback.c.m4 index ad27a9a..dd98f0e 100644 --- a/regress/hplayback.c.m4 +++ b/regress/hplayback.c.m4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - playback routines m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -37,17 +37,15 @@ m4_include(hmacros.i4) #include #include +#include + #include "harness.h" -static FILE *Tinputfile, *Treportfile; +static FILE *Tinputfile, *Tfuzzrawfile, *Treportfile; static vbuf vb2; -extern void Tshutdown(void) { - adns__vbuf_free(&vb2); -} - -static void Tensurereportfile(void) { +static void Tensure_reportfile(void) { const char *fdstr; int fd; @@ -58,6 +56,36 @@ static void Tensurereportfile(void) { Treportfile= fdopen(fd,"a"); if (!Treportfile) Tfailed("fdopen ADNS_TEST_REPORT_FD"); } +static void Tensure_fuzzrawfile(void) { + static int done; + + if (done) return; + done++; + + const char *fdstr= getenv("ADNS_TEST_FUZZRAW_DUMP_FD"); + if (!fdstr) return; + + int fd= atoi(fdstr); + Tfuzzrawfile= fdopen(fd,"ab"); + if (!Tfuzzrawfile) Tfailed("fdopen ADNS_TEST_FUZZRAW_DUMP_FD"); +} + +static void FR_write(const void *p, size_t sz) { + if (!Tfuzzrawfile) return; + ssize_t got = fwrite(p,1,sz,Tfuzzrawfile); + if (ferror(Tfuzzrawfile)) Tfailed("write fuzzraw output file"); + assert(got==sz); +} + +#define FR_WRITE(x) (FR_write(&(x), sizeof((x)))) + +extern void Tshutdown(void) { + adns__vbuf_free(&vb2); + if (Tfuzzrawfile) { + if (fclose(Tfuzzrawfile)) Tfailed("close fuzzraw output file"); + } +} + static void Psyntax(const char *where) { fprintf(stderr,"adns test harness: syntax error in test log input file: %s\n",where); exit(-1); @@ -68,17 +96,27 @@ static void Pcheckinput(void) { if (feof(Tinputfile)) Psyntax("eof at syscall reply"); } -void Tensurerecordfile(void) { - const char *fdstr; +void T_gettimeofday_hook(void) { + static struct timeval previously; + struct timeval delta; + memset(&delta,0,sizeof(delta)); + timersub(¤ttime, &previously, &delta); + previously = currenttime; + FR_WRITE(delta); +} + +void Tensuresetup(void) { int fd; int chars; unsigned long sec, usec; + Tensure_reportfile(); + Tensure_fuzzrawfile(); + if (Tinputfile) return; Tinputfile= stdin; - fdstr= getenv("ADNS_TEST_IN_FD"); - if (fdstr) { - fd= atoi(fdstr); + fd = Ttestinputfd(); + if (fd >= 0) { Tinputfile= fdopen(fd,"r"); if (!Tinputfile) Tfailed("fdopen ADNS_TEST_IN_FD"); } setvbuf(Tinputfile,0,_IONBF,0); @@ -126,6 +164,7 @@ static int Perrno(const char *stuff) { if (te->n) return te->v; r= strtoul(stuff+2,&ep,10); if (*ep) Psyntax("errno value not recognised, not numeric"); + if (r==0 || r>255) Psyntax("numeric errno out of range 1..255"); return r; } @@ -148,7 +187,8 @@ static void P_updatetime(void) { } static void Pfdset(fd_set *set, int max) { - int r, c; + int c; + unsigned long ul; char *ep; if (!set) { @@ -158,16 +198,33 @@ static void Pfdset(fd_set *set, int max) { if (vb2.buf[vb2.used++] != hm_squote[hm_squote) Psyntax("fd set start not ["); FD_ZERO(set); - if (vb2.buf[vb2.used] == hm_squote]hm_squote) { vb2.used++; return; } - for (;;) { - r= strtoul(vb2.buf+vb2.used,&ep,10); - if (r>=max) Psyntax("fd set member > max"); - if (ep == (char*)vb2.buf+vb2.used) Psyntax("empty entry in fd set"); - FD_SET(r,set); - vb2.used= ep - (char*)vb2.buf; - c= vb2.buf[vb2.used++]; - if (c == hm_squote]hm_squote) break; - if (c != hm_squote,hm_squote) Psyntax("fd set separator not ,"); + if (vb2.buf[vb2.used] == hm_squote]hm_squote) { + vb2.used++; + } else { + for (;;) { + ul= strtoul(vb2.buf+vb2.used,&ep,10); + if (ul>=max) Psyntax("fd set member > max"); + if (ep == (char*)vb2.buf+vb2.used) Psyntax("empty entry in fd set"); + FD_SET(ul,set); + vb2.used= ep - (char*)vb2.buf; + c= vb2.buf[vb2.used++]; + if (c == hm_squote]hm_squote) break; + if (c != hm_squote,hm_squote) Psyntax("fd set separator not ,"); + } + } + + uint16_t accum; + int inaccum=0, fd; + for (fd=0; ; fd++) { + if (fd>=max || inaccum==16) { + FR_WRITE(accum); + inaccum= 0; + } + if (fd>=max) + break; + accum <<= 1; + accum |= !!FD_ISSET(fd,set); + inaccum++; } } @@ -200,12 +257,15 @@ static void Ppollfds(struct pollfd *fds, int nfds) { if (vb2.buf[vb2.used++] != hm_squote[hm_squote) Psyntax("pollfds start not ["); for (i=0; ifd= strtoul(vb2.buf+vb2.used,&ep,10); + int gotfd= strtoul(vb2.buf+vb2.used,&ep,10); + if (gotfd != fds->fd) Psyntax("poll fds[].fd changed"); vb2.used= ep - (char*)vb2.buf; Pstring(", events=",", events= in pollfds"); - fds->events= Ppollfdevents(); + int gotevents= Ppollfdevents(); + if (gotevents != fds->events) Psyntax("poll fds[].events changed"); Pstring(", revents=",", revents= in pollfds"); fds->revents= Ppollfdevents(); + if (gotevents) FR_WRITE(fds->revents); Pstring("}","} in pollfds"); Pstring(comma,"separator in pollfds"); comma= ", "; @@ -237,6 +297,14 @@ static void Paddr(struct sockaddr *addr, int *lenr) { if (*ep && *ep != ' ') Psyntax("invalid port (bad syntax)"); if (ul >= 65536) Psyntax("port too large"); + if (Tfuzzrawfile) { + int tl = strlen(p); + FR_WRITE(tl); + FR_write(p,tl); + uint16_t port16 = ul; + FR_WRITE(port16); + } + a.len= sizeof(a.addr); err= adns_text2addr(p, (int)ul, 0, &a.addr.sa,&a.len); if (err) Psyntax("invalid address"); @@ -276,7 +344,7 @@ static int Pbytes(byte *buf, int maxlen) { void Q_vb(void) { const char *nl; - Tensurerecordfile(); + Tensuresetup(); if (!adns__vbuf_ensure(&vb2,vb.used+2)) Tnomem(); fread(vb2.buf,1,vb.used+2,Tinputfile); if (feof(Tinputfile)) { @@ -294,7 +362,6 @@ void Q_vb(void) { vb.used,vb.buf, vb.used,vb2.buf+1); exit(1); } - Tensurereportfile(); nl= memchr(vb.buf,'\n',vb.used); fprintf(Treportfile," %.*s\n", (int)(nl ? nl - (const char*)vb.buf : vb.used), vb.buf); } @@ -303,12 +370,9 @@ m4_define(`hm_syscall', ` hm_create_proto_h int H$1(hm_args_massage($3,void)) { int r, amtread; + hm_create_nothing m4_define(`hm_rv_fd',`char *ep;') m4_define(`hm_rv_any',`char *ep;') - m4_define(`hm_rv_len',`') - m4_define(`hm_rv_must',`') - m4_define(`hm_rv_succfail',`') - m4_define(`hm_rv_fcntl',`') $2 hm_create_hqcall_vars @@ -324,7 +388,7 @@ int H$1(hm_args_massage($3,void)) { if (!adns__vbuf_ensure(&vb2,1000)) Tnomem(); fgets(vb2.buf,vb2.avail,Tinputfile); Pcheckinput(); - Tensurereportfile(); + Tensuresetup(); fprintf(Treportfile,"%s",vb2.buf); amtread= strlen(vb2.buf); if (amtread<=0 || vb2.buf[--amtread]!=hm_squote\nhm_squote) @@ -332,27 +396,56 @@ int H$1(hm_args_massage($3,void)) { vb2.buf[amtread]= 0; if (memcmp(vb2.buf," $1=",hm_r_offset)) Psyntax("syscall reply mismatch"); +#ifdef FUZZRAW_SYNC + hm_fr_syscall_ident($1) + FR_WRITE(sync_expect); +#endif + + m4_define(`hm_rv_check_errno',` if (vb2.buf[hm_r_offset] == hm_squoteEhm_squote) { int e; e= Perrno(vb2.buf+hm_r_offset); P_updatetime(); errno= e; + FR_WRITE(e); return -1; } - - m4_define(`hm_rv_succfail',` + r= 0; + FR_WRITE(r); + ') + m4_define(`hm_rv_check_success',` if (memcmp(vb2.buf+hm_r_offset,"OK",2)) Psyntax("success/fail not E* or OK"); vb2.used= hm_r_offset+2; r= 0; ') - m4_define(`hm_rv_len',`hm_rv_succfail') - m4_define(`hm_rv_must',`hm_rv_succfail') - m4_define(`hm_rv_any',` - r= strtoul(vb2.buf+hm_r_offset,&ep,10); - if (*ep && *ep!=hm_squote hm_squote) Psyntax("return value not E* or positive number"); + m4_define(`hm_rv_any_nowrite',` + hm_rv_check_errno + unsigned long ul_r= strtoul(vb2.buf+hm_r_offset,&ep,10); + if (ul_r < 0 || ul_r > INT_MAX || + (*ep && *ep!=hm_squote hm_squote)) + Psyntax("return value not E* or positive number"); + r= ul_r; vb2.used= ep - (char*)vb2.buf; ') + + m4_define(`hm_rv_succfail',` + hm_rv_check_errno + hm_rv_check_success + ') + m4_define(`hm_rv_len',` + hm_rv_check_errno + hm_rv_check_success + ') + m4_define(`hm_rv_must',` + hm_rv_check_success + ') + m4_define(`hm_rv_any',` + hm_rv_any_nowrite + FR_WRITE(r); + ') m4_define(`hm_rv_fd',`hm_rv_any') + m4_define(`hm_rv_select',`hm_rv_any_nowrite') + m4_define(`hm_rv_poll',`hm_rv_any_nowrite') m4_define(`hm_rv_fcntl',` r= 0; if (cmd == F_GETFL) { @@ -365,7 +458,7 @@ int H$1(hm_args_massage($3,void)) { Psyntax("fcntl flags not O_NONBLOCK|... or ~O_NONBLOCK&..."); } } else if (cmd == F_SETFL) { - hm_rv_succfail + hm_rv_check_success } else { Psyntax("fcntl not F_GETFL or F_SETFL"); } @@ -381,7 +474,11 @@ int H$1(hm_args_massage($3,void)) { if (vb2.used != amtread) Psyntax("junk at end of line"); hm_create_nothing - m4_define(`hm_arg_bytes_out',`r= Pbytes($'`2,$'`4);') + m4_define(`hm_arg_bytes_out',` + r= Pbytes($'`2,$'`4); + FR_WRITE(r); + FR_write(buf,r); + ') $3 P_updatetime(); @@ -392,3 +489,5 @@ int H$1(hm_args_massage($3,void)) { m4_define(`hm_specsyscall', `') m4_include(`hsyscalls.i4') + +hm_stdsyscall_close diff --git a/regress/hrecord.c b/regress/hrecord.c deleted file mode 100644 index dec099b..0000000 --- a/regress/hrecord.c +++ /dev/null @@ -1,257 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "harness.h" -static FILE *Toutputfile; -void Tshutdown(void) { -} -static void R_recordtime(void) { - int r; - struct timeval tv, tvrel; - Tensurerecordfile(); - r= gettimeofday(&tv,0); if (r) Tfailed("gettimeofday syscallbegin"); - tvrel.tv_sec= tv.tv_sec - currenttime.tv_sec; - tvrel.tv_usec= tv.tv_usec - currenttime.tv_usec; - if (tv.tv_usec < 0) { tvrel.tv_usec += 1000000; tvrel.tv_sec--; } - Tvbf("\n +%ld.%06ld",(long)tvrel.tv_sec,(long)tvrel.tv_usec); - currenttime= tv; -} -void Tensurerecordfile(void) { - const char *fdstr; - int fd, r; - if (Toutputfile) return; - Toutputfile= stdout; - fdstr= getenv("ADNS_TEST_OUT_FD"); - if (fdstr) { - fd= atoi(fdstr); - Toutputfile= fdopen(fd,"a"); if (!Toutputfile) Tfailed("fdopen ADNS_TEST_OUT_FD"); - } - r= gettimeofday(¤ttime,0); if (r) Tfailed("gettimeofday syscallbegin"); - if (fprintf(Toutputfile," start %ld.%06ld\n", - (long)currenttime.tv_sec,(long)currenttime.tv_usec) == EOF) Toutputerr(); -} -void Q_vb(void) { - if (!adns__vbuf_append(&vb,"",1)) Tnomem(); - Tensurerecordfile(); - if (fprintf(Toutputfile," %s\n",vb.buf) == EOF) Toutputerr(); - if (fflush(Toutputfile)) Toutputerr(); -} -static void R_vb(void) { - Q_vb(); -} -int Hselect( int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to ) { - int r, e; - Qselect( max , rfds , wfds , efds , to ); - r= select( max , rfds , wfds , efds , to ); - e= errno; - vb.used= 0; - Tvba("select="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tvbf("%d",r); - Tvba(" rfds="); Tvbfdset(max,rfds); - Tvba(" wfds="); Tvbfdset(max,wfds); - Tvba(" efds="); Tvbfdset(max,efds); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -#ifdef HAVE_POLL -int Hpoll( struct pollfd *fds , int nfds , int timeout ) { - int r, e; - Qpoll( fds , nfds , timeout ); - r= poll( fds , nfds , timeout ); - e= errno; - vb.used= 0; - Tvba("poll="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tvbf("%d",r); - Tvba(" fds="); Tvbpollfds(fds,nfds); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -#endif -int Hsocket( int domain , int type , int protocol ) { - int r, e; - Tmust("socket","domain",domain==AF_INET || domain==AF_INET6); - Tmust("socket","type",type==SOCK_STREAM || type==SOCK_DGRAM); - Qsocket( domain , type ); - r= socket( domain , type , protocol ); - e= errno; - vb.used= 0; - Tvba("socket="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tvbf("%d",r); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hfcntl( int fd , int cmd , ... ) { - int r, e; - va_list al; long arg; - Tmust("fcntl","cmd",cmd==F_SETFL || cmd==F_GETFL); - if (cmd == F_SETFL) { - va_start(al,cmd); arg= va_arg(al,long); va_end(al); - } else { - arg= 0; - } - Qfcntl( fd , cmd , arg ); - r= fcntl( fd , cmd , arg ); - e= errno; - vb.used= 0; - Tvba("fcntl="); - if (r==-1) { Tvberrno(e); goto x_error; } - if (cmd == F_GETFL) { - Tvbf(r & O_NONBLOCK ? "O_NONBLOCK|..." : "~O_NONBLOCK&..."); - } else { - if (cmd == F_SETFL) { - Tmust("fcntl","return",!r); - } else { - Tmust("cmd","F_GETFL/F_SETFL",0); - } - Tvba("OK"); - } - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hconnect( int fd , const struct sockaddr *addr , int addrlen ) { - int r, e; - Qconnect( fd , addr , addrlen ); - r= connect( fd , addr , addrlen ); - e= errno; - vb.used= 0; - Tvba("connect="); - if (r) { Tvberrno(e); goto x_error; } - Tvba("OK"); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hbind( int fd , const struct sockaddr *addr , int addrlen ) { - int r, e; - Qbind( fd , addr , addrlen ); - r= bind( fd , addr , addrlen ); - e= errno; - vb.used= 0; - Tvba("bind="); - if (r) { Tvberrno(e); goto x_error; } - Tvba("OK"); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hlisten( int fd , int backlog ) { - int r, e; - Qlisten( fd , backlog ); - r= listen( fd , backlog ); - e= errno; - vb.used= 0; - Tvba("listen="); - if (r) { Tvberrno(e); goto x_error; } - Tvba("OK"); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hclose( int fd ) { - int r, e; - Qclose( fd ); - r= close( fd ); - e= errno; - vb.used= 0; - Tvba("close="); - if (r) { Tvberrno(e); goto x_error; } - Tvba("OK"); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hsendto( int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen ) { - int r, e; - Tmust("sendto","flags",flags==0); - Qsendto( fd , msg , msglen , addr , addrlen ); - r= sendto( fd , msg , msglen , flags , addr , addrlen ); - e= errno; - vb.used= 0; - Tvba("sendto="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tvbf("%d",r); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen ) { - int r, e; - Tmust("recvfrom","flags",flags==0); - Tmust("recvfrom","*addrlen",*addrlen>=sizeof(struct sockaddr_in)); - Qrecvfrom( fd , buflen , *addrlen ); - r= recvfrom( fd , buf , buflen , flags , addr , addrlen ); - e= errno; - vb.used= 0; - Tvba("recvfrom="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tmust("recvfrom","return",r<=buflen); - Tvba("OK"); - Tvba(" addr="); Tvbaddr(addr,*addrlen); - Tvbbytes(buf,r); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hread( int fd , void *buf , size_t buflen ) { - int r, e; - Qread( fd , buflen ); - r= read( fd , buf , buflen ); - e= errno; - vb.used= 0; - Tvba("read="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tmust("read","return",r<=buflen); - Tvba("OK"); - Tvbbytes(buf,r); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} -int Hwrite( int fd , const void *buf , size_t len ) { - int r, e; - Qwrite( fd , buf , len ); - r= write( fd , buf , len ); - e= errno; - vb.used= 0; - Tvba("write="); - if (r==-1) { Tvberrno(e); goto x_error; } - Tvbf("%d",r); - x_error: - R_recordtime(); - R_vb(); - errno= e; - return r; -} diff --git a/regress/hrecord.c.m4 b/regress/hrecord.c.m4 index b9d5a73..c8a133e 100644 --- a/regress/hrecord.c.m4 +++ b/regress/hrecord.c.m4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - recording routines m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -44,7 +44,7 @@ static void R_recordtime(void) { int r; struct timeval tv, tvrel; - Tensurerecordfile(); + Tensuresetup(); r= gettimeofday(&tv,0); if (r) Tfailed("gettimeofday syscallbegin"); tvrel.tv_sec= tv.tv_sec - currenttime.tv_sec; tvrel.tv_usec= tv.tv_usec - currenttime.tv_usec; @@ -53,7 +53,9 @@ static void R_recordtime(void) { currenttime= tv; } -void Tensurerecordfile(void) { +void T_gettimeofday_hook(void) { } + +void Tensuresetup(void) { const char *fdstr; int fd, r; @@ -73,7 +75,7 @@ void Tensurerecordfile(void) { void Q_vb(void) { if (!adns__vbuf_append(&vb,"",1)) Tnomem(); - Tensurerecordfile(); + Tensuresetup(); if (fprintf(Toutputfile," %s\n",vb.buf) == EOF) Toutputerr(); if (fflush(Toutputfile)) Toutputerr(); } @@ -112,7 +114,7 @@ int H$1(hm_args_massage($3,void)) { m4_define(`hm_rv_must',`Tmust("$1","return",!r); Tvba("OK");') m4_define(`hm_rv_len',` if (r==-1) { Tvberrno(e); goto x_error; } - Tmust("$1","return",r<=$'`1); + Tmust("$'`1","return",r<=$'`1); Tvba("OK");') m4_define(`hm_rv_fcntl',` if (r==-1) { Tvberrno(e); goto x_error; } @@ -138,6 +140,7 @@ int H$1(hm_args_massage($3,void)) { m4_define(`hm_arg_bytes_out',`Tvbbytes($'`2,r);') $3 + hm_create_nothing m4_define(`hm_rv_any',`x_error:') m4_define(`hm_rv_fd',`x_error:') m4_define(`hm_rv_succfail',`x_error:') @@ -156,3 +159,5 @@ int H$1(hm_args_massage($3,void)) { m4_define(`hm_specsyscall', `') m4_include(`hsyscalls.i4') + +hm_stdsyscall_close diff --git a/regress/hredirect.h b/regress/hredirect.h deleted file mode 100644 index 7bff129..0000000 --- a/regress/hredirect.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef HREDIRECT_H_INCLUDED -#define HREDIRECT_H_INCLUDED -#include "hsyscalls.h" -#undef select -#define select Hselect -#ifdef HAVE_POLL -#undef poll -#define poll Hpoll -#endif -#undef socket -#define socket Hsocket -#undef fcntl -#define fcntl Hfcntl -#undef connect -#define connect Hconnect -#undef bind -#define bind Hbind -#undef listen -#define listen Hlisten -#undef close -#define close Hclose -#undef sendto -#define sendto Hsendto -#undef recvfrom -#define recvfrom Hrecvfrom -#undef read -#define read Hread -#undef write -#define write Hwrite -#undef writev -#define writev Hwritev -#undef gettimeofday -#define gettimeofday Hgettimeofday -#undef getpid -#define getpid Hgetpid -#undef malloc -#define malloc Hmalloc -#undef free -#define free Hfree -#undef realloc -#define realloc Hrealloc -#undef exit -#define exit Hexit -#endif diff --git a/regress/hredirect.h.m4 b/regress/hredirect.h.m4 index ccb48f0..a40783c 100644 --- a/regress/hredirect.h.m4 +++ b/regress/hredirect.h.m4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - redefinitions of system calls m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -36,4 +36,7 @@ m4_define(`hm_specsyscall',`#undef $2 #define $2 H$2') m4_include(`hsyscalls.i4') +m4_dnl only usage site is definition of main +#define main(C, V) Hmain(C, V); int Hmain(C, V) + #endif diff --git a/regress/hsyscalls.h b/regress/hsyscalls.h deleted file mode 100644 index 6dc9edc..0000000 --- a/regress/hsyscalls.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef HSYSCALLS_H_INCLUDED -#define HSYSCALLS_H_INCLUDED -#include -#include -#include -#include -#include -#ifdef HAVE_POLL -#include -#endif -int Hselect( int max , fd_set *rfds , fd_set *wfds , fd_set *efds , struct timeval *to ); -#ifdef HAVE_POLL -int Hpoll( struct pollfd *fds , int nfds , int timeout ); -#endif -int Hsocket( int domain , int type , int protocol ); -int Hfcntl( int fd , int cmd , ... ); -int Hconnect( int fd , const struct sockaddr *addr , int addrlen ); -int Hbind( int fd , const struct sockaddr *addr , int addrlen ); -int Hlisten( int fd , int backlog ); -int Hclose( int fd ); -int Hsendto( int fd , const void *msg , int msglen , unsigned int flags , const struct sockaddr *addr , int addrlen ); -int Hrecvfrom( int fd , void *buf , int buflen , unsigned int flags , struct sockaddr *addr , int *addrlen ); -int Hread( int fd , void *buf , size_t buflen ); -int Hwrite( int fd , const void *buf , size_t len ); -int Hwritev(int fd, const struct iovec *vector, size_t count); -int Hgettimeofday(struct timeval *tv, struct timezone *tz); -pid_t Hgetpid(void); -void* Hmalloc(size_t sz); -void Hfree(void *ptr); -void* Hrealloc(void *op, size_t nsz); -void Hexit(int rv)NONRETURNING; -#endif diff --git a/regress/hsyscalls.h.m4 b/regress/hsyscalls.h.m4 index 7400895..9e622ec 100644 --- a/regress/hsyscalls.h.m4 +++ b/regress/hsyscalls.h.m4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - prototypes of redefinitions of system calls m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/regress/hsyscalls.i4 b/regress/hsyscalls.i4 index a480e6a..dbc584f 100644 --- a/regress/hsyscalls.i4 +++ b/regress/hsyscalls.i4 @@ -3,7 +3,7 @@ m4_dnl (part of complex test harness, not of the library) m4_dnl - list of syscalls to override/log and their args m4_dnl This file is part of adns, which is -m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +m4_dnl Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson m4_dnl Copyright (C) 2014 Mark Wooding m4_dnl Copyright (C) 1999-2000,2003,2006 Tony Finch m4_dnl Copyright (C) 1991 Massachusetts Institute of Technology @@ -29,8 +29,11 @@ m4_dnl hm_rv_must must succeed and return 0 m4_dnl hm_rv_any any nonnegative return allowed, -1 means see errno m4_dnl hm_rv_fd file descriptor is returned, -1 means see errno m4_dnl hm_rv_succfail returns 0 (ok) or -1 (see errno) -m4_dnl hm_rv_len() returns length read/written, must be <=max, -1 => errno +m4_dnl hm_rv_len() returns length read, must be <=max, -1 => errno +m4_dnl hm_rv_wlen() returns length written, must be <=max, -1 => errno m4_dnl hm_rv_fcntl syscall is fcntl, do special processing +m4_dnl hm_rv_select select, do special processing } default is _any +m4_dnl hm_rv_poll poll, do special processing } after create_nothing m4_dnl is list of macros for arguments, each followed by hm_na m4_dnl hm_arg_nullptr(,) pointer of type type, must be null m4_dnl hm_arg_int() signed integer @@ -53,7 +56,7 @@ m4_dnl return value from syscall is supposed to be returned length m4_dnl hm_arg_addr_out(,) struct sockaddr*, length io at (an int*) hm_syscall( - select, `hm_rv_any', ` + select, `hm_rv_select', ` hm_arg_int(max) hm_na hm_arg_fdset_io(rfds,max) hm_na hm_arg_fdset_io(wfds,max) hm_na @@ -63,7 +66,7 @@ hm_syscall( #ifdef HAVE_POLL hm_syscall( - poll, `hm_rv_any', ` + poll, `hm_rv_poll', ` hm_arg_pollfds_io(fds,nfds) hm_na hm_arg_int(timeout) hm_na ') @@ -101,12 +104,7 @@ hm_syscall( ') hm_syscall( - close, `hm_rv_succfail', ` - hm_arg_fd(fd) hm_na -') - -hm_syscall( - sendto, `hm_rv_any', ` + sendto, `hm_rv_wlen(msglen)', ` hm_arg_fd(fd) hm_na hm_arg_bytes_in(void,msg,int,msglen) hm_na hm_arg_must(unsigned int,flags,0) hm_na @@ -128,16 +126,27 @@ hm_syscall( ') hm_syscall( - write, `hm_rv_any', ` + write, `hm_rv_wlen(len)', ` hm_arg_fd(fd) hm_na hm_arg_bytes_in(void,buf,size_t,len) hm_na ') hm_specsyscall(int, writev, `int fd, const struct iovec *vector, size_t count') hm_specsyscall(int, gettimeofday, `struct timeval *tv, struct timezone *tz') +hm_specsyscall(int, clock_gettime, `clockid_t clk, struct timespec *ts') hm_specsyscall(pid_t, getpid, `void') +hm_specsyscall(int, close, `int fd') + +m4_define(hm_stdsyscall_close,` +hm_syscall( + close, `hm_rv_succfail', ` + hm_arg_fd(fd) hm_na +') +') hm_specsyscall(void*, malloc, `size_t sz') hm_specsyscall(void, free, `void *ptr') hm_specsyscall(void*, realloc, `void *op, size_t nsz') hm_specsyscall(void, exit, `int rv', NONRETURNING) + +hm_specsyscall(FILE*, fopen, `const char *path, const char *mode') diff --git a/regress/m1test b/regress/m1test index e5411dc..5f928f1 100755 --- a/regress/m1test +++ b/regress/m1test @@ -3,7 +3,7 @@ # test recording script # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology @@ -67,7 +67,7 @@ queryargs="$*" initstring="`cat $srcdir/init-$initfile.text`" xinitflagsf=$srcdir/$program-xinitflags.text -if test -f $xinitflagsf +if test -e $xinitflagsf then useinitflags="$initflags $(cat $xinitflagsf)"; else diff --git a/regress/make1fuzz b/regress/make1fuzz new file mode 100755 index 0000000..e121094 --- /dev/null +++ b/regress/make1fuzz @@ -0,0 +1,62 @@ +#!/bin/sh +set -e + +: ${srcdir=.} +. "$srcdir"/shlib + +casename="$1" + +playback_prepare + +ofuzz="fuzz-$casename" +ofuzzraw="fuzzraw-$casename" + +rm -f "$ofuzz.tmp" +rm -f "$ofuzzraw.tmp" +exec >"$ofuzz.tmp" +exec 6>"$ofuzzraw.tmp" + +fuzzout_complete () { + mv "$ofuzz.tmp" "$ofuzz" + mv "$ofuzzraw.tmp" "$ofuzzraw" + exit 0 +} + +if test ! -e $playback; then + echo 0 + echo 0 >&6 + fuzzout_complete +fi + +dump_args () { + printf "%d\n" "$#" + for a in "$@"; do + printf "%d\n" "${#a}" + printf "%s\n" "$a" + done + + if test -e "$case.in" + then + inputsz=$(stat -c'%s' -L "$case.in") + printf "%d\n" "$inputsz" + cat "$case.in" + else + echo 0 + fi + + echo +} + +playback_execute_hook () { + dump_args "${program}_fuzz" "$@" + dump_args "${program}_fuzzraw" "$@" >&6 + cat <&4 >"$ofuzz.sys.tmp" + exec 4<$ofuzz.sys.tmp + ADNS_TEST_FUZZRAW_DUMP_FD=6 + export ADNS_TEST_FUZZRAW_DUMP_FD +} +playback_execute + +cat $ofuzz.sys.tmp + +fuzzout_complete diff --git a/regress/r1test b/regress/r1test index e03ba02..7d5a4d8 100755 --- a/regress/r1test +++ b/regress/r1test @@ -3,7 +3,7 @@ # test execution script, for running one test # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology @@ -24,52 +24,28 @@ set -e : ${srcdir=.} +. "$srcdir"/shlib mrc=1 trap 'exit $mrc' 0 casename="$1" -case="$srcdir/case-$casename" -ocase="output-$casename" -exec 4<"$case.sys" -read <&4 program initfile initflags -read <&4 queryargs - -initstring="`cat $srcdir/init-$initfile.text`" -xinitflagsf=$srcdir/$program-xinitflags.text -if test -f $xinitflagsf -then - initflags="$initflags `cat $xinitflagsf`"; -else - initflags="$initflags /" -fi +playback_prepare rm -f $ocase.* EF_DISABLE_BANNER=1 export EF_DISABLE_BANNER -if test -f "$case.in" -then - exec <"$case.in" -else - exec >"$ocase.report" 4<&4 >"$ocase.out" 2>"$ocase.err" \ - $ADNS_TEST_DEBUG $playback $initflags"$initstring" $queryargs -rc=$? -set -e +playback_execute_hook () { :; } +playback_execute if [ "$rc" = 5 ] then diff --git a/regress/shlib b/regress/shlib new file mode 100644 index 0000000..eabe631 --- /dev/null +++ b/regress/shlib @@ -0,0 +1,42 @@ +# -*- shell -*- + +playback_prepare () { + case="$srcdir/case-$casename" + ocase="output-$casename" + + if test -e "$case.in" + then + exec <"$case.in" + else + exec >"$ocase.report" 4<&4 >"$ocase.out" 2>"$ocase.err" \ + $ADNS_TEST_DEBUG $playback "$@" + rc=$? + set -e +} + +playback_execute () { + playback_execute_core $initflags"$initstring" $queryargs +} diff --git a/settings.make.in b/settings.make.in index 47eaaa7..4f8379a 100644 --- a/settings.make.in +++ b/settings.make.in @@ -2,7 +2,7 @@ # used by autoconf/configure to generate settings.make # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology @@ -26,14 +26,15 @@ include ../common.make all: $(TARGETS) clean mostlyclean: + rm -f $(TARGETS) $(AUTOCSRCS) $(AUTOCHDRS) rm -f *.o *.tmp* *.so *.so.* pipe.* - rm -f output-*.err output-*.leftover - rm -f output-*.out output-*.report + rm -f output-*.err output-*.leftover output-*.trouble + rm -f output-*.out output-*.report fuzz-* fuzzraw-* + rm -rf fuzzcat.d distclean: clean - rm -f $(TARGETS) *~ ./#*# core *.orig *.rej Makefile config.h + rm -f *~ ./#*# core *.orig *.rej Makefile config.h -distprep: $(AUTOCSRCS) $(AUTOCHDRS) +distprep: maintainer-clean: distclean - -rm -f $(AUTOCSRCS) $(AUTOCHDRS) diff --git a/src/Makefile.in b/src/Makefile.in index 449289b..a84807e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ # src/Makefile[.in] - library main Makefile # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/src/addrfam.c b/src/addrfam.c index 0ba2049..f114d74 100644 --- a/src/addrfam.c +++ b/src/addrfam.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/src/adns.h b/src/adns.h index a6599f6..ba44b06 100644 --- a/src/adns.h +++ b/src/adns.h @@ -4,11 +4,8 @@ */ /* * - * This file is - * Copyright (C) 1997-2000,2003,2006,2014 Ian Jackson - * - * It is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014 Ian Jackson + * This file is part of adns, which is + * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology * @@ -103,6 +100,7 @@ typedef enum { /* In general, or together the desired flags: */ adns_if_noautosys= 0x0010,/* do not make syscalls at every opportunity */ adns_if_eintr= 0x0020,/* allow _wait and _synchronous to return EINTR */ adns_if_nosigpipe= 0x0040,/* applic has SIGPIPE ignored, do not protect */ + adns_if_monotonic= 0x0080,/* enable if you can; see adns_processtimeouts */ adns_if_checkc_entex=0x0100,/* consistency checks on entry/exit to adns fns */ adns_if_checkc_freq= 0x0300,/* consistency checks very frequently (slow!) */ @@ -488,6 +486,21 @@ typedef struct { * these approaches has optimal performance. */ +/* + * Use of time: + * + * adns needs to manipulate timeouts. For API compatibility reasons + * (adns predates clock_gettime) the default is to use wall clock time + * from gettimeofday. This will malfunction if the system clock is + * not suitably stable. To avoid this, you should set + * adns_if_monotonic + * + * If you specify adns_if_monotonic then all `now' values passed to + * adns must be from clock_gettime(CLOCK_MONOTONIC). clock_gettime + * returns a struct timespec; you must convert it to a struct timeval + * by dividing the nsec by 1000 to make usec, rounding down. + */ + int adns_init(adns_state *newstate_r, adns_initflags flags, FILE *diagfile /*0=>stderr*/); @@ -822,6 +835,8 @@ int adns_processexceptional(adns_state ads, int fd, const struct timeval *now); * use that fd and only in the manner specified, regardless of whether * adns_if_noautosys was specified. * + * now is as for adns_processtimeouts. + * * adns_processexceptional should be called when select(2) reports an * exceptional condition, or poll(2) reports POLLPRI. * @@ -837,15 +852,19 @@ void adns_processtimeouts(adns_state ads, const struct timeval *now); /* Gives adns flow-of-control so that it can process any timeouts * which might have happened. Very like _processreadable/writeable. * - * now may be 0; if it isn't, *now must be the current time, recently - * obtained from gettimeofday. + * now may be 0; if it isn't, *now must be the current time from + * gettimeofday, or iff adns_if_monotonic it must be converted + * from the results of clock_gettime(CLOCK_MONOTONIC) (with the + * timespec.tv_nsec rounded down to make timeval.tv_usec). */ void adns_firsttimeout(adns_state ads, struct timeval **tv_mod, struct timeval *tv_buf, struct timeval now); /* Asks adns when it would first like the opportunity to time - * something out. now must be the current time, from gettimeofday. + * something out. + * + * now must be the current time, as for adns_processtimeouts. * * If tv_mod points to 0 then tv_buf must be non-null, and * _firsttimeout will fill in *tv_buf with the time until the first @@ -869,8 +888,9 @@ void adns_globalsystemfailure(adns_state ads); * adns_s_systemfail, and adns will close any stream sockets it has * open. * - * This is used by adns, for example, if gettimeofday() fails. - * Without this the program's event loop might start to spin ! + * This is used by adns, for example, if gettimeofday() or + * clock_gettime fails. Without this the program's event loop might + * start to spin ! * * This call will never block. */ @@ -886,9 +906,11 @@ void adns_beforeselect(adns_state ads, int *maxfd, fd_set *readfds, /* Find out file descriptors adns is interested in, and when it would * like the opportunity to time something out. If you do not plan to * block then tv_mod may be 0. Otherwise, tv_mod and tv_buf are as - * for adns_firsttimeout. readfds, writefds, exceptfds and maxfd_io may + * for adns_processtimeouts. readfds, writefds, exceptfds and maxfd_io may * not be 0. * + * now is as for adns_processtimeouts. + * * If tv_mod is 0 on entry then this will never actually do any I/O, * or change the fds that adns is using or the timeouts it wants. In * any case it won't block, and it will set the timeout to zero if a @@ -902,6 +924,8 @@ void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds, * select. This is just a fancy way of calling adns_processreadable/ * writeable/timeouts as appropriate, as if select had returned the * data being passed. Always succeeds. + * + * now is as for adns_processtimeouts. */ /* @@ -965,6 +989,8 @@ int adns_beforepoll(adns_state ads, struct pollfd *fds, * descriptors, and use _firsttimeout is used to find out when adns * might want to time something out.) * + * now is as for adns_processtimeouts. + * * adns_beforepoll will return 0 on success, and will not fail for any * reason other than the fds buffer being too small (ERANGE). * @@ -987,6 +1013,8 @@ void adns_afterpoll(adns_state ads, const struct pollfd *fds, int nfds, /* Gives adns flow-of-control for a bit; intended for use after * poll(2). fds and nfds should be the results from poll(). pollfd * structs mentioning fds not belonging to adns will be ignored. + * + * now is as for adns_processtimeouts. */ @@ -1057,8 +1085,13 @@ const char *adns_errtypeabbrev(adns_status st); * the abbreviation of the error - eg, for adns_s_timeout it returns * "timeout". adns_errtypeabbrev returns the abbreviation of the * error class: ie, for values up to adns_s_max_XXX it will return the - * string XXX. You MUST NOT call these functions with status values - * not returned by the same adns library. + * string XXX. + * + * If you call these functions with status values not actually + * returned from other functions in the same adns library, the + * returned information may be NULL. (You are also guaranteed + * that the return value will not be NULL for values in the + * adns_status enum, *except* for adns_s_max_XXXX.) */ #ifdef __cplusplus diff --git a/src/adns.make b/src/adns.make index 076df8b..210be5d 100644 --- a/src/adns.make +++ b/src/adns.make @@ -1,7 +1,7 @@ # src/adns.make - library definitions, including list of object files # # This file is part of adns, which is -# Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson +# Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson # Copyright (C) 2014 Mark Wooding # Copyright (C) 1999-2000,2003,2006 Tony Finch # Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/src/check.c b/src/check.c index fcf1995..f5e1a9e 100644 --- a/src/check.c +++ b/src/check.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -136,14 +136,19 @@ static void checkc_queue_tcpw(adns_state ads) { } static void checkc_queue_childw(adns_state ads) { - adns_query parent, child; + adns_query parent, child, search; DLIST_CHECK(ads->childw, parent, , { assert(parent->state == query_childw); assert(parent->children.head); DLIST_CHECK(parent->children, child, siblings., { assert(child->parent == parent); - assert(child->state != query_done); + if (child->state == query_done) { + for (search= ads->intdone.head; search; search= search->next) + if (search==child) goto child_done_ok; + assert(!"done child not on intdone"); + child_done_ok:; + } }); checkc_query(ads,parent); checkc_query_alloc(ads,parent); @@ -182,7 +187,10 @@ void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc) { switch (cc) { case cc_user: break; - case cc_entex: + case cc_enter: + if (!(ads->iflags & adns_if_checkc_entex)) return; + break; + case cc_exit: if (!(ads->iflags & adns_if_checkc_entex)) return; assert(!ads->intdone.head); break; diff --git a/src/config.h.in b/src/config.h.in index bd36686..ddc3462 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -1,4 +1,29 @@ -/* src/config.h.in. Generated automatically from configure.in by autoheader 2.13. */ +/* src/config.h.in. Generated from configure.in by autoheader. */ +/* + * acconfig.h + * input file for autoheader/autoconf/configure: extra stuff for config.h + */ +/* + * This file is part of adns, which is + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson + * Copyright (C) 2014 Mark Wooding + * Copyright (C) 1999-2000,2003,2006 Tony Finch + * Copyright (C) 1991 Massachusetts Institute of Technology + * (See the file INSTALL for full details.) + * + * 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 3, 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. + */ /* Define if inline functions a la GCC are available. */ #undef HAVE_INLINE @@ -18,15 +43,64 @@ /* Define if we want to include rpc/types.h. Crap BSDs put INADDR_LOOPBACK there. */ #undef HAVEUSE_RPCTYPES_H -/* Define if you have the poll function. */ -#undef HAVE_POLL -/* Define if you have the nsl library (-lnsl). */ +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL -/* Define if you have the socket library (-lsocket). */ +/* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + /* Use the definitions: */ #ifndef HAVE_INLINE diff --git a/src/dlist.h b/src/dlist.h index 8d83af2..7ffa22e 100644 --- a/src/dlist.h +++ b/src/dlist.h @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/src/event.c b/src/event.c index dcc49e9..c326c28 100644 --- a/src/event.c +++ b/src/event.c @@ -6,7 +6,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -36,6 +36,7 @@ #include #include #include +#include #include "internal.h" #include "tvarith.h" @@ -149,6 +150,19 @@ void adns__tcp_tryconnect(adns_state ads, struct timeval now) { /* Timeout handling functions. */ +int adns__gettimeofday(adns_state ads, struct timeval *tv) { + if (!(ads->iflags & adns_if_monotonic)) + return gettimeofday(tv,0); + + struct timespec ts; + int r = clock_gettime(CLOCK_MONOTONIC,&ts); + if (r) return r; + + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + return 0; +} + void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, struct timeval *tv_buf) { const struct timeval *now; @@ -156,8 +170,9 @@ void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, now= *now_io; if (now) return; - r= gettimeofday(tv_buf,0); if (!r) { *now_io= tv_buf; return; } - adns__diag(ads,-1,0,"gettimeofday failed: %s",strerror(errno)); + r= adns__gettimeofday(ads,tv_buf); if (!r) { *now_io= tv_buf; return; } + adns__diag(ads,-1,0,"gettimeofday/clock_gettime failed: %s", + strerror(errno)); adns_globalsystemfailure(ads); return; } @@ -209,11 +224,16 @@ static void timeouts_queue(adns_state ads, int act, struct timeval **tv_io, struct timeval *tvbuf, struct timeval now, struct query_queue *queue) { adns_query qu, nqu; + struct timeval expires; for (qu= queue->head; qu; qu= nqu) { nqu= qu->next; - if (!timercmp(&now,&qu->timeout,>)) { - inter_maxtoabs(tv_io,tvbuf,now,qu->timeout); + if (timercmp(&now,&qu->timeout_started,<)) /* clock rewound */ + qu->timeout_started= now; + expires= qu->timeout_started; + timevaladd(&expires, qu->timeout_ms); + if (!timercmp(&now,&expires,>)) { + inter_maxtoabs(tv_io,tvbuf,now,expires); } else { if (!act) { inter_immed(tv_io,tvbuf); return; } LIST_UNLINK(*queue,qu); @@ -284,7 +304,7 @@ void adns__timeouts(adns_state ads, int act, void adns_firsttimeout(adns_state ads, struct timeval **tv_io, struct timeval *tvbuf, struct timeval now) { - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__timeouts(ads, 0, tv_io,tvbuf, now); adns__returning(ads,0); } @@ -292,7 +312,7 @@ void adns_firsttimeout(adns_state ads, void adns_processtimeouts(adns_state ads, const struct timeval *now) { struct timeval tv_buf; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__must_gettimeofday(ads,&now,&tv_buf); if (now) adns__timeouts(ads, 1, 0,0, *now); adns__returning(ads,0); @@ -346,7 +366,7 @@ int adns_processreadable(adns_state ads, int fd, const struct timeval *now) { struct udpsocket *udp; adns_sockaddr udpaddr; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); switch (ads->tcpstate) { case server_disconnected: @@ -433,7 +453,7 @@ xit: int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { int r; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); switch (ads->tcpstate) { case server_disconnected: @@ -461,7 +481,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { } assert(FD_ISSET(ads->tcpsocket,&writeable)); if (!adns__vbuf_ensure(&ads->tcprecv,1)) { r= ENOMEM; goto xit; } - r= read(ads->tcpsocket,&ads->tcprecv.buf,1); + r= read(ads->tcpsocket,ads->tcprecv.buf,1); if (r==0 || (r<0 && (errno==EAGAIN || errno==EWOULDBLOCK))) { tcp_connected(ads,*now); r= 0; goto xit; @@ -488,6 +508,7 @@ int adns_processwriteable(adns_state ads, int fd, const struct timeval *now) { adns__tcp_broken(ads,"write",strerror(errno)); r= 0; goto xit; } else if (r>0) { + assert(r <= ads->tcpsend.used); ads->tcpsend.used -= r; memmove(ads->tcpsend.buf,ads->tcpsend.buf+r,ads->tcpsend.used); } @@ -505,7 +526,7 @@ xit: int adns_processexceptional(adns_state ads, int fd, const struct timeval *now) { - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); switch (ads->tcpstate) { case server_disconnected: case server_broken: @@ -574,7 +595,7 @@ void adns_beforeselect(adns_state ads, int *maxfd_io, fd_set *readfds_io, struct pollfd pollfds[MAX_POLLFDS]; int i, fd, maxfd, npollfds; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); if (tv_mod && (!*tv_mod || (*tv_mod)->tv_sec || (*tv_mod)->tv_usec)) { /* The caller is planning to sleep. */ @@ -605,7 +626,7 @@ void adns_afterselect(adns_state ads, int maxfd, const fd_set *readfds, struct pollfd pollfds[MAX_POLLFDS]; int npollfds, i; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__must_gettimeofday(ads,&now,&tv_buf); if (!now) goto xit; adns_processtimeouts(ads,now); @@ -623,10 +644,24 @@ xit: /* General helpful functions. */ void adns_globalsystemfailure(adns_state ads) { - adns__consistency(ads,0,cc_entex); + /* Must not be called by adns during actual processing of a + * particular query, since it reenters adns. Only safe to call in + * situations where it would be safe to call adns_returning. */ + adns__consistency(ads,0,cc_enter); - while (ads->udpw.head) adns__query_fail(ads->udpw.head, adns_s_systemfail); - while (ads->tcpw.head) adns__query_fail(ads->tcpw.head, adns_s_systemfail); + for (;;) { + adns_query qu; +#define GSF_QQ(QQ) \ + if ((qu= ads->QQ.head)) { \ + LIST_UNLINK(ads->QQ,qu); \ + adns__query_fail(qu, adns_s_systemfail); \ + continue; \ + } + GSF_QQ(udpw); + GSF_QQ(tcpw); +#undef GSF_QQ + break; + } switch (ads->tcpstate) { case server_connecting: @@ -648,9 +683,9 @@ int adns_processany(adns_state ads) { struct pollfd pollfds[MAX_POLLFDS]; int npollfds; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); - r= gettimeofday(&now,0); + r= adns__gettimeofday(ads,&now); if (!r) adns_processtimeouts(ads,&now); /* We just use adns__fdevents to loop over the fd's trying them. @@ -707,7 +742,7 @@ int adns_wait(adns_state ads, fd_set readfds, writefds, exceptfds; struct timeval tvbuf, *tvp; - adns__consistency(ads,*query_io,cc_entex); + adns__consistency(ads,*query_io,cc_enter); for (;;) { r= adns__internal_check(ads,query_io,answer_r,context_r); if (r != EAGAIN) break; @@ -739,8 +774,8 @@ int adns_check(adns_state ads, struct timeval now; int r; - adns__consistency(ads,*query_io,cc_entex); - r= gettimeofday(&now,0); + adns__consistency(ads,*query_io,cc_enter); + r= adns__gettimeofday(ads,&now); if (!r) adns__autosys(ads,now); r= adns__internal_check(ads,query_io,answer_r,context_r); diff --git a/src/general.c b/src/general.c index c4d1f55..cfe07bd 100644 --- a/src/general.c +++ b/src/general.c @@ -5,7 +5,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -219,7 +219,7 @@ adns_status adns_rr_info(adns_rrtype type, if (!datap) return adns_s_ok; adns__vbuf_init(&vb); - st= typei->convstring(&vb,datap); + st= typei->convstring(&vb,type,datap); if (st) goto x_freevb; if (!adns__vbuf_append(&vb,"",1)) { st= adns_s_nomemory; goto x_freevb; } assert(strlen(vb.buf) == vb.used-1); @@ -288,14 +288,14 @@ const char *adns_strerror(adns_status st) { const struct sinfo *si; si= findsinfo(st); - return si->string; + return si ? si->string : 0; } const char *adns_errabbrev(adns_status st) { const struct sinfo *si; si= findsinfo(st); - return si->abbrev; + return si ? si->abbrev : 0; } @@ -332,7 +332,7 @@ const char *adns_errtypeabbrev(adns_status st) { sti= bsearch(&st,stinfos, sizeof(stinfos)/sizeof(*stinfos), sizeof(*stinfos), sti_compar); - return sti->abbrev; + return sti ? sti->abbrev : 0; } diff --git a/src/internal.h b/src/internal.h index 00cf825..c03a77b 100644 --- a/src/internal.h +++ b/src/internal.h @@ -6,7 +6,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -53,7 +53,7 @@ typedef unsigned char byte; /* Configuration and constants */ -#define MAXSERVERS 5 +#define MAXSERVERS 5 /* do not increase beyond no. of bits in `unsigned'! */ #define MAXSORTLIST 15 #define UDPMAXRETRIES 15 #define UDPRETRYMS 2000 @@ -95,7 +95,8 @@ typedef unsigned char byte; typedef enum { cc_user, - cc_entex, + cc_enter, + cc_exit, cc_freq } consistency_checks; @@ -170,7 +171,7 @@ typedef struct typeinfo { * Previously, used alloc_interim, now use alloc_final. */ - adns_status (*convstring)(vbuf *vb, const void *data); + adns_status (*convstring)(vbuf *vb, adns_rrtype, const void *data); /* Converts the RR data to a string representation in vbuf. * vbuf will be appended to (it must have been initialised), * and will not be null-terminated by convstring. @@ -246,7 +247,7 @@ union maxalign { void *p; void (*fp)(void); union maxalign *up; -} data; +}; struct adns__query { adns_state ads; @@ -297,7 +298,8 @@ struct adns__query { int id, flags, retries; int udpnextserver; unsigned long udpsent; /* bitmap indexed by server */ - struct timeval timeout; + int timeout_ms; + struct timeval timeout_started; time_t expires; /* Earliest expiry time of any record we used. */ qcontext ctx; @@ -371,7 +373,8 @@ struct adns__state { int configerrno; struct query_queue udpw, tcpw, childw, output, intdone; adns_query forallnext; - int nextid, tcpsocket; + unsigned nextid; + int tcpsocket; struct udpsocket { int af; int fd; } udpsockets[MAXUDP]; int nudpsockets; vbuf tcpsend, tcprecv; @@ -719,6 +722,8 @@ void adns__returning(adns_state ads, adns_query qu); * external-faciing functions which call adns__returning should * normally be avoided in internal code. */ +void adns__intdone_process(adns_state ads); + /* From reply.c: */ void adns__procdgram(adns_state ads, const byte *dgram, int len, @@ -881,6 +886,17 @@ void adns__autosys(adns_state ads, struct timeval now); * lest we end up in recursive descent ! */ +static inline void +adns__timeout_set(adns_query qu, struct timeval now, long ms) + { qu->timeout_ms= ms; qu->timeout_started= now; } + +static inline void +adns__timeout_clear(adns_query qu) + { qu->timeout_ms= 0; timerclear(&qu->timeout_started); } + + +int adns__gettimeofday(adns_state ads, struct timeval *tv_buf); + void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io, struct timeval *tv_buf); /* Call with care - might reentrantly cause queries to be completed! */ @@ -934,7 +950,7 @@ static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; } (( ((sz)+sizeof(union maxalign)-1) / sizeof(union maxalign) ) \ * sizeof(union maxalign) ) -#define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff) +#define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ffu) #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)) #define GET_L(cb,tv) ( (tv)=0, \ diff --git a/src/parse.c b/src/parse.c index 07d0614..2eb68e4 100644 --- a/src/parse.c +++ b/src/parse.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -71,6 +71,7 @@ adns_status adns__findlabel_next(findlabel_state *fls, int *lablen_r, int *labstart_r) { int lablen, jumpto; const char *dgram; + int had_pointer= 0; dgram= fls->dgram; for (;;) { @@ -81,6 +82,7 @@ adns_status adns__findlabel_next(findlabel_state *fls, if ((lablen & 0x0c0) != 0x0c0) return adns_s_unknownformat; if (fls->cbyte >= fls->dglen) goto x_truncated; if (fls->cbyte >= fls->max) goto x_badresponse; + if (had_pointer++ >= 2) goto x_loop; GET_B(fls->cbyte,jumpto); jumpto |= (lablen&0x3f)<<8; if (fls->dmend_r) *(fls->dmend_r)= fls->cbyte; @@ -107,7 +109,12 @@ adns_status adns__findlabel_next(findlabel_state *fls, x_badresponse: adns__diag(fls->ads,fls->serv,fls->qu, - "label in domain runs beyond end of domain"); + "label in domain runs or points outside of packet"); + return adns_s_invalidresponse; + + x_loop: + adns__diag(fls->ads,fls->serv,fls->qu, + "compressed label pointer chain"); return adns_s_invalidresponse; } diff --git a/src/poll.c b/src/poll.c index 75bc192..6484b34 100644 --- a/src/poll.c +++ b/src/poll.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -37,7 +37,7 @@ int adns_beforepoll(adns_state ads, struct pollfd *fds, int *nfds_io, int space, found, timeout_ms, r; struct pollfd fds_tmp[MAX_POLLFDS]; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); if (timeout_io) { adns__must_gettimeofday(ads,&now,&tv_nowbuf); @@ -85,10 +85,11 @@ void adns_afterpoll(adns_state ads, const struct pollfd *fds, int nfds, const struct timeval *now) { struct timeval tv_buf; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); adns__must_gettimeofday(ads,&now,&tv_buf); if (now) { adns__timeouts(ads, 1, 0,0, *now); + adns__intdone_process(ads); /* fdevents calls adns_processwriteable */ adns__fdevents(ads, fds,nfds, 0,0,0,0, *now,0); } adns__returning(ads,0); @@ -101,7 +102,7 @@ int adns_wait_poll(adns_state ads, int r, nfds, to; struct pollfd fds[MAX_POLLFDS]; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); for (;;) { r= adns__internal_check(ads,query_io,answer_r,context_r); diff --git a/src/query.c b/src/query.c index 480cbf5..82adbdd 100644 --- a/src/query.c +++ b/src/query.c @@ -6,7 +6,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -72,7 +72,7 @@ static adns_query query_alloc(adns_state ads, qu->retries= 0; qu->udpnextserver= 0; qu->udpsent= 0; - timerclear(&qu->timeout); + adns__timeout_clear(qu); qu->expires= now.tv_sec + MAXTTLBELIEVE; memset(&qu->ctx,0,sizeof(qu->ctx)); @@ -273,7 +273,7 @@ int adns_submit(adns_state ads, adns_query qu; const char *p; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); if (flags & ~(adns_queryflags)0x4009ffff) /* 0x40080000 are reserved for `harmless' future expansion @@ -284,7 +284,7 @@ int adns_submit(adns_state ads, typei= adns__findtype(type); if (!typei) return ENOSYS; - r= gettimeofday(&now,0); if (r) goto x_errno; + r= adns__gettimeofday(ads,&now); if (r) goto x_errno; qu= query_alloc(ads,typei,type,flags,now); if (!qu) goto x_errno; qu->ctx.ext= context; @@ -431,10 +431,10 @@ void adns__free_interim(adns_query qu, void *p) { if (!an) return; assert(!qu->final_allocspace); + qu->interim_allocd -= sz; + assert(qu->interim_allocd >= 0); LIST_UNLINK(qu->allocations, an); free(an); - qu->interim_allocd -= sz; - assert(!qu->interim_allocd >= 0); } void *adns__alloc_mine(adns_query qu, size_t sz) { @@ -504,7 +504,7 @@ static void free_query_allocs(adns_query qu) { qu->query_dgram= 0; } -void adns__returning(adns_state ads, adns_query qu_for_caller) { +void adns__intdone_process(adns_state ads) { while (ads->intdone.head) { adns_query iq= ads->intdone.head; adns_query parent= iq->parent; @@ -516,7 +516,11 @@ void adns__returning(adns_state ads, adns_query qu_for_caller) { free(iq->answer); free(iq); } - adns__consistency(ads,qu_for_caller,cc_entex); +} + +void adns__returning(adns_state ads, adns_query qu_for_caller) { + adns__intdone_process(ads); + adns__consistency(ads,qu_for_caller,cc_exit); } void adns__cancel(adns_query qu) { @@ -554,7 +558,7 @@ void adns_cancel(adns_query qu) { assert(!qu->parent); ads= qu->ads; - adns__consistency(ads,qu,cc_entex); + adns__consistency(ads,qu,cc_enter); adns__cancel(qu); adns__returning(ads,0); } diff --git a/src/reply.c b/src/reply.c index bd2d0e8..caf5c05 100644 --- a/src/reply.c +++ b/src/reply.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -35,7 +35,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, int flg_ra, flg_rd, flg_tc, flg_qr, opcode; int rrtype, rrclass, rdlength, rdstart; int anstart, nsstart; - int ownermatched, l, nrrs; + int ownermatched, l, nrrs, restartfrom; unsigned long ttl, soattl; const typeinfo *typei; adns_query qu, nqu; @@ -162,6 +162,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, * If it has any CNAMEs we stuff them in the answer. */ wantedrrs= 0; + restartfrom= -1; cbyte= anstart; for (rri= 0; rrianswer->type & adns_rrt_typemask)) { + if (restartfrom==-1) restartfrom= rri; wantedrrs++; } else { adns__debug(ads,serv,qu,"ignoring answer RR" @@ -331,13 +333,15 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, pai.arcount= arcount; pai.now= now; + assert(restartfrom>=0); for (rri=0, nrrs=0; rrianswer->type & adns_rrt_typemask) || + rrclass != DNS_CLASS_IN || !ownermatched) continue; adns__update_expires(qu,ttl,now); @@ -366,6 +370,11 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen, adns__query_fail(qu,adns_s_invalidresponse); return; } + if (qu->flags & adns_qf_usevc) { + adns__diag(ads,serv,qu,"server sent datagram with TC over TCP"); + adns__query_fail(qu,adns_s_invalidresponse); + return; + } qu->flags |= adns_qf_usevc; x_restartquery: diff --git a/src/setup.c b/src/setup.c index 8ff92d2..3646968 100644 --- a/src/setup.c +++ b/src/setup.c @@ -5,7 +5,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -147,11 +147,17 @@ static void ccf_search(adns_state ads, const char *fn, tl= 0; while (nextword(&bufp,&word,&l)) { count++; tl += l+1; } - newptrs= malloc(sizeof(char*)*count); - if (!newptrs) { saveerr(ads,errno); return; } + if (count) { + newptrs= malloc(sizeof(char*)*count); + if (!newptrs) { saveerr(ads,errno); return; } - newchars= malloc(tl); - if (!newchars) { saveerr(ads,errno); free(newptrs); return; } + newchars= malloc(tl); + if (!newchars) { saveerr(ads,errno); free(newptrs); return; } + } else { + assert(!tl); + newptrs= 0; + newchars= 0; + } bufp= buf; pp= newptrs; @@ -222,11 +228,12 @@ static void ccf_sortlist(adns_state ads, const char *fn, } } else { maskwhat = "prefix length"; - initial= strtoul(slash,&ep,10); - if (*ep || initial>adns__addr_width(sl->base.sa.sa_family)) { + unsigned long prefixlen = strtoul(slash,&ep,10); + if (*ep || prefixlen>adns__addr_width(sl->base.sa.sa_family)) { configparseerr(ads,fn,lno,"mask length `%s' invalid",slash); continue; } + initial= prefixlen; sl->mask.sa.sa_family= sl->base.sa.sa_family; adns__prefix_mask(&sl->mask, initial); } @@ -735,7 +742,7 @@ static int init_files(adns_state *ads_r, adns_initflags flags, r= init_finish(ads); if (r) return r; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_exit); *ads_r= ads; return 0; } @@ -761,7 +768,7 @@ static int init_strcfg(adns_state *ads_r, adns_initflags flags, } r= init_finish(ads); if (r) return r; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_exit); *ads_r= ads; return 0; } @@ -785,15 +792,20 @@ int adns_init_logfn(adns_state *newstate_r, adns_initflags flags, return init_files(newstate_r, flags, logfn, logfndata); } +static void cancel_all(adns_query qu) { + if (!qu->parent) adns__cancel(qu); + else cancel_all(qu->parent); +} + void adns_finish(adns_state ads) { int i; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); for (;;) { - if (ads->udpw.head) adns__cancel(ads->udpw.head); - else if (ads->tcpw.head) adns__cancel(ads->tcpw.head); - else if (ads->childw.head) adns__cancel(ads->childw.head); - else if (ads->output.head) adns__cancel(ads->output.head); - else if (ads->intdone.head) adns__cancel(ads->output.head); + if (ads->udpw.head) cancel_all(ads->udpw.head); + else if (ads->tcpw.head) cancel_all(ads->tcpw.head); + else if (ads->childw.head) cancel_all(ads->childw.head); + else if (ads->output.head) cancel_all(ads->output.head); + else if (ads->intdone.head) cancel_all(ads->output.head); else break; } for (i=0; inudpsockets; i++) close(ads->udpsockets[i].fd); @@ -805,7 +817,7 @@ void adns_finish(adns_state ads) { } void adns_forallqueries_begin(adns_state ads) { - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); ads->forallnext= ads->udpw.head ? ads->udpw.head : ads->tcpw.head ? ads->tcpw.head : @@ -816,7 +828,7 @@ void adns_forallqueries_begin(adns_state ads) { adns_query adns_forallqueries_next(adns_state ads, void **context_r) { adns_query qu, nqu; - adns__consistency(ads,0,cc_entex); + adns__consistency(ads,0,cc_enter); nqu= ads->forallnext; for (;;) { qu= nqu; diff --git a/src/transmit.c b/src/transmit.c index 33c3329..bf2f8c6 100644 --- a/src/transmit.c +++ b/src/transmit.c @@ -5,7 +5,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -87,6 +87,7 @@ static adns_status qdparselabel(adns_state ads, while (p!=pe && (c= *p++)!='.') { if (c=='\\') { if (!(flags & adns_qf_quoteok_query)) return adns_s_querydomaininvalid; + if (p==pe) return adns_s_querydomaininvalid; if (ctype_digit(p[0])) { if (p+1==pe || p+2==pe) return adns_s_querydomaininvalid; if (ctype_digit(p[1]) && ctype_digit(p[2])) { @@ -233,8 +234,7 @@ void adns__querysend_tcp(adns_query qu, struct timeval now) { static void query_usetcp(adns_query qu, struct timeval now) { qu->state= query_tcpw; - qu->timeout= now; - timevaladd(&qu->timeout,TCPWAITMS); + adns__timeout_set(qu,now,TCPWAITMS); LIST_LINK_TAIL(qu->ads->tcpw,qu); adns__querysend_tcp(qu,now); adns__tcp_tryconnect(qu->ads,now); @@ -280,8 +280,7 @@ void adns__query_send(adns_query qu, struct timeval now) { if (r<0 && errno != EAGAIN) adns__warn(ads,serv,0,"sendto failed: %s",strerror(errno)); - qu->timeout= now; - timevaladd(&qu->timeout,UDPRETRYMS); + adns__timeout_set(qu, now, UDPRETRYMS); qu->udpsent |= (1<udpnextserver= (serv+1)%ads->nservers; qu->retries++; diff --git a/src/tvarith.h b/src/tvarith.h index fe3b78d..8dd7896 100644 --- a/src/tvarith.h +++ b/src/tvarith.h @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology diff --git a/src/types.c b/src/types.c index a4478fa..428dbfa 100644 --- a/src/types.c +++ b/src/types.c @@ -4,7 +4,7 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006,2014-2016 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology @@ -221,7 +221,7 @@ static adns_status pa_txt(const parseinfo *pai, int cbyte, return adns_s_ok; } -static adns_status cs_txt(vbuf *vb, const void *datap) { +static adns_status cs_txt(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_intstr *const *rrp= datap; const adns_rr_intstr *current; adns_status st; @@ -238,7 +238,7 @@ static adns_status cs_txt(vbuf *vb, const void *datap) { * _hinfo (cs) */ -static adns_status cs_hinfo(vbuf *vb, const void *datap) { +static adns_status cs_hinfo(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_intstrpair *rrp= datap; adns_status st; @@ -316,7 +316,7 @@ static adns_status csp_genaddr(vbuf *vb, int af, const void *p) { return adns_s_ok; } -static adns_status cs_inaddr(vbuf *vb, const void *datap) { +static adns_status cs_inaddr(vbuf *vb, adns_rrtype rrt, const void *datap) { return csp_genaddr(vb, AF_INET,datap); } @@ -338,7 +338,7 @@ static int di_in6addr(adns_state ads, return dip_genaddr(ads,AF_INET6,datap_a,datap_b); } -static adns_status cs_in6addr(vbuf *vb, const void *datap) { +static adns_status cs_in6addr(vbuf *vb, adns_rrtype rrt, const void *datap) { return csp_genaddr(vb,AF_INET6,datap); } @@ -499,7 +499,7 @@ static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) { return adns_s_ok; } -static adns_status cs_addr(vbuf *vb, const void *datap) { +static adns_status cs_addr(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_addr *rrp= datap; return csp_addr(vb,rrp); @@ -691,7 +691,7 @@ static void icb_addr(adns_query parent, adns_query child) { * settled on. */ adns__cancel_children(parent); - r= gettimeofday(&now, 0); if (r) goto x_gtod; + r= adns__gettimeofday(ads,&now); if (r) goto x_gtod; qf= adns__qf_addr_cname; if (!(parent->flags & adns_qf_cname_loose)) qf |= adns_qf_cname_forbid; addr_subqueries(parent, now, qf, child->vb.buf, child->vb.used); @@ -712,7 +712,7 @@ static void icb_addr(adns_query parent, adns_query child) { adns__cancel_children(parent); adns__free_interim(parent, pans->rrs.bytes); pans->rrs.bytes= 0; pans->nrrs= 0; - r= gettimeofday(&now, 0); if (r) goto x_gtod; + r= adns__gettimeofday(ads,&now); if (r) goto x_gtod; adns__search_next(ads, parent, now); return; } @@ -737,7 +737,8 @@ x_gtod: /* We have our own error handling, because adns__must_gettimeofday * handles errors by calling adns_globalsystemfailure, which would * reenter the query processing logic. */ - adns__diag(ads, -1, parent, "gettimeofday failed: %s", strerror(errno)); + adns__diag(ads, -1, parent, "gettimeofday/clock_gettime failed: %s", + strerror(errno)); err= adns_s_systemfail; goto x_err; @@ -785,7 +786,7 @@ static adns_status csp_domain(vbuf *vb, const char *domain) { return adns_s_ok; } -static adns_status cs_domain(vbuf *vb, const void *datap) { +static adns_status cs_domain(vbuf *vb, adns_rrtype rrt, const void *datap) { const char *const *domainp= datap; return csp_domain(vb,*domainp); } @@ -838,6 +839,7 @@ static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha, &type, &class, &ttl, &rdlen, &rdstart, pai->dgram, pai->dglen, dmstart, &ownermatched); if (st) return st; + if (type==-1) continue; if (!ownermatched || class != DNS_CLASS_IN) continue; typef= addr_rrtypeflag(type); if (!(want & typef)) continue; @@ -1000,11 +1002,13 @@ static void mf_hostaddr(adns_query qu, void *datap) { mfp_hostaddr(qu,rrp); } -static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) { +static adns_status csp_hostaddr(vbuf *vb, adns_rrtype rrt, + const adns_rr_hostaddr *rrp) { const char *errstr; adns_status st; char buf[20]; int i; + size_t addrsz= gsz_addr(0, rrt); st= csp_domain(vb,rrp->host); if (st) return st; @@ -1024,7 +1028,7 @@ static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) { CSP_ADDSTR(" ("); for (i=0; inaddrs; i++) { CSP_ADDSTR(" "); - st= csp_addr(vb,&rrp->addrs[i]); + st= csp_addr(vb, (const void*)((const char*)rrp->addrs + addrsz*i)); } CSP_ADDSTR(" )"); } else { @@ -1033,10 +1037,10 @@ static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) { return adns_s_ok; } -static adns_status cs_hostaddr(vbuf *vb, const void *datap) { +static adns_status cs_hostaddr(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_hostaddr *rrp= datap; - return csp_hostaddr(vb,rrp); + return csp_hostaddr(vb,rrt,rrp); } /* @@ -1108,26 +1112,35 @@ static void mf_inthostaddr(adns_query qu, void *datap) { mfp_hostaddr(qu,&rrp->ha); } -static adns_status cs_inthostaddr(vbuf *vb, const void *datap) { - const adns_rr_inthostaddr *rrp= datap; +static adns_status csp_intofinthost(vbuf *vb, int i) { char buf[10]; - sprintf(buf,"%u ",rrp->i); + if (i < 0 || i > 0xffff) + /* currently only used for MX whose priorities are 16-bit */ + return adns_s_invaliddata; + + sprintf(buf,"%u ",i); CSP_ADDSTR(buf); + return adns_s_ok; +} + +static adns_status cs_inthostaddr(vbuf *vb, adns_rrtype rrt, const void *datap) { + const adns_rr_inthostaddr *rrp= datap; + adns_status st; - return csp_hostaddr(vb,&rrp->ha); + st = csp_intofinthost(vb,rrp->i); if (st) return st; + return csp_hostaddr(vb,rrt,&rrp->ha); } /* * _inthost (cs) */ -static adns_status cs_inthost(vbuf *vb, const void *datap) { +static adns_status cs_inthost(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_intstr *rrp= datap; - char buf[10]; + adns_status st; - sprintf(buf,"%u ",rrp->i); - CSP_ADDSTR(buf); + st = csp_intofinthost(vb,rrp->i); if (st) return st; return csp_domain(vb,rrp->str); } @@ -1278,6 +1291,7 @@ static adns_status pap_mailbox822(const parseinfo *pai, pai->dgram, pai->dglen, max, *cbyte_io, cbyte_io); st= adns__findlabel_next(&fls,&lablen,&labstart); + if (st) return st; if (!lablen) { adns__vbuf_appendstr(vb,"."); goto x_ok; @@ -1350,7 +1364,7 @@ static adns_status pa_rp(const parseinfo *pai, int cbyte, return adns_s_ok; } -static adns_status cs_rp(vbuf *vb, const void *datap) { +static adns_status cs_rp(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_strpair *rrp= datap; adns_status st; @@ -1370,7 +1384,7 @@ static adns_status pa_soa(const parseinfo *pai, int cbyte, adns_rr_soa *rrp= datap; const byte *dgram= pai->dgram; adns_status st; - int msw, lsw, i; + int i; st= pap_domain(pai, &cbyte, max, &rrp->mname, pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0); @@ -1382,9 +1396,8 @@ static adns_status pa_soa(const parseinfo *pai, int cbyte, if (cbyte+20 != max) return adns_s_invaliddata; for (i=0; i<5; i++) { - GET_W(cbyte,msw); - GET_W(cbyte,lsw); - (&rrp->serial)[i]= (msw<<16) | lsw; + unsigned long v; + (&rrp->serial)[i]= GET_L(cbyte, v); } return adns_s_ok; @@ -1397,7 +1410,7 @@ static void mf_soa(adns_query qu, void *datap) { adns__makefinal_str(qu,&rrp->rname); } -static adns_status cs_soa(vbuf *vb, const void *datap) { +static adns_status cs_soa(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_soa *rrp= datap; char buf[20]; int i; @@ -1408,6 +1421,8 @@ static adns_status cs_soa(vbuf *vb, const void *datap) { st= csp_mailbox(vb,rrp->rname); if (st) return st; for (i=0; i<5; i++) { + if (rrp->serial > 0xffffffffUL) + return adns_s_invaliddata; sprintf(buf," %lu",(&rrp->serial)[i]); CSP_ADDSTR(buf); } @@ -1496,12 +1511,16 @@ static int di_srv(adns_state ads, const void *datap_a, const void *datap_b) { static adns_status csp_srv_begin(vbuf *vb, const adns_rr_srvha *rrp /* might be adns_rr_srvraw* */) { char buf[30]; + if (rrp->priority < 0 || rrp->priority > 0xffff || + rrp->weight < 0 || rrp->weight > 0xffff || + rrp->port < 0 || rrp->port > 0xffff) + return adns_s_invaliddata; sprintf(buf,"%u %u %u ", rrp->priority, rrp->weight, rrp->port); CSP_ADDSTR(buf); return adns_s_ok; } -static adns_status cs_srvraw(vbuf *vb, const void *datap) { +static adns_status cs_srvraw(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_srvraw *rrp= datap; adns_status st; @@ -1509,12 +1528,12 @@ static adns_status cs_srvraw(vbuf *vb, const void *datap) { return csp_domain(vb,rrp->host); } -static adns_status cs_srvha(vbuf *vb, const void *datap) { +static adns_status cs_srvha(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_srvha *rrp= datap; adns_status st; st= csp_srv_begin(vb,(const void*)datap); if (st) return st; - return csp_hostaddr(vb,&rrp->ha); + return csp_hostaddr(vb,rrt,&rrp->ha); } static void postsort_srv(adns_state ads, void *array, int nrrs,int rrsz, @@ -1605,12 +1624,15 @@ static adns_status pa_opaque(const parseinfo *pai, int cbyte, return adns_s_ok; } -static adns_status cs_opaque(vbuf *vb, const void *datap) { +static adns_status cs_opaque(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_byteblock *rrp= datap; char buf[10]; int l; unsigned char *p; + if (rrp->len < 0 || rrp->len > 0xffff) + return adns_s_invaliddata; + sprintf(buf,"\\# %d",rrp->len); CSP_ADDSTR(buf);