about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Core/AddressSpace.cpp34
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/Core/AddressSpace.cpp b/lib/Core/AddressSpace.cpp
index ab3bbb8c..bb77f0fc 100644
--- a/lib/Core/AddressSpace.cpp
+++ b/lib/Core/AddressSpace.cpp
@@ -336,13 +336,33 @@ bool AddressSpace::copyInConcretes() {
 bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os,
                                   uint64_t src_address) {
   auto address = reinterpret_cast<std::uint8_t*>(src_address);
-  if (memcmp(address, os->concreteStore, mo->size) != 0) {
-    if (os->readOnly) {
-      return false;
-    } else {
-      ObjectState *wos = getWriteable(mo, os);
-      memcpy(wos->concreteStore, address, mo->size);
-    }
+
+  // Don't do anything if the underlying representation has not been changed
+  // externally.
+  if (std::memcmp(address, os->concreteStore, mo->size) == 0)
+    return true;
+
+  // External object representation has been changed
+
+  // Return `false` if the object is marked as read-only
+  if (os->readOnly)
+    return false;
+
+  ObjectState *wos = getWriteable(mo, os);
+  // Check if the object is fully concrete object. If so, use the fast
+  // path and `memcpy` the new values from the external object to the internal
+  // representation
+  if (!wos->unflushedMask) {
+    std::memcpy(wos->concreteStore, address, mo->size);
+    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);
   }
   return true;
 }