about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-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;
+}