about summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--lib/Core/Memory.cpp5
-rw-r--r--test/regression/2015-06-22-struct-write.c21
2 files changed, 25 insertions, 1 deletions
diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp
index 50e9aa9f..47bc7576 100644
--- a/lib/Core/Memory.cpp
+++ b/lib/Core/Memory.cpp
@@ -529,7 +529,10 @@ void ObjectState::write(unsigned offset, ref<Expr> value) {
   // Check for writes of constant values.
   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(value)) {
     Expr::Width w = CE->getWidth();
-    if (w <= 64) {
+    //assuming width can't be 0 so I can miss half of power of two check
+    assert(w > 0);
+    //also checks that w is a power of two
+    if (w <= 64 && !(w & (w - 1))) {
       uint64_t val = CE->getZExtValue();
       switch (w) {
       default: assert(0 && "Invalid write size!");
diff --git a/test/regression/2015-06-22-struct-write.c b/test/regression/2015-06-22-struct-write.c
new file mode 100644
index 00000000..6efc4ee6
--- /dev/null
+++ b/test/regression/2015-06-22-struct-write.c
@@ -0,0 +1,21 @@
+// RUN: %llvmgcc %s -emit-llvm -g -O0 -c -o %t.bc
+// RUN: rm -rf %t.klee-out
+// RUN: %klee --output-dir=%t.klee-out -exit-on-error %t.bc
+
+#include <assert.h>
+#include <klee/klee.h>
+
+union U0 {
+	signed f3 :18;
+};
+
+static union U0 u = { 0UL };
+
+int main(int argc, char **argv) {
+  u.f3 = 534;
+
+  klee_assert(u.f3 == 534);
+
+  return 0;
+}
+