about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
authorMartin Nowack <m.nowack@imperial.ac.uk>2024-02-27 16:20:11 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2024-02-29 19:57:08 +0000
commit76a2adef91dc987083e8e30f40c4143742e4e726 (patch)
tree08ec0577557ca4785a6bd9dab6ebcfd43696e490
parent2cae55383a11fbcb3fcc1a8bac67949e2245d451 (diff)
downloadklee-76a2adef91dc987083e8e30f40c4143742e4e726.tar.gz
Add support to fully concretise objects if modified externally
Propagate ExternalCallPolicy to allow user-based selection.
-rw-r--r--lib/Core/AddressSpace.cpp24
-rw-r--r--lib/Core/AddressSpace.h12
-rw-r--r--lib/Core/Executor.cpp6
3 files changed, 27 insertions, 15 deletions
diff --git a/lib/Core/AddressSpace.cpp b/lib/Core/AddressSpace.cpp
index bb77f0fc..138119b1 100644
--- a/lib/Core/AddressSpace.cpp
+++ b/lib/Core/AddressSpace.cpp
@@ -318,14 +318,14 @@ void AddressSpace::copyOutConcrete(const MemoryObject *mo,
   std::memcpy(address, os->concreteStore, mo->size);
 }
 
-bool AddressSpace::copyInConcretes() {
+bool AddressSpace::copyInConcretes(bool concretize) {
   for (auto &obj : objects) {
     const MemoryObject *mo = obj.first;
 
     if (!mo->isUserSpecified) {
       const auto &os = obj.second;
 
-      if (!copyInConcrete(mo, os.get(), mo->address))
+      if (!copyInConcrete(mo, os.get(), mo->address, concretize))
         return false;
     }
   }
@@ -334,7 +334,7 @@ bool AddressSpace::copyInConcretes() {
 }
 
 bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os,
-                                  uint64_t src_address) {
+                                  uint64_t src_address, bool concretize) {
   auto address = reinterpret_cast<std::uint8_t*>(src_address);
 
   // Don't do anything if the underlying representation has not been changed
@@ -357,12 +357,18 @@ bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os,
     return true;
   }
 
-  // The object is partially symbolic, it needs to be updated byte-by-byte
-  // via object state's `write` function
-  for (size_t i = 0, ie = mo->size; i < ie; ++i) {
-    u_int8_t external_byte_value = *(address + i);
-    if (external_byte_value != wos->concreteStore[i])
-      wos->write8(i, external_byte_value);
+  // Check if object should be concretized
+  if (concretize) {
+    wos->makeConcrete();
+    std::memcpy(wos->concreteStore, address, mo->size);
+  } else {
+    // The object is partially symbolic, it needs to be updated byte-by-byte
+    // via object state's `write` function
+    for (size_t i = 0, ie = mo->size; i < ie; ++i) {
+      u_int8_t external_byte_value = *(address + i);
+      if (external_byte_value != wos->concreteStore[i])
+        wos->write8(i, external_byte_value);
+    }
   }
   return true;
 }
diff --git a/lib/Core/AddressSpace.h b/lib/Core/AddressSpace.h
index 37ae76f9..fa4fb940 100644
--- a/lib/Core/AddressSpace.h
+++ b/lib/Core/AddressSpace.h
@@ -138,18 +138,22 @@ namespace klee {
     /// potentially copied) if the memory values are different from
     /// the current concrete values.
     ///
-    /// \retval true The copy succeeded. 
-    /// \retval false The copy failed because a read-only object was modified.
-    bool copyInConcretes();
+    /// \param concretize fully concretize the object representation if changed
+    /// externally
+    /// \return true if copy succeeded, otherwise false (e.g. try to modify
+    /// read-only object)
+    bool copyInConcretes(bool concretize);
 
     /// Updates the memory object with the raw memory from the address
     ///
     /// @param mo The MemoryObject to update
     /// @param os The associated memory state containing the actual data
     /// @param src_address the address to copy from
+    /// @param concretize fully concretize the object representation if changed
+    /// externally
     /// @return
     bool copyInConcrete(const MemoryObject *mo, const ObjectState *os,
-                        uint64_t src_address);
+                        uint64_t src_address, bool concretize);
   };
 } // End klee namespace
 
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index 1af88d88..bc27c5f3 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -4126,7 +4126,8 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target,
     return;
   }
 
-  if (!state.addressSpace.copyInConcretes()) {
+  if (!state.addressSpace.copyInConcretes(ExternalCalls ==
+                                          ExternalCallPolicy::All)) {
     terminateStateOnExecError(state, "external modified read-only object",
                               StateTerminationType::External);
     return;
@@ -4143,7 +4144,8 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target,
   // Update errno memory object with the errno value from the call
   int error = externalDispatcher->getLastErrno();
   state.addressSpace.copyInConcrete(result.first, result.second,
-                                    (uint64_t)&error);
+                                    (uint64_t)&error,
+                                    ExternalCalls == ExternalCallPolicy::All);
 #endif
 
   Type *resultType = target->inst->getType();