implement our own assert() function

I recently upgraded the software on my macOS server and was dismayed to
see that cppcheck reported a huge number of format string errors due to
mismatches between the format string and its arguments from calls to
`assert()`. It turns out they are due to the macOS header using `%lu`
for the line number which is obviously wrong since it is using the C
preprocessor `__LINE__` symbol which evaluates to a signed int.

I also noticed that the macOS implementation writes to stdout, rather
than stderr. It also uses `printf()` which can be a problem on some
platforms if the stream is already in wide mode which is the normal case
for fish.

So implement our own `assert()` implementation. This also eliminates
double-negative warnings that we get from some of our calls to
`assert()` on some platforms by oclint.

Also reimplement the `DIE()` macro in terms of our internal
implementation.

Rewrite `assert(0 && msg)` statements to `DIE(msg)` for clarity and to
eliminate oclint warnings about constant expressions.

Fixes #3276, albeit not in the fashion I originally envisioned.
This commit is contained in:
Kurtis Rader
2017-02-13 20:37:27 -08:00
parent 7fc1994339
commit 509ee64fc9
69 changed files with 119 additions and 117 deletions

View File

@@ -1,7 +1,6 @@
// Various functions, mostly string utilities, that are used by most parts of fish.
#include "config.h"
#include <assert.h>
#include <cxxabi.h>
#include <dlfcn.h>
#include <errno.h>
@@ -28,6 +27,7 @@
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <algorithm>
#include <memory> // IWYU pragma: keep
#include <type_traits>
@@ -266,14 +266,14 @@ char *wcs2str(const wchar_t *in) {
if (result) {
// It converted into the local buffer, so copy it.
result = strdup(result);
if (!result) DIE_MEM();
assert(result);
}
return result;
}
// Here we probably allocate a buffer probably much larger than necessary.
char *out = (char *)malloc(MAX_UTF8_BYTES * wcslen(in) + 1);
if (!out) DIE_MEM();
assert(out);
return wcs2str_internal(in, out);
}
@@ -400,9 +400,7 @@ void append_formatv(wcstring &target, const wchar_t *format, va_list va_orig) {
break;
}
buff = (wchar_t *)realloc((buff == static_buff ? NULL : buff), size);
if (buff == NULL) {
DIE_MEM();
}
assert(buff != NULL);
}
// Try printing.
@@ -2031,3 +2029,10 @@ void redirect_tty_output() {
if (tcgetattr(STDERR_FILENO, &t) == -1 && errno == EIO) dup2(fd, STDERR_FILENO);
close(fd);
}
/// Display a failed assertion message, dump a stack trace if possible, then die.
[[noreturn]] void __assert(const char *msg, const char *file, size_t line) {
debug(0, L"%s:%zu: failed assertion: %s", file, line, msg);
show_stackframe(L'E', 99, 1);
abort();
}