Many printf-like variadic functions weren't properly decorated with
FORMAT annotations. Add them everywhere.
It is not possible to annotate a function pointer type, so that
doesn't work for the function pointers in struct log_if. However, we
have convenience wrapper functions slilog and vslilog, which are
appropriately decorated and therefore safer. Change all call sites to
use those instead, and leave a comment. (Rename the function pointer
variable names so that we don't miss any call sites.)
Fix the bugs that this new compiler checking reveals. These are
nearly all in fatal error reporting, and not very scary.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
uint32_t message_level=M_WARNING|M_ERR|M_SECURITY|M_FATAL;
struct log_if *system_log=NULL;
uint32_t message_level=M_WARNING|M_ERR|M_SECURITY|M_FATAL;
struct log_if *system_log=NULL;
+static void vMessageFallback(uint32_t class, const char *message, va_list args)
+ FORMAT(printf,2,0);
static void vMessageFallback(uint32_t class, const char *message, va_list args)
{
FILE *dest=stdout;
static void vMessageFallback(uint32_t class, const char *message, va_list args)
{
FILE *dest=stdout;
+static void MessageFallback(uint32_t class, const char *message, ...)
+ FORMAT(printf,2,3);
static void MessageFallback(uint32_t class, const char *message, ...)
{
va_list ap;
static void MessageFallback(uint32_t class, const char *message, ...)
{
va_list ap;
if (secnet_is_daemon) {
for (i=st; i; i=i->next) {
if (secnet_is_daemon) {
for (i=st; i; i=i->next) {
- i->l->vlog(i->l->st,class,message,args);
+ vslilog(i->l,class,message,args);
}
} else {
vMessage(class,message,args);
}
} else {
vMessage(class,message,args);
+static void log_multi(void *st, int priority, const char *message, ...)
+ FORMAT(printf,3,4);
static void log_multi(void *st, int priority, const char *message, ...)
{
va_list ap;
static void log_multi(void *st, int priority, const char *message, ...)
{
va_list ap;
}
r=safe_malloc(sizeof(*r), "init_log");
r->st=l;
}
r=safe_malloc(sizeof(*r), "init_log");
r->st=l;
- r->log=log_multi;
- r->vlog=log_vmulti;
+ r->logfn=log_multi;
+ r->vlogfn=log_vmulti;
+static void logfile_log(void *state, int class, const char *message, ...)
+ FORMAT(printf,3,4);
static void logfile_log(void *state, int class, const char *message, ...)
{
va_list ap;
static void logfile_log(void *state, int class, const char *message, ...)
{
va_list ap;
st->cl.apply=NULL;
st->cl.interface=&st->ops;
st->ops.st=st;
st->cl.apply=NULL;
st->cl.interface=&st->ops;
st->ops.st=st;
- st->ops.log=logfile_log;
- st->ops.vlog=logfile_vlog;
+ st->ops.logfn=logfile_log;
+ st->ops.vlogfn=logfile_vlog;
+static void syslog_vlog(void *sst, int class, const char *message,
+ va_list args)
+ FORMAT(printf,3,0);
static void syslog_vlog(void *sst, int class, const char *message,
va_list args)
{
static void syslog_vlog(void *sst, int class, const char *message,
va_list args)
{
+static void syslog_log(void *sst, int priority, const char *message, ...)
+ FORMAT(printf,3,4);
static void syslog_log(void *sst, int priority, const char *message, ...)
{
va_list ap;
static void syslog_log(void *sst, int priority, const char *message, ...)
{
va_list ap;
st->cl.apply=NULL;
st->cl.interface=&st->ops;
st->ops.st=st;
st->cl.apply=NULL;
st->cl.interface=&st->ops;
st->ops.st=st;
- st->ops.log=syslog_log;
- st->ops.vlog=syslog_vlog;
+ st->ops.logfn=syslog_log;
+ st->ops.vlogfn=syslog_vlog;
item=list_elem(args,0);
if (!item || item->type!=t_dict)
item=list_elem(args,0);
if (!item || item->type!=t_dict)
remain=FDLOG_BUFSIZE-st->i-1;
if (remain<=0) {
st->buffer[FDLOG_BUFSIZE-1]=0;
remain=FDLOG_BUFSIZE-st->i-1;
if (remain<=0) {
st->buffer[FDLOG_BUFSIZE-1]=0;
- st->log->log(st->log,M_WARNING,"%s: overlong line: %s",
+ slilog(st->log,M_WARNING,"%s: overlong line: %s",
st->prefix,st->buffer);
st->i=0;
remain=FDLOG_BUFSIZE-1;
st->prefix,st->buffer);
st->i=0;
remain=FDLOG_BUFSIZE-1;
for (i=0; i<st->i; i++) {
if (st->buffer[i]=='\n') {
st->buffer[i]=0;
for (i=0; i<st->i; i++) {
if (st->buffer[i]=='\n') {
st->buffer[i]=0;
- st->log->log(st->log->st,M_INFO,"%s: %s",
+ slilog(st->log,M_INFO,"%s: %s",
st->prefix,st->buffer);
i++;
memmove(st->buffer,st->buffer+i,st->i-i);
st->prefix,st->buffer);
i++;
memmove(st->buffer,st->buffer+i,st->i-i);
fatal("run: beforepoll_fn (%s) returns %d",i->desc,rv);
}
if (timeout<-1) {
fatal("run: beforepoll_fn (%s) returns %d",i->desc,rv);
}
if (timeout<-1) {
- fatal("run: beforepoll_fn (%s) set timeout to %d",timeout);
+ fatal("run: beforepoll_fn (%s) set timeout to %d",
+ i->desc,timeout);
}
idx+=nfds;
remain-=nfds;
}
idx+=nfds;
remain-=nfds;
va_list args);
struct log_if {
void *st;
va_list args);
struct log_if {
void *st;
- log_msg_fn *log;
- log_vmsg_fn *vlog;
+ log_msg_fn *logfn; /* Do not call these directly - you don't get */
+ log_vmsg_fn *vlogfn; /* printf format checking. Use [v]slilog instead */
};
/* (convenience functions, defined in util.c) */
extern void slilog(struct log_if *lf, int class, const char *message, ...)
};
/* (convenience functions, defined in util.c) */
extern void slilog(struct log_if *lf, int class, const char *message, ...)
#define M_FATAL 0x100
/* The fatal() family of functions require messages that do not end in '\n' */
#define M_FATAL 0x100
/* The fatal() family of functions require messages that do not end in '\n' */
-extern NORETURN(fatal(const char *message, ...));
-extern NORETURN(fatal_perror(const char *message, ...));
-extern NORETURN(fatal_status(int status, const char *message, ...));
-extern NORETURN(fatal_perror_status(int status, const char *message, ...));
+extern NORETURN(fatal(const char *message, ...)) FORMAT(printf,1,2);
+extern NORETURN(fatal_perror(const char *message, ...)) FORMAT(printf,1,2);
+extern NORETURN(fatal_status(int status, const char *message, ...))
+ FORMAT(printf,2,3);
+extern NORETURN(fatal_perror_status(int status, const char *message, ...))
+ FORMAT(printf,2,3);
/* The cfgfatal() family of functions require messages that end in '\n' */
extern NORETURN(cfgfatal(struct cloc loc, cstring_t facility,
/* The cfgfatal() family of functions require messages that end in '\n' */
extern NORETURN(cfgfatal(struct cloc loc, cstring_t facility,
- const char *message, ...));
+ const char *message, ...)) FORMAT(printf,3,4);
extern void cfgfile_postreadcheck(struct cloc loc, FILE *f);
extern NORETURN(vcfgfatal_maybefile(FILE *maybe_f, struct cloc loc,
cstring_t facility, const char *message,
extern void cfgfile_postreadcheck(struct cloc loc, FILE *f);
extern NORETURN(vcfgfatal_maybefile(FILE *maybe_f, struct cloc loc,
cstring_t facility, const char *message,
+ va_list))
+ FORMAT(printf,4,0);
extern NORETURN(cfgfatal_maybefile(FILE *maybe_f, struct cloc loc,
cstring_t facility,
extern NORETURN(cfgfatal_maybefile(FILE *maybe_f, struct cloc loc,
cstring_t facility,
- const char *message, ...));
+ const char *message, ...))
+ FORMAT(printf,4,5);
extern void Message(uint32_t class, const char *message, ...)
FORMAT(printf,2,3);
extern void Message(uint32_t class, const char *message, ...)
FORMAT(printf,2,3);
struct transform_inst_if *new_transform; /* For key setup/verify */
};
struct transform_inst_if *new_transform; /* For key setup/verify */
};
+static void slog(struct site *st, uint32_t event, cstring_t msg, ...)
+FORMAT(printf,3,4);
static void slog(struct site *st, uint32_t event, cstring_t msg, ...)
{
va_list ap;
static void slog(struct site *st, uint32_t event, cstring_t msg, ...)
{
va_list ap;
}
vsnprintf(buf,sizeof(buf),msg,ap);
}
vsnprintf(buf,sizeof(buf),msg,ap);
- st->log->log(st->log->st,class,"%s: %s",st->tunname,buf);
+ slilog(st->log,class,"%s: %s",st->tunname,buf);
slog(st,LOG_SETUP_INIT,
(!configured_addr ? "using only %d old peer address(es)"
: "using configured address, and/or perhaps %d old peer address(es)"),
slog(st,LOG_SETUP_INIT,
(!configured_addr ? "using only %d old peer address(es)"
: "using configured address, and/or perhaps %d old peer address(es)"),
/* Non-mobile peers havve st->peers.npeers==0 or ==1, since they
* have transport_peers_max==1. The effect is that this code
/* Non-mobile peers havve st->peers.npeers==0 or ==1, since they
* have transport_peers_max==1. The effect is that this code
fatal("%s: userv exited unexpectedly: uncaught signal %d",
st->slip.nl.name,WTERMSIG(status));
} else {
fatal("%s: userv exited unexpectedly: uncaught signal %d",
st->slip.nl.name,WTERMSIG(status));
} else {
- fatal("%s: userv stopped unexpectedly");
+ fatal("%s: userv stopped unexpectedly",
+ st->slip.nl.name);
}
}
Message(M_WARNING,"%s: userv subprocess died with status %d\n",
}
}
Message(M_WARNING,"%s: userv subprocess died with status %d\n",
char *d;
d=strdup(s);
if (!d) {
char *d;
d=strdup(s);
if (!d) {
+ fatal_perror("%s",message);
void *r;
r=malloc(size);
if (!r) {
void *r;
r=malloc(size);
if (!r) {
+ fatal_perror("%s",message);
void vslilog(struct log_if *lf, int priority, const char *message, va_list ap)
{
void vslilog(struct log_if *lf, int priority, const char *message, va_list ap)
{
- lf->vlog(lf->st,priority,message,ap);
+ lf->vlogfn(lf->st,priority,message,ap);
}
void slilog(struct log_if *lf, int priority, const char *message, ...)
}
void slilog(struct log_if *lf, int priority, const char *message, ...)