scan-build doesn't know that internal_errorf(1, ...) doesn't return,
which leads to false positives.
The diff below introduces internal_warningf() and annotates
internal_errorf() as "noreturn", same thing as what is done for
warningf() and errorf().
ok?
Index: alloc.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/alloc.c,v
retrieving revision 1.18
diff -u -p -r1.18 alloc.c
--- alloc.c 2 Nov 2017 06:55:35 -0000 1.18
+++ alloc.c 16 Jan 2018 15:02:47 -0000
@@ -45,11 +45,11 @@ alloc(size_t size, Area *ap)
/* ensure that we don't overflow by allocating space for link */
if (size > SIZE_MAX - sizeof(struct link))
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
l = malloc(sizeof(struct link) + size);
if (l == NULL)
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
l->next = ap->freelist;
l->prev = NULL;
if (ap->freelist)
@@ -73,7 +73,7 @@ areallocarray(void *ptr, size_t nmemb, s
/* condition logic cloned from calloc() */
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
}
return aresize(ptr, nmemb * size, ap);
@@ -89,7 +89,7 @@ aresize(void *ptr, size_t size, Area *ap
/* ensure that we don't overflow by allocating space for link */
if (size > SIZE_MAX - sizeof(struct link))
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
l = P2L(ptr);
lprev = l->prev;
@@ -97,7 +97,7 @@ aresize(void *ptr, size_t size, Area *ap
l2 = realloc(l, sizeof(struct link) + size);
if (l2 == NULL)
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
if (lprev)
lprev->next = l2;
else
Index: c_ksh.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/c_ksh.c,v
retrieving revision 1.57
diff -u -p -r1.57 c_ksh.c
--- c_ksh.c 15 Jan 2018 14:58:05 -0000 1.57
+++ c_ksh.c 16 Jan 2018 15:02:47 -0000
@@ -1273,7 +1273,7 @@ c_getopts(char **wp)
}
if (genv->loc->next == NULL) {
- internal_errorf(0, "c_getopts: no argv");
+ internal_warningf("c_getopts: no argv");
return 1;
}
/* Which arguments are we parsing... */
Index: c_ulimit.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/c_ulimit.c,v
retrieving revision 1.24
diff -u -p -r1.24 c_ulimit.c
--- c_ulimit.c 14 Dec 2015 13:59:42 -0000 1.24
+++ c_ulimit.c 16 Jan 2018 15:02:47 -0000
@@ -111,7 +111,7 @@ c_ulimit(char **wp)
for (l = limits; l->name && l->option != optc; l++)
;
if (!l->name) {
- internal_errorf(0, "ulimit: %c", optc);
+ internal_warningf("ulimit: %c", optc);
return 1;
}
if (builtin_opt.optarg) {
Index: edit.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/edit.c,v
retrieving revision 1.62
diff -u -p -r1.62 edit.c
--- edit.c 15 Jan 2018 14:58:05 -0000 1.62
+++ edit.c 16 Jan 2018 15:02:47 -0000
@@ -372,7 +372,7 @@ x_file_glob(int flags, const char *str,
source = s;
if (yylex(ONEWORD|UNESCAPE) != LWORD) {
source = sold;
- internal_errorf(0, "fileglob: substitute error");
+ internal_warningf("fileglob: substitute error");
return 0;
}
source = sold;
@@ -616,12 +616,12 @@ x_try_array(const char *buf, int buflen,
/* Try to find the array. */
if (asprintf(&name, "complete_%.*s_%d", cmdlen, cmd, n) < 0)
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
v = global(name);
free(name);
if (~v->flag & (ISSET|ARRAY)) {
if (asprintf(&name, "complete_%.*s", cmdlen, cmd) < 0)
- internal_errorf(1, "unable to allocate memory");
+ internal_errorf("unable to allocate memory");
v = global(name);
free(name);
if (~v->flag & (ISSET|ARRAY))
Index: eval.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/eval.c,v
retrieving revision 1.58
diff -u -p -r1.58 eval.c
--- eval.c 14 Jan 2018 16:04:21 -0000 1.58
+++ eval.c 16 Jan 2018 15:02:47 -0000
@@ -69,7 +69,7 @@ substitute(const char *cp, int f)
s->start = s->str = cp;
source = s;
if (yylex(ONEWORD) != LWORD)
- internal_errorf(1, "substitute");
+ internal_errorf("substitute");
source = sold;
afree(s, ATEMP);
return evalstr(yylval.cp, f);
@@ -168,7 +168,7 @@ expand(char *cp, /* input word */
size_t len;
if (cp == NULL)
- internal_errorf(1, "expand(NULL)");
+ internal_errorf("expand(NULL)");
/* for alias, readonly, set, typeset commands */
if ((f & DOVACHECK) && is_wdvarassign(cp)) {
f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE);
@@ -587,7 +587,7 @@ expand(char *cp, /* input word */
char *p;
if ((p = strdup("")) == NULL)
- internal_errorf(1, "unable "
+ internal_errorf("unable "
"to allocate memory");
XPput(*wp, p);
}
Index: exec.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/exec.c,v
retrieving revision 1.71
diff -u -p -r1.71 exec.c
--- exec.c 15 Jan 2018 14:58:05 -0000 1.71
+++ exec.c 16 Jan 2018 15:02:47 -0000
@@ -644,7 +644,7 @@ comexec(struct op *t, struct tbl *volati
/* NOTREACHED */
default:
quitenv(NULL);
- internal_errorf(1, "CFUNC %d", i);
+ internal_errorf("CFUNC %d", i);
}
break;
}
@@ -727,7 +727,7 @@ shcomexec(char **wp)
tp = ktsearch(&builtins, *wp, hash(*wp));
if (tp == NULL)
- internal_errorf(1, "shcomexec: %s", *wp);
+ internal_errorf("shcomexec: %s", *wp);
return call_builtin(tp, wp);
}
@@ -1221,7 +1221,7 @@ herein(const char *content, int sub)
s->start = s->str = content;
source = s;
if (yylex(ONEWORD|HEREDOC) != LWORD)
- internal_errorf(1, "herein: yylex");
+ internal_errorf("herein: yylex");
source = osource;
shf_puts(evalstr(yylval.cp, 0), shf);
} else
@@ -1446,5 +1446,5 @@ static void
dbteste_error(Test_env *te, int offset, const char *msg)
{
te->flags |= TEF_ERROR;
- internal_errorf(0, "dbteste_error: %s (offset %d)", msg, offset);
+ internal_warningf("dbteste_error: %s (offset %d)", msg, offset);
}
Index: io.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/io.c,v
retrieving revision 1.35
diff -u -p -r1.35 io.c
--- io.c 20 Mar 2016 00:01:21 -0000 1.35
+++ io.c 16 Jan 2018 15:06:26 -0000
@@ -86,21 +86,37 @@ bi_errorf(const char *fmt, ...)
}
}
-/* Called when something that shouldn't happen does */
-void
-internal_errorf(int jump, const char *fmt, ...)
+static void
+internal_error_vwarn(const char *fmt, va_list va)
{
- va_list va;
-
error_prefix(true);
shf_fprintf(shl_out, "internal error: ");
- va_start(va, fmt);
shf_vfprintf(shl_out, fmt, va);
- va_end(va);
shf_putchar('\n', shl_out);
shf_flush(shl_out);
- if (jump)
- unwind(LERROR);
+}
+
+/* Warn when something that shouldn't happen does */
+void
+internal_warningf(const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ internal_error_vwarn(fmt, va);
+ va_end(va);
+}
+
+/* Warn and unwind when something that shouldn't happen does */
+__dead void
+internal_errorf(const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ internal_error_vwarn(fmt, va);
+ va_end(va);
+ unwind(LERROR);
}
/* used by error reporting functions to print "ksh: .kshrc[25]: " */
@@ -139,7 +155,7 @@ shprintf(const char *fmt, ...)
va_list va;
if (!shl_stdout_ok)
- internal_errorf(1, "shl_stdout not valid");
+ internal_errorf("shl_stdout not valid");
va_start(va, fmt);
shf_vfprintf(shl_stdout, fmt, va);
va_end(va);
Index: jobs.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/jobs.c,v
retrieving revision 1.58
diff -u -p -r1.58 jobs.c
--- jobs.c 8 Jan 2018 22:22:28 -0000 1.58
+++ jobs.c 16 Jan 2018 15:02:47 -0000
@@ -411,7 +411,7 @@ exchild(struct op *t, int flags, volatil
/* link process into jobs list */
if (flags&XPIPEI) { /* continuing with a pipe */
if (!last_job)
- internal_errorf(1,
+ internal_errorf(
"exchild: XPIPEI and no last_job - pid %d",
(int) procpid);
j = last_job;
@@ -522,7 +522,7 @@ exchild(struct op *t, int flags, volatil
tty_close();
cleartraps();
execute(t, (flags & XERROK) | XEXEC, NULL); /* no return */
- internal_errorf(0, "exchild: execute() returned");
+ internal_warningf("exchild: execute() returned");
unwind(LLEAVE);
/* NOTREACHED */
}
@@ -590,7 +590,7 @@ waitlast(void)
if (!j)
warningf(true, "waitlast: no last job");
else
- internal_errorf(0, "waitlast: not started");
+ internal_warningf("waitlast: not started");
sigprocmask(SIG_SETMASK, &omask, NULL);
return 125; /* not so arbitrary, non-zero value */
}
@@ -931,7 +931,7 @@ j_set_async(Job *j)
if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE)
remove_job(async_job, "async");
if (!(j->flags & JF_STARTED)) {
- internal_errorf(0, "j_async: job not started");
+ internal_warningf("j_async: job not started");
return;
}
async_job = j;
@@ -945,8 +945,8 @@ j_set_async(Job *j)
if (!oldest) {
/* XXX debugging */
if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) {
- internal_errorf(0,
- "j_async: bad nzombie (%d)", nzombie);
+ internal_warningf("j_async: bad nzombie (%d)",
+ nzombie);
nzombie = 0;
}
break;
@@ -1186,7 +1186,7 @@ check_job(Job *j)
/* XXX debugging (nasty - interrupt routine using shl_out) */
if (!(j->flags & JF_STARTED)) {
- internal_errorf(0, "check_job: job started (flags 0x%x)",
+ internal_warningf("check_job: job started (flags 0x%x)",
j->flags);
return;
}
@@ -1546,7 +1546,7 @@ remove_job(Job *j, const char *where)
for (; curr != NULL && curr != j; prev = &curr->next, curr = *prev)
;
if (curr != j) {
- internal_errorf(0, "remove_job: job not found (%s)", where);
+ internal_warningf("remove_job: job not found (%s)", where);
return;
}
*prev = curr->next;
Index: main.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/main.c,v
retrieving revision 1.88
diff -u -p -r1.88 main.c
--- main.c 15 Jan 2018 14:58:05 -0000 1.88
+++ main.c 16 Jan 2018 15:07:56 -0000
@@ -492,7 +492,7 @@ include(const char *name, int argc, char
unwind(i);
/* NOTREACHED */
default:
- internal_errorf(1, "include: %d", i);
+ internal_errorf("include: %d", i);
/* NOTREACHED */
}
}
@@ -579,7 +579,7 @@ shell(Source *volatile s, volatile int t
default:
source = old_source;
quitenv(NULL);
- internal_errorf(1, "shell: %d", i);
+ internal_errorf("shell: %d", i);
/* NOTREACHED */
}
}
Index: misc.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/misc.c,v
retrieving revision 1.67
diff -u -p -r1.67 misc.c
--- misc.c 15 Jan 2018 14:58:05 -0000 1.67
+++ misc.c 16 Jan 2018 15:02:47 -0000
@@ -407,7 +407,7 @@ parse_args(char **argv,
break;
}
if (ele == NELEM(sh_options)) {
- internal_errorf(1, "parse_args: `%c'", optc);
+ internal_errorf("parse_args: `%c'", optc);
return -1; /* not reached */
}
}
Index: sh.h
===================================================================
RCS file: /d/cvs/src/bin/ksh/sh.h,v
retrieving revision 1.70
diff -u -p -r1.70 sh.h
--- sh.h 15 Jan 2018 14:58:05 -0000 1.70
+++ sh.h 16 Jan 2018 15:04:32 -0000
@@ -464,8 +464,10 @@ void warningf(bool, const char *, ...)
__attribute__((__format__ (printf, 2, 3)));
void bi_errorf(const char *, ...)
__attribute__((__format__ (printf, 1, 2)));
-void internal_errorf(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
+void internal_errorf(const char *, ...)
+ __attribute__((__noreturn__, __format__ (printf, 1, 2)));
+void internal_warningf(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)));
void error_prefix(int);
void shellf(const char *, ...)
__attribute__((__format__ (printf, 1, 2)));
Index: shf.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/shf.c,v
retrieving revision 1.31
diff -u -p -r1.31 shf.c
--- shf.c 20 Mar 2016 00:01:21 -0000 1.31
+++ shf.c 16 Jan 2018 15:02:47 -0000
@@ -100,7 +100,7 @@ shf_fdopen(int fd, int sflags, struct sh
}
if (!(sflags & (SHF_RD | SHF_WR)))
- internal_errorf(1, "shf_fdopen: missing read/write");
+ internal_errorf("shf_fdopen: missing read/write");
if (shf) {
if (bsize) {
@@ -157,9 +157,9 @@ shf_reopen(int fd, int sflags, struct sh
}
if (!(sflags & (SHF_RD | SHF_WR)))
- internal_errorf(1, "shf_reopen: missing read/write");
+ internal_errorf("shf_reopen: missing read/write");
if (!shf || !shf->buf || shf->bsize < bsize)
- internal_errorf(1, "shf_reopen: bad shf/buf/bsize");
+ internal_errorf("shf_reopen: bad shf/buf/bsize");
/* assumes shf->buf and shf->bsize already set up */
shf->fd = fd;
@@ -189,7 +189,7 @@ shf_sopen(char *buf, int bsize, int sfla
/* can't have a read+write string */
if (!(sflags & (SHF_RD | SHF_WR)) ||
(sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR))
- internal_errorf(1, "shf_sopen: flags 0x%x", sflags);
+ internal_errorf("shf_sopen: flags 0x%x", sflags);
if (!shf) {
shf = alloc(sizeof(struct shf), ATEMP);
@@ -282,7 +282,7 @@ shf_flush(struct shf *shf)
return (shf->flags & SHF_WR) ? EOF : 0;
if (shf->fd < 0)
- internal_errorf(1, "shf_flush: no fd");
+ internal_errorf("shf_flush: no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errno_;
@@ -312,7 +312,7 @@ shf_emptybuf(struct shf *shf, int flags)
int ret = 0;
if (!(shf->flags & SHF_STRING) && shf->fd < 0)
- internal_errorf(1, "shf_emptybuf: no fd");
+ internal_errorf("shf_emptybuf: no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errno_;
@@ -392,7 +392,7 @@ shf_fillbuf(struct shf *shf)
return 0;
if (shf->fd < 0)
- internal_errorf(1, "shf_fillbuf: no fd");
+ internal_errorf("shf_fillbuf: no fd");
if (shf->flags & (SHF_EOF | SHF_ERROR)) {
if (shf->flags & SHF_ERROR)
@@ -438,10 +438,10 @@ shf_read(char *buf, int bsize, struct sh
int ncopy;
if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_read: flags %x", shf->flags);
+ internal_errorf("shf_read: flags %x", shf->flags);
if (bsize <= 0)
- internal_errorf(1, "shf_read: bsize %d", bsize);
+ internal_errorf("shf_read: bsize %d", bsize);
while (bsize > 0) {
if (shf->rnleft == 0 &&
@@ -473,7 +473,7 @@ shf_getse(char *buf, int bsize, struct s
char *orig_buf = buf;
if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_getse: flags %x", shf->flags);
+ internal_errorf("shf_getse: flags %x", shf->flags);
if (bsize <= 0)
return NULL;
@@ -508,7 +508,7 @@ int
shf_getchar(struct shf *shf)
{
if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_getchar: flags %x", shf->flags);
+ internal_errorf("shf_getchar: flags %x", shf->flags);
if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0))
return EOF;
@@ -523,7 +523,7 @@ int
shf_ungetc(int c, struct shf *shf)
{
if (!(shf->flags & SHF_RD))
- internal_errorf(1, "shf_ungetc: flags %x", shf->flags);
+ internal_errorf("shf_ungetc: flags %x", shf->flags);
if ((shf->flags & SHF_ERROR) || c == EOF ||
(shf->rp == shf->buf && shf->rnleft))
@@ -558,7 +558,7 @@ int
shf_putchar(int c, struct shf *shf)
{
if (!(shf->flags & SHF_WR))
- internal_errorf(1, "shf_putchar: flags %x", shf->flags);
+ internal_errorf("shf_putchar: flags %x", shf->flags);
if (c == EOF)
return EOF;
@@ -568,7 +568,7 @@ shf_putchar(int c, struct shf *shf)
int n;
if (shf->fd < 0)
- internal_errorf(1, "shf_putchar: no fd");
+ internal_errorf("shf_putchar: no fd");
if (shf->flags & SHF_ERROR) {
errno = shf->errno_;
return EOF;
@@ -614,10 +614,10 @@ shf_write(const char *buf, int nbytes, s
int ncopy;
if (!(shf->flags & SHF_WR))
- internal_errorf(1, "shf_write: flags %x", shf->flags);
+ internal_errorf("shf_write: flags %x", shf->flags);
if (nbytes < 0)
- internal_errorf(1, "shf_write: nbytes %d", nbytes);
+ internal_errorf("shf_write: nbytes %d", nbytes);
/* Don't buffer if buffer is empty and we're writting a large amount. */
if ((ncopy = shf->wnleft) &&
@@ -687,7 +687,7 @@ shf_snprintf(char *buf, int bsize, const
int n;
if (!buf || bsize <= 0)
- internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",
+ internal_errorf("shf_snprintf: buf %lx, bsize %d",
(long) buf, bsize);
shf_sopen(buf, bsize, SHF_WR, &shf);
Index: table.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/table.c,v
retrieving revision 1.24
diff -u -p -r1.24 table.c
--- table.c 27 Dec 2017 13:02:57 -0000 1.24
+++ table.c 16 Jan 2018 15:02:47 -0000
@@ -128,7 +128,7 @@ ktenter(struct table *tp, const char *n,
if (tp->size <= INT_MAX/2)
texpand(tp, 2*tp->size);
else
- internal_errorf(1, "too many vars");
+ internal_errorf("too many vars");
goto Search;
}
Index: trap.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/trap.c,v
retrieving revision 1.30
diff -u -p -r1.30 trap.c
--- trap.c 17 Mar 2016 23:33:23 -0000 1.30
+++ trap.c 16 Jan 2018 15:02:47 -0000
@@ -402,7 +402,7 @@ setexecsig(Trap *p, int restore)
{
/* XXX debugging */
if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL)))
- internal_errorf(1, "setexecsig: unset signal %d(%s)",
+ internal_errorf("setexecsig: unset signal %d(%s)",
p->signal, p->name);
/* restore original value for exec'd kids */
Index: tree.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/tree.c,v
retrieving revision 1.30
diff -u -p -r1.30 tree.c
--- tree.c 6 Jan 2018 16:28:58 -0000 1.30
+++ tree.c 16 Jan 2018 15:02:47 -0000
@@ -549,7 +549,7 @@ wdscan(const char *wp, int c)
nest--;
break;
default:
- internal_errorf(0,
+ internal_warningf(
"wdscan: unknown char 0x%x (carrying on)",
wp[-1]);
}
Index: var.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/var.c,v
retrieving revision 1.64
diff -u -p -r1.64 var.c
--- var.c 15 Jan 2018 14:58:05 -0000 1.64
+++ var.c 16 Jan 2018 15:02:47 -0000
@@ -366,7 +366,7 @@ setstr(struct tbl *vq, const char *s, in
/* debugging */
if (s >= vq->val.s &&
s <= vq->val.s + strlen(vq->val.s))
- internal_errorf(true,
+ internal_errorf(
"setstr: %s=%s: assigning to self",
vq->name, s);
afree(vq->val.s, vq->areap);
Index: vi.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/vi.c,v
retrieving revision 1.54
diff -u -p -r1.54 vi.c
--- vi.c 13 Jan 2018 02:06:54 -0000 1.54
+++ vi.c 16 Jan 2018 15:02:47 -0000
@@ -1669,7 +1669,7 @@ grabhist(int save, int n)
}
(void) histnum(n);
if ((hptr = *histpos()) == NULL) {
- internal_errorf(0, "grabhist: bad history array");
+ internal_warningf("grabhist: bad history array");
return -1;
}
if (save)
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE