nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 4a482325865c83dbb0a0e20ce8bfc8f9eae42860
parent 7d4a9d5da52686b2469a426392cdf16148a10218
Author: Rolf Eike Beer <eike@sf-mail.de>
Date:   Fri,  4 Dec 2020 17:56:48 +0100

add noreturn attribute to a couple of functions

When building with -Wextra there are a lot of false positives for fallthroughs,
which happen because the compiler does not detect that these functions in fact
never return. Add an attribute if building with gcc. According to the
documentation it is supported since version 2.5, which is way older than
anything one can reasonably expect this to work on.

Diffstat:
M.github/workflows/ccpp.yml | 2+-
Anoreturn.h | 10++++++++++
Mqmail-inject.c | 17+++++++++--------
Mqmail-local.c | 18+++++++++---------
Mqmail-popup.c | 22+++++++++++-----------
Mqmail-qmtpd.c | 5+++--
Mqmail-qread.c | 9+++++----
Mqmail-queue.c | 11++++++-----
Mqmail-remote.c | 31++++++++++++++++---------------
Mqmail-start.c | 3++-
Msendmail.c | 9+++++----
Mstrerr.h | 4+++-
Mtcp-env.c | 3++-
13 files changed, 82 insertions(+), 62 deletions(-)

diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml @@ -75,7 +75,7 @@ jobs: OS: ${{ matrix.host }} - name: configure - run: echo "${CC} -O2 -fPIC -Wall -Wshadow -Werror=implicit-function-declaration ${CFLAGS}" > conf-cc + run: echo "${CC} -O2 -fPIC -Wall -Wshadow -Werror=implicit-function-declaration -Wimplicit-fallthrough ${CFLAGS}" > conf-cc env: CC: ${{ matrix.config.cc }} CFLAGS: ${{ matrix.config.cflags }} diff --git a/noreturn.h b/noreturn.h @@ -0,0 +1,10 @@ +#ifndef NORETURN_H +#define NORETURN_H + +#if defined(__clang__) || defined(__GNUC__) +#define _noreturn_ __attribute__((noreturn)) +#else +#define _noreturn_ +#endif + +#endif diff --git a/qmail-inject.c b/qmail-inject.c @@ -17,6 +17,7 @@ #include "qmail.h" #include "now.h" #include "exit.h" +#include "noreturn.h" #include "quote.h" #include "headerbody.h" #include "auto_qmail.h" @@ -57,18 +58,18 @@ void put(s,len) char *s; int len; { if (flagqueue) qmail_put(&qqt,s,len); else substdio_put(subfdout,s,len); } void puts(s) char *s; { put(s,str_len(s)); } -void perm() { _exit(100); } -void temp() { _exit(111); } -void die_nomem() { +void _noreturn_ perm() { _exit(100); } +void _noreturn_ temp() { _exit(111); } +void _noreturn_ die_nomem() { substdio_putsflush(subfderr,"qmail-inject: fatal: out of memory\n"); temp(); } -void die_invalid(sa) stralloc *sa; { +void _noreturn_ die_invalid(sa) stralloc *sa; { substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: "); substdio_putflush(subfderr,sa->s,sa->len); perm(); } -void die_qqt() { +void _noreturn_ die_qqt() { substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); } -void die_chdir() { +void _noreturn_ die_chdir() { substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); } -void die_read() { +void _noreturn_ die_read() { if (errno == error_nomem) die_nomem(); substdio_putsflush(subfderr,"qmail-inject: fatal: read error\n"); temp(); } void doordie(sa,r) stralloc *sa; int r; { @@ -88,7 +89,7 @@ saa hrrlist = {0}; saa reciplist = {0}; int flagresent; -void exitnicely() +void _noreturn_ exitnicely() { char *qqx; diff --git a/qmail-local.c b/qmail-local.c @@ -31,16 +31,16 @@ #include "gfrom.h" #include "auto_patrn.h" -void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); } - -void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); } -void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); } -void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); } -void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); } -void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); } -void temp_slowlock() +void _noreturn_ usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); } + +void _noreturn_ temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); } +void _noreturn_ temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); } +void _noreturn_ temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); } +void _noreturn_ temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); } +void _noreturn_ temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); } +void _noreturn_ temp_slowlock() { strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); } -void temp_qmail(fn) char *fn; +void _noreturn_ temp_qmail(char *fn) { strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); } int flagdoit; diff --git a/qmail-popup.c b/qmail-popup.c @@ -10,11 +10,12 @@ #include "now.h" #include "fmt.h" #include "exit.h" +#include "noreturn.h" #include "readwrite.h" #include "timeoutread.h" #include "timeoutwrite.h" -void die() { _exit(1); } +void _noreturn_ die() { _exit(1); } GEN_SAFE_TIMEOUTREAD(saferead,1200,fd,die()) GEN_SAFE_TIMEOUTWRITE(safewrite,1200,fd,die()) @@ -41,11 +42,11 @@ void err(s) char *s; flush(); } -void die_usage() { err("usage: popup hostname subprogram"); die(); } -void die_nomem() { err("out of memory"); die(); } -void die_pipe() { err("unable to open pipe"); die(); } -void die_write() { err("unable to write pipe"); die(); } -void die_fork() { err("unable to fork"); die(); } +void _noreturn_ die_usage() { err("usage: popup hostname subprogram"); die(); } +void _noreturn_ die_nomem() { err("out of memory"); die(); } +void _noreturn_ die_pipe() { err("unable to open pipe"); die(); } +void _noreturn_ die_write() { err("unable to write pipe"); die(); } +void _noreturn_ die_fork() { err("unable to fork"); die(); } void die_childcrashed() { err("aack, child crashed"); } void die_badauth() { err("authorization failed"); } @@ -54,7 +55,7 @@ void err_wantuser() { err("USER first"); } void err_authoriz(arg) char *arg; { err("authorization first"); } void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } -void pop3_quit(arg) char *arg; { okay(0); die(); } +void _noreturn_ pop3_quit(char *arg) { okay(0); die(); } char unique[FMT_ULONG + FMT_ULONG + 3]; @@ -66,10 +67,9 @@ substdio ssup; char upbuf[128]; -void doanddie(user,userlen,pass) -char *user; -unsigned int userlen; /* including 0 byte */ -char *pass; +void _noreturn_ doanddie(char *user, + unsigned int userlen, /* including 0 byte */ + char *pass) { int child; int wstat; diff --git a/qmail-qmtpd.c b/qmail-qmtpd.c @@ -5,6 +5,7 @@ #include "str.h" #include "fmt.h" #include "env.h" +#include "noreturn.h" #include "scan.h" #include "sig.h" #include "rcpthosts.h" @@ -14,8 +15,8 @@ #include "received.h" #include "exit.h" -void badproto() { _exit(100); } -void resources() { _exit(111); } +void _noreturn_ badproto() { _exit(100); } +void _noreturn_ resources() { _exit(111); } ssize_t safewrite(int fd, const void *buf, size_t len) { diff --git a/qmail-qread.c b/qmail-qread.c @@ -12,13 +12,14 @@ #include "open.h" #include "datetime.h" #include "date822fmt.h" +#include "noreturn.h" #include "readwrite.h" #include "error.h" #include "exit.h" readsubdir rs; -void die(n) int n; { substdio_flush(subfdout); _exit(n); } +void _noreturn_ die(n) int n; { substdio_flush(subfdout); _exit(n); } void warn(s1,s2) char *s1; char *s2; { @@ -31,9 +32,9 @@ void warn(s1,s2) char *s1; char *s2; substdio_puts(subfdout,"\n"); } -void die_nomem() { substdio_puts(subfdout,"fatal: out of memory\n"); die(111); } -void die_chdir() { warn("fatal: unable to chdir",""); die(111); } -void die_opendir(fn) char *fn; { warn("fatal: unable to opendir ",fn); die(111); } +void _noreturn_ die_nomem() { substdio_puts(subfdout,"fatal: out of memory\n"); die(111); } +void _noreturn_ die_chdir() { warn("fatal: unable to chdir",""); die(111); } +void _noreturn_ die_opendir(char *fn) { warn("fatal: unable to opendir ",fn); die(111); } void err(id) unsigned long id; { diff --git a/qmail-queue.c b/qmail-queue.c @@ -12,6 +12,7 @@ #include "now.h" #include "triggerpull.h" #include "extra.h" +#include "noreturn.h" #include "uidgid.h" #include "auto_qmail.h" #include "auto_uids.h" @@ -60,11 +61,11 @@ void cleanup() } } -void die(e) int e; { _exit(e); } -void die_write() { cleanup(); die(53); } -void die_read() { cleanup(); die(54); } -void sigalrm() { /* thou shalt not clean up here */ die(52); } -void sigbug() { die(81); } +void _noreturn_ die(int e) { _exit(e); } +void _noreturn_ die_write() { cleanup(); die(53); } +void _noreturn_ die_read() { cleanup(); die(54); } +void _noreturn_ sigalrm() { /* thou shalt not clean up here */ die(52); } +void _noreturn_ sigbug() { die(81); } unsigned int receivedlen; char *received; diff --git a/qmail-remote.c b/qmail-remote.c @@ -22,6 +22,7 @@ #include "now.h" #include "exit.h" #include "constmap.h" +#include "noreturn.h" #include "tcpto.h" #include "readwrite.h" #include "timeoutconn.h" @@ -49,38 +50,38 @@ struct ip_address partner; void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } -void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); } +void _noreturn_ zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); } void outsafe(sa) stralloc *sa; { int i; char ch; for (i = 0;i < sa->len;++i) { ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } -void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } -void temp_oserr() { out("Z\ +void _noreturn_ temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } +void _noreturn_ temp_oserr() { out("Z\ System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); } -void temp_noconn() { out("Z\ +void _noreturn_ temp_noconn() { out("Z\ Sorry, I wasn't able to establish an SMTP connection. (#4.4.1)\n"); zerodie(); } -void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); } -void temp_dnscanon() { out("Z\ +void _noreturn_ temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); } +void _noreturn_ temp_dnscanon() { out("Z\ CNAME lookup failed temporarily. (#4.4.3)\n"); zerodie(); } -void temp_dns() { out("Z\ +void _noreturn_ temp_dns() { out("Z\ Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie(); } -void temp_chdir() { out("Z\ +void _noreturn_ temp_chdir() { out("Z\ Unable to switch to home directory. (#4.3.0)\n"); zerodie(); } -void temp_control() { out("Z\ +void _noreturn_ temp_control() { out("Z\ Unable to read control files. (#4.3.0)\n"); zerodie(); } -void perm_partialline() { out("D\ +void _noreturn_ perm_partialline() { out("D\ SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); } -void perm_usage() { out("D\ +void _noreturn_ perm_usage() { out("D\ I (qmail-remote) was invoked improperly. (#5.3.5)\n"); zerodie(); } -void perm_dns() { out("D\ +void _noreturn_ perm_dns() { out("D\ Sorry, I couldn't find any host named "); outsafe(&host); out(". (#5.1.2)\n"); zerodie(); } -void perm_nomx() { out("D\ +void _noreturn_ perm_nomx() { out("D\ Sorry, I couldn't find a mail exchanger or IP address. (#5.4.4)\n"); zerodie(); } -void perm_ambigmx() { out("D\ +void _noreturn_ perm_ambigmx() { out("D\ Sorry. Although I'm listed as a best-preference MX or A for that host,\n\ it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n"); zerodie(); } @@ -93,7 +94,7 @@ void outhost() int flagcritical = 0; -void dropped() { +void _noreturn_ dropped() { out("ZConnected to "); outhost(); out(" but connection died. "); diff --git a/qmail-start.c b/qmail-start.c @@ -3,6 +3,7 @@ #include "prot.h" #include "exit.h" #include "fork.h" +#include "noreturn.h" #include "uidgid.h" #include "auto_uids.h" #include "auto_users.h" @@ -12,7 +13,7 @@ char *(qcargs[]) = { "qmail-clean", 0 }; char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 }; char *(qrargs[]) = { "qmail-rspawn", 0 }; -void die() { _exit(111); } +void _noreturn_ die() { _exit(111); } int pi0[2]; int pi1[2]; diff --git a/sendmail.c b/sendmail.c @@ -5,22 +5,23 @@ #include "auto_qmail.h" #include "exit.h" #include "env.h" +#include "noreturn.h" #include "str.h" -void nomem() +void _noreturn_ nomem() { substdio_putsflush(subfderr,"sendmail: fatal: out of memory\n"); _exit(111); } -void die_usage() +void _noreturn_ die_usage() { substdio_putsflush(subfderr,"sendmail: usage: sendmail [ -t ] [ -fsender ] [ -Fname ] [ -bp ] [ -bs ] [ arg ... ]\n"); _exit(100); } char *smtpdarg[] = { "bin/qmail-smtpd", 0 }; -void smtpd() +void _noreturn_ smtpd() { if (!env_get("PROTO")) { if (!env_put("RELAYCLIENT=")) nomem(); @@ -38,7 +39,7 @@ void smtpd() } char *qreadarg[] = { "bin/qmail-qread", 0 }; -void mailq() +void _noreturn_ mailq() { execv(*qreadarg,qreadarg); substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-qread\n"); diff --git a/strerr.h b/strerr.h @@ -1,6 +1,8 @@ #ifndef STRERR_H #define STRERR_H +#include "noreturn.h" + struct strerr { struct strerr *who; @@ -15,7 +17,7 @@ extern void strerr_sysinit(); extern char *strerr(); extern void strerr_warn(); -extern void strerr_die(); +extern void _noreturn_ strerr_die(); #define STRERR(r,se,a) \ { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } diff --git a/tcp-env.c b/tcp-env.c @@ -2,6 +2,7 @@ #include <sys/socket.h> #include <sys/param.h> #include <netinet/in.h> +#include "noreturn.h" #include "sig.h" #include "stralloc.h" #include "str.h" @@ -16,7 +17,7 @@ #include "exit.h" #include "case.h" -void die() { _exit(111); } +void _noreturn_ die() { _exit(111); } struct sockaddr_in salocal; unsigned long localport;