diff options
author | Frank Busse <bb0xfb@gmail.com> | 2018-10-03 14:19:59 +0100 |
---|---|---|
committer | Cristian Cadar <c.cadar@imperial.ac.uk> | 2018-10-10 18:58:09 +0100 |
commit | 224532d66198c80c89b6017e14de4bbed53e305e (patch) | |
tree | 25101661e0c9ef28a6479f3445c639660ca52a33 | |
parent | 44892ef160e9a6cb471ecbf100d45cfc5e65f8e6 (diff) | |
download | klee-224532d66198c80c89b6017e14de4bbed53e305e.tar.gz |
fix handling of failing external calls
Currently KLEE only handles the first segfault in external calls as it doesn't unblock SIGSEGV afterwards. This patch unblocks the signal and enables handling of multiple failing calls.
-rw-r--r-- | lib/Core/ExternalDispatcher.cpp | 17 | ||||
-rw-r--r-- | test/regression/2018-10-01-double-segfault.c | 27 |
2 files changed, 36 insertions, 8 deletions
diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp index c8ebf38a..60bdf711 100644 --- a/lib/Core/ExternalDispatcher.cpp +++ b/lib/Core/ExternalDispatcher.cpp @@ -34,20 +34,20 @@ #include "llvm/IR/CallSite.h" #endif -#include <setjmp.h> -#include <signal.h> +#include <csetjmp> +#include <csignal> using namespace llvm; using namespace klee; /***/ -static jmp_buf escapeCallJmpBuf; +static sigjmp_buf escapeCallJmpBuf; extern "C" { static void sigsegv_handler(int signal, siginfo_t *info, void *context) { - longjmp(escapeCallJmpBuf, 1); + siglongjmp(escapeCallJmpBuf, 1); } } @@ -249,13 +249,14 @@ bool ExternalDispatcherImpl::runProtectedCall(Function *f, uint64_t *args) { std::vector<GenericValue> gvArgs; gTheArgsP = args; - segvAction.sa_handler = 0; - memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask)); + segvAction.sa_handler = nullptr; + sigemptyset(&(segvAction.sa_mask)); + sigaddset(&(segvAction.sa_mask), SIGSEGV); segvAction.sa_flags = SA_SIGINFO; segvAction.sa_sigaction = ::sigsegv_handler; sigaction(SIGSEGV, &segvAction, &segvActionOld); - if (setjmp(escapeCallJmpBuf)) { + if (sigsetjmp(escapeCallJmpBuf, 1)) { res = false; } else { errno = lastErrno; @@ -265,7 +266,7 @@ bool ExternalDispatcherImpl::runProtectedCall(Function *f, uint64_t *args) { res = true; } - sigaction(SIGSEGV, &segvActionOld, 0); + sigaction(SIGSEGV, &segvActionOld, nullptr); return res; } diff --git a/test/regression/2018-10-01-double-segfault.c b/test/regression/2018-10-01-double-segfault.c new file mode 100644 index 00000000..0fa10e8b --- /dev/null +++ b/test/regression/2018-10-01-double-segfault.c @@ -0,0 +1,27 @@ +// REQUIRES: not-asan +// RUN: %llvmgcc %s -emit-llvm -O0 -g -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +// CHECK: failed external call: strdup +// CHECK: failed external call: strdup + +// objective: check handling of more than one failing external call + + +#include "klee/klee.h" + +#include <stdbool.h> +#include <string.h> + +int main(int argc, char * argv[]) { + bool b; + klee_make_symbolic(&b, sizeof(bool), "b"); + + char * s0; + if (b) { + s0 = strdup((char *) 0xdeadbeef); + } else { + s0 = strdup((void *) 0xdeafbee5); + } + (void) s0; +} |