about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorFrank Busse <bb0xfb@gmail.com>2018-10-03 14:19:59 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2018-10-10 18:58:09 +0100
commit224532d66198c80c89b6017e14de4bbed53e305e (patch)
tree25101661e0c9ef28a6479f3445c639660ca52a33
parent44892ef160e9a6cb471ecbf100d45cfc5e65f8e6 (diff)
downloadklee-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.cpp17
-rw-r--r--test/regression/2018-10-01-double-segfault.c27
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;
+}