X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=regress%2Fhplayback.c.m4;h=dd98f0ec0b8bf1df4172286ebecfd07232318614;hb=HEAD;hp=fb4295cca0dc31e6bb86bc6ce3969871712dc40b;hpb=d6286f09c92b303c9b23a463fa40ae3684b9bbd2;p=adns.git diff --git a/regress/hplayback.c.m4 b/regress/hplayback.c.m4 index fb4295c..7e688bf 100644 --- a/regress/hplayback.c.m4 +++ b/regress/hplayback.c.m4 @@ -2,12 +2,8 @@ m4_dnl hplayback.c.m4 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,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 -m4_dnl (See the file INSTALL for full details.) +m4_dnl This file is part of adns, which is Copyright Ian Jackson +m4_dnl and contributors (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 @@ -37,17 +33,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 +52,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,11 +92,23 @@ static void Pcheckinput(void) { if (feof(Tinputfile)) Psyntax("eof at syscall reply"); } -void Tensurerecordfile(void) { +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; fd = Ttestinputfd(); @@ -124,29 +160,37 @@ 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; } static void P_updatetime(void) { int chars; - unsigned long sec, usec; + unsigned long sec; + long 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); + sscanf(vb2.buf," +%lu.%ld%n",&sec,&usec,&chars); if (chars==-1) Psyntax("update time invalid"); currenttime.tv_sec+= sec; - currenttime.tv_usec+= usec; - if (currenttime.tv_usec > 1000000) { + usec = (long)currenttime.tv_usec + usec; + while (usec < 0) { + currenttime.tv_sec--; + usec += 1000000; + } + while (usec > 1000000) { currenttime.tv_sec++; - currenttime.tv_usec -= 1000000; + usec -= 1000000; } + currenttime.tv_usec = usec; if (vb2.buf[chars] != hm_squote\nhm_squote) Psyntax("not newline after update time"); } static void Pfdset(fd_set *set, int max) { - int r, c; + int c; + unsigned long ul; char *ep; if (!set) { @@ -156,16 +200,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++; } } @@ -198,12 +259,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= ", "; @@ -235,6 +299,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"); @@ -274,7 +346,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)) { @@ -292,7 +364,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); } @@ -301,12 +372,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 @@ -322,7 +390,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) @@ -330,27 +398,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) { @@ -363,7 +460,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"); } @@ -379,7 +476,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(); @@ -390,3 +491,5 @@ int H$1(hm_args_massage($3,void)) { m4_define(`hm_specsyscall', `') m4_include(`hsyscalls.i4') + +hm_stdsyscall_close