From ed2a9fa62cf8c47e891f2b8a80e216a70e0006dc Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 26 Apr 2022 13:33:14 +0100 Subject: [PATCH 1/4] bv_utilst::sign_extension, zero_extension and zeros can be static These methods do not use any state of bv_utilst and can therefore be static. --- src/solvers/flattening/bv_utils.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/solvers/flattening/bv_utils.h b/src/solvers/flattening/bv_utils.h index 35a64eec59b..1b988cda0c6 100644 --- a/src/solvers/flattening/bv_utils.h +++ b/src/solvers/flattening/bv_utils.h @@ -179,17 +179,17 @@ class bv_utilst static bvt extension(const bvt &bv, std::size_t new_size, representationt rep); - bvt sign_extension(const bvt &bv, std::size_t new_size) + static bvt sign_extension(const bvt &bv, std::size_t new_size) { return extension(bv, new_size, representationt::SIGNED); } - bvt zero_extension(const bvt &bv, std::size_t new_size) + static bvt zero_extension(const bvt &bv, std::size_t new_size) { return extension(bv, new_size, representationt::UNSIGNED); } - bvt zeros(std::size_t new_size) const + static bvt zeros(std::size_t new_size) { bvt result; result.resize(new_size, const_literal(false)); From 1ba814803a2c5fa8b18e5ea31c9a43b3df0017e5 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Tue, 26 Apr 2022 21:26:46 +0100 Subject: [PATCH 2/4] new pointer encoding This changes the encoding of pointers in the flattening solver as follows: * Pointers with constant zero offset are encoded by numbering the object (0 is the NULL object). * Pointers that might have an offset are numbered, and encoded/decoded as needed. The numbering points into a table, which records an n-bit object and n-bit offset for an n-bit pointer. The key benefit of the encoding above are that a) offset arithmetic no longer overflows before the given width of the pointer is reached, b) the full width of the pointer (usually 32 or 64 bits) can be used to encode the object number, thereby eliminating the requirement to configure the number of 'object bits'. --- src/solvers/flattening/bv_pointers.cpp | 251 ++++++++++++++++--------- src/solvers/flattening/bv_pointers.h | 17 +- 2 files changed, 177 insertions(+), 91 deletions(-) diff --git a/src/solvers/flattening/bv_pointers.cpp b/src/solvers/flattening/bv_pointers.cpp index 86f0361cb89..0e4f3e024af 100644 --- a/src/solvers/flattening/bv_pointers.cpp +++ b/src/solvers/flattening/bv_pointers.cpp @@ -11,7 +11,6 @@ Author: Daniel Kroening, kroening@kroening.com #include #include #include -#include #include #include #include @@ -71,53 +70,93 @@ bv_pointerst::endianness_map(const typet &type, bool little_endian) const return bv_endianness_mapt{type, little_endian, ns, bv_width}; } -std::size_t bv_pointerst::get_object_width(const pointer_typet &) const -{ - // not actually type-dependent for now - return config.bv_encoding.object_bits; -} - -std::size_t bv_pointerst::get_offset_width(const pointer_typet &type) const +bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type) { - const std::size_t pointer_width = type.get_width(); - const std::size_t object_width = get_object_width(type); - PRECONDITION(pointer_width >= object_width); - return pointer_width - object_width; -} + const auto width = type.get_width(); + PRECONDITION(width == bv.size()); -std::size_t bv_pointerst::get_address_width(const pointer_typet &type) const -{ - return type.get_width(); -} + const auto result = prop.new_variables(width); + bvt match_found; -bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type) - const -{ - const std::size_t offset_width = get_offset_width(type); - const std::size_t object_width = get_object_width(type); - PRECONDITION(bv.size() >= offset_width + object_width); + for(std::size_t i = 0; i < numbered_pointers.size(); i++) + { + auto cond = bv_utils.equal( + bv, + bv_utilst::concatenate( + bv_utilst::build_constant(i, width - 1), {const_literal(true)})); + match_found.push_back(cond); + bv_utils.cond_implies_equal( + cond, + bv_utilst::zero_extension(numbered_pointers[i].first, width), + result); + } - return bvt( - bv.begin() + offset_width, bv.begin() + offset_width + object_width); + auto within_bounds = prop.lor(match_found); + + // The top bit distinguishes 'object only' vs. 'table encoded'. + // When outside of the table, return an invalid object. + return bv_utils.select( + bv.back(), + bv_utils.select( + within_bounds, + result, + bv_utilst::build_constant(pointer_logic.get_invalid_object(), width)), + bv); } bvt bv_pointerst::offset_literals(const bvt &bv, const pointer_typet &type) - const { - const std::size_t offset_width = get_offset_width(type); - PRECONDITION(bv.size() >= offset_width); + const auto width = type.get_width(); + PRECONDITION(width == bv.size()); + + const auto result = prop.new_variables(width); - return bvt(bv.begin(), bv.begin() + offset_width); + for(std::size_t i = 0; i < numbered_pointers.size(); i++) + { + auto cond = bv_utils.equal( + bv, + bv_utilst::concatenate( + bv_utilst::build_constant(i, width - 1), {const_literal(true)})); + bv_utils.cond_implies_equal( + cond, + bv_utilst::sign_extension(numbered_pointers[i].second, width), + result); + } + + // the top bit distinguishes 'object only' vs. 'table encoded' + return bv_utils.select(bv.back(), result, bv_utilst::zeros(width)); } -bvt bv_pointerst::object_offset_encoding(const bvt &object, const bvt &offset) +bvt bv_pointerst::object_offset_encoding( + const bvt &object_bv, + const bvt &offset_bv, + const pointer_typet &type) { - bvt result; - result.reserve(offset.size() + object.size()); - result.insert(result.end(), offset.begin(), offset.end()); - result.insert(result.end(), object.begin(), object.end()); - - return result; + const auto width = type.get_width(); + PRECONDITION(object_bv.size() == width); + PRECONDITION(offset_bv.size() == width); + + // is the offset zero? + if(std::find_if_not(offset_bv.begin(), offset_bv.end(), [](literalt l) { + return l == const_literal(false); + }) != offset_bv.end()) + { + // offset is not zero, add to the pointer table + auto number = numbered_pointers.size(); + numbered_pointers.emplace_back(object_bv, offset_bv); + + // Encode the table index. + // Also set top bit to distinguish from object-only pointers. + return bv_utilst::concatenate( + bv_utilst::build_constant(number, width - 1), {const_literal(true)}); + } + else + { + // Offset is zero, just zero-extend object number. + // Top bit is zero to indicate object-only pointer. + return bv_utilst::concatenate( + bv_utilst::zero_extension(object_bv, width - 1), {const_literal(false)}); + } } literalt bv_pointerst::convert_rest(const exprt &expr) @@ -141,17 +180,7 @@ literalt bv_pointerst::convert_rest(const exprt &expr) bvt invalid_bv = object_literals( encode(pointer_logic.get_invalid_object(), type), type); - const std::size_t object_bits = get_object_width(type); - - bvt equal_invalid_bv; - equal_invalid_bv.reserve(object_bits); - - for(std::size_t i=0; i(binary2integer(value_addr, false)); - pointer.offset=binary2integer(value_offset, true); + + // Top bit set? + if(value.front() == '1') + { + // It's a pointer into the table. Turn bits into number, but + // first strip top bit. + auto index = binary2integer(value.substr(1, std::string::npos), false); + + if(index >= 0 && index < numbered_pointers.size()) + { + // copy from table + const auto &entry = numbered_pointers[numeric_cast_v(index)]; + pointer.object = binary2integer(bits_to_string(prop, entry.first), false); + pointer.offset = binary2integer(bits_to_string(prop, entry.second), true); + } + else + { + // out of bounds, we'll make it an 'invalid pointer' + pointer.object = pointer_logic.get_invalid_object(); + pointer.offset = 0; + } + } + else + { + // It's an object only, offset is zero. + pointer.object = binary2integer(value, false); + pointer.offset = 0; + } return annotated_pointer_constant_exprt{ bvrep, pointer_logic.pointer_expr(pointer, pt)}; } -bvt bv_pointerst::encode(const mp_integer &addr, const pointer_typet &type) +bvt bv_pointerst::encode(const mp_integer &object, const pointer_typet &type) const { - const std::size_t offset_bits = get_offset_width(type); - const std::size_t object_bits = get_object_width(type); + const auto width = type.get_width(); - bvt zero_offset(offset_bits, const_literal(false)); - bvt object = bv_utils.build_constant(addr, object_bits); + auto object_bv = bv_utilst::build_constant(object, width - 1); - return object_offset_encoding(object, zero_offset); + // Offset is zero, just zero-extend object number. + // Top bit is zero to indicate object-only pointer. + return bv_utilst::concatenate(object_bv, {const_literal(false)}); } bvt bv_pointerst::offset_arithmetic( @@ -833,7 +908,7 @@ bvt bv_pointerst::offset_arithmetic( const bvt &bv, const mp_integer &x) { - const std::size_t offset_bits = get_offset_width(type); + const std::size_t offset_bits = type.get_width(); return offset_arithmetic( type, bv, 1, bv_utils.build_constant(x, offset_bits)); @@ -851,36 +926,45 @@ bvt bv_pointerst::offset_arithmetic( index.type().id()==ID_signedbv?bv_utilst::representationt::SIGNED: bv_utilst::representationt::UNSIGNED; - const std::size_t offset_bits = get_offset_width(type); - bv_index=bv_utils.extension(bv_index, offset_bits, rep); + PRECONDITION(bv.size() == type.get_width()); + + bv_index = bv_utils.extension(bv_index, bv.size(), rep); return offset_arithmetic(type, bv, factor, bv_index); } bvt bv_pointerst::offset_arithmetic( const pointer_typet &type, - const bvt &bv, + const bvt &pointer_bv, const mp_integer &factor, - const bvt &index) + const bvt &index_bv) { - bvt bv_index; + PRECONDITION(pointer_bv.size() == type.get_width()); + PRECONDITION(index_bv.size() == type.get_width()); + + bvt index_scaled_bv; if(factor==1) - bv_index=index; + { + index_scaled_bv = index_bv; + } else { - bvt bv_factor=bv_utils.build_constant(factor, index.size()); - bv_index = bv_utils.signed_multiplier(index, bv_factor); + bvt factor_bv = bv_utils.build_constant(factor, pointer_bv.size()); + index_scaled_bv = bv_utils.signed_multiplier( + bv_utils.sign_extension(index_bv, pointer_bv.size()), factor_bv); } - const std::size_t offset_bits = get_offset_width(type); - bv_index = bv_utils.sign_extension(bv_index, offset_bits); + bvt offset_bv = offset_literals(pointer_bv, type); + CHECK_RETURN(offset_bv.size() == pointer_bv.size()); - bvt offset_bv = offset_literals(bv, type); + DATA_INVARIANT( + offset_bv.size() == index_scaled_bv.size(), + "pointer offset bitvector width"); - bvt bv_tmp = bv_utils.add(offset_bv, bv_index); + bvt sum = bv_utils.add(offset_bv, index_scaled_bv); - return object_offset_encoding(object_literals(bv, type), bv_tmp); + return object_offset_encoding(object_literals(pointer_bv, type), sum, type); } bvt bv_pointerst::add_addr(const exprt &expr) @@ -888,15 +972,14 @@ bvt bv_pointerst::add_addr(const exprt &expr) const auto a = pointer_logic.add_object(expr); const pointer_typet type = pointer_type(expr.type()); - const std::size_t object_bits = get_object_width(type); - const std::size_t max_objects=std::size_t(1)<> numbered_pointers; }; #endif // CPROVER_SOLVERS_FLATTENING_BV_POINTERS_H From b08c997d3e16f8200f6a67550d9b3ed07ec2ce64 Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Wed, 27 Apr 2022 18:38:59 +0100 Subject: [PATCH 3/4] pointer encoding: tests changed --- jbmc/regression/jbmc-json-ui/pointer-simplification/test.desc | 2 +- .../jbmc-strings/StringFormatHex/test-hex-eval-upper.desc | 2 +- .../regression/jbmc-strings/StringFormatHex/test-hex-eval.desc | 2 +- jbmc/regression/jbmc-strings/char_escape/test.desc | 2 +- jbmc/regression/jbmc/address_space_size_limit1/test.desc | 2 +- jbmc/regression/jbmc/assume-inputs-non-null/class_assume.desc | 2 +- jbmc/regression/jbmc/lambda-boxing/Boolean.desc | 2 +- jbmc/regression/jbmc/lambda-boxing/Float.desc | 2 +- jbmc/regression/jbmc/lambda-boxing/Integer.desc | 2 +- jbmc/regression/jbmc/lambda-void-return-type/test.desc | 2 +- .../jbmc/no-main-args-elements-maybe-null2/test.desc | 2 +- jbmc/regression/jbmc/string_field_aliasing/test.desc | 2 +- jbmc/regression/strings-smoke-tests/java_parseint/test4.desc | 2 +- regression/cbmc-library/fprintf-01/test.desc | 2 +- regression/cbmc-library/free-01/test.desc | 2 +- regression/cbmc-primitives/r_w_ok_bug/test.desc | 2 +- .../r_w_ok_inconsistent_invalid/test-no-cp.desc | 2 +- .../cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc | 2 +- regression/cbmc-primitives/same-object-01/test-no-cp.desc | 2 +- regression/cbmc-primitives/same-object-01/test.desc | 2 +- regression/cbmc/Pointer_comparison1/main.c | 3 +-- regression/cbmc/address_space_size_limit1/test.desc | 2 +- regression/cbmc/hex_trace/main.c | 1 + regression/cbmc/memory_allocation1/test.desc | 2 +- regression/cbmc/mm_io1/test.desc | 2 +- regression/cbmc/pointer-extra-checks/test.desc | 2 +- regression/contracts/assigns-enforce-malloc-zero/test.desc | 2 +- regression/contracts/test_struct_member_enforce/test.desc | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/jbmc/regression/jbmc-json-ui/pointer-simplification/test.desc b/jbmc/regression/jbmc-json-ui/pointer-simplification/test.desc index b6fbcc4a530..50d7aaf18ac 100644 --- a/jbmc/regression/jbmc-json-ui/pointer-simplification/test.desc +++ b/jbmc/regression/jbmc-json-ui/pointer-simplification/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG test filter.jq --json-ui --trace ^EXIT=0$ diff --git a/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval-upper.desc b/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval-upper.desc index 07722f345f2..386fe0feeda 100644 --- a/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval-upper.desc +++ b/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval-upper.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Test --function Test.testHexEvalUpper --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` --trace ^EXIT=10$ diff --git a/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval.desc b/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval.desc index 6042b9571cb..68bf07a99cf 100644 --- a/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval.desc +++ b/jbmc/regression/jbmc-strings/StringFormatHex/test-hex-eval.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Test --function Test.testHexEval --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` --trace ^EXIT=10$ diff --git a/jbmc/regression/jbmc-strings/char_escape/test.desc b/jbmc/regression/jbmc-strings/char_escape/test.desc index fe0255b60de..aa2af5efedc 100644 --- a/jbmc/regression/jbmc-strings/char_escape/test.desc +++ b/jbmc/regression/jbmc-strings/char_escape/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Test --function Test.test --trace --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` --json-ui ^EXIT=10$ diff --git a/jbmc/regression/jbmc/address_space_size_limit1/test.desc b/jbmc/regression/jbmc/address_space_size_limit1/test.desc index a9bb6c1ed0a..cd86e56700d 100644 --- a/jbmc/regression/jbmc/address_space_size_limit1/test.desc +++ b/jbmc/regression/jbmc/address_space_size_limit1/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Test --object-bits 4 too many addressed objects diff --git a/jbmc/regression/jbmc/assume-inputs-non-null/class_assume.desc b/jbmc/regression/jbmc/assume-inputs-non-null/class_assume.desc index 4e07e36aac7..7c9ce8eb92b 100644 --- a/jbmc/regression/jbmc/assume-inputs-non-null/class_assume.desc +++ b/jbmc/regression/jbmc/assume-inputs-non-null/class_assume.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG My --function My.classArg --java-assume-inputs-non-null ^EXIT=10$ diff --git a/jbmc/regression/jbmc/lambda-boxing/Boolean.desc b/jbmc/regression/jbmc/lambda-boxing/Boolean.desc index 0332bda7d98..04893538e3f 100644 --- a/jbmc/regression/jbmc/lambda-boxing/Boolean.desc +++ b/jbmc/regression/jbmc/lambda-boxing/Boolean.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG BoxingLambda --function BoxingLambda.testBoolean --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` \[java::BoxingLambda\.testBoolean:\(\)V\.assertion\.1\] line 73 assertion at file BoxingLambda\.java line 73 function java::BoxingLambda\.testBoolean:\(\)V bytecode-index 25: SUCCESS diff --git a/jbmc/regression/jbmc/lambda-boxing/Float.desc b/jbmc/regression/jbmc/lambda-boxing/Float.desc index 9f5d65588f0..7c011ea31db 100644 --- a/jbmc/regression/jbmc/lambda-boxing/Float.desc +++ b/jbmc/regression/jbmc/lambda-boxing/Float.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG BoxingLambda --function BoxingLambda.testFloat --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` \[java::BoxingLambda\.testFloat:\(\)V\.assertion\.1\] line 125 assertion at file BoxingLambda\.java line 125 function java::BoxingLambda\.testFloat:\(\)V bytecode-index 27: SUCCESS diff --git a/jbmc/regression/jbmc/lambda-boxing/Integer.desc b/jbmc/regression/jbmc/lambda-boxing/Integer.desc index 60e86c4827c..165f727b44d 100644 --- a/jbmc/regression/jbmc/lambda-boxing/Integer.desc +++ b/jbmc/regression/jbmc/lambda-boxing/Integer.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG BoxingLambda --function BoxingLambda.testInteger --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` \[java::BoxingLambda\.testInteger:\(\)V\.assertion\.1\] line 138 assertion at file BoxingLambda\.java line 138 function java::BoxingLambda\.testInteger:\(\)V bytecode-index 26: SUCCESS diff --git a/jbmc/regression/jbmc/lambda-void-return-type/test.desc b/jbmc/regression/jbmc/lambda-void-return-type/test.desc index f850216ee3a..ce6e46ad364 100644 --- a/jbmc/regression/jbmc/lambda-void-return-type/test.desc +++ b/jbmc/regression/jbmc/lambda-void-return-type/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Test --function Test.test --classpath `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` ^EXIT=10$ diff --git a/jbmc/regression/jbmc/no-main-args-elements-maybe-null2/test.desc b/jbmc/regression/jbmc/no-main-args-elements-maybe-null2/test.desc index 3ded38f4ad6..2b6fc518980 100644 --- a/jbmc/regression/jbmc/no-main-args-elements-maybe-null2/test.desc +++ b/jbmc/regression/jbmc/no-main-args-elements-maybe-null2/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Main --function Main.main ^EXIT=10$ diff --git a/jbmc/regression/jbmc/string_field_aliasing/test.desc b/jbmc/regression/jbmc/string_field_aliasing/test.desc index 9082fd092e3..5ba913b80ff 100644 --- a/jbmc/regression/jbmc/string_field_aliasing/test.desc +++ b/jbmc/regression/jbmc/string_field_aliasing/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Cart --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` --trace --java-max-vla-length 96 --java-unwind-enum-static --max-nondet-string-length 200 --unwind 4 --function Cart.checkTax4 --string-printable ^EXIT=10$ diff --git a/jbmc/regression/strings-smoke-tests/java_parseint/test4.desc b/jbmc/regression/strings-smoke-tests/java_parseint/test4.desc index 09c74c001ad..11ac9232999 100644 --- a/jbmc/regression/strings-smoke-tests/java_parseint/test4.desc +++ b/jbmc/regression/strings-smoke-tests/java_parseint/test4.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG Test4 --max-nondet-string-length 1000 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar ../../../lib/java-models-library/target/cprover-api.jar` --function Test4.main --trace ^EXIT=10$ diff --git a/regression/cbmc-library/fprintf-01/test.desc b/regression/cbmc-library/fprintf-01/test.desc index 96c9b4bcd7b..9542d988e8d 100644 --- a/regression/cbmc-library/fprintf-01/test.desc +++ b/regression/cbmc-library/fprintf-01/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --pointer-check --bounds-check ^EXIT=0$ diff --git a/regression/cbmc-library/free-01/test.desc b/regression/cbmc-library/free-01/test.desc index 769ba573e7c..40f601bba9f 100644 --- a/regression/cbmc-library/free-01/test.desc +++ b/regression/cbmc-library/free-01/test.desc @@ -1,7 +1,7 @@ CORE main.c --pointer-check --bounds-check --stop-on-fail -free argument must be NULL or valid pointer +free argument must be (dynamic object|NULL or valid pointer) ^EXIT=10$ ^SIGNAL=0$ ^VERIFICATION FAILED$ diff --git a/regression/cbmc-primitives/r_w_ok_bug/test.desc b/regression/cbmc-primitives/r_w_ok_bug/test.desc index e47b34c18b2..54d5d3700de 100644 --- a/regression/cbmc-primitives/r_w_ok_bug/test.desc +++ b/regression/cbmc-primitives/r_w_ok_bug/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --pointer-check --no-simplify --no-propagation ^\[main.pointer_dereference.\d+\] line 8 dereference failure: pointer outside object bounds in \*p1: FAILURE$ diff --git a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc index ada56588c85..44db1c65414 100644 --- a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc +++ b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --pointer-check --no-simplify --no-propagation ^EXIT=0$ diff --git a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc index 2b2871e6642..3c0504f372a 100644 --- a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc +++ b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --pointer-check ^EXIT=0$ diff --git a/regression/cbmc-primitives/same-object-01/test-no-cp.desc b/regression/cbmc-primitives/same-object-01/test-no-cp.desc index 97df364eec4..8482907fb49 100644 --- a/regression/cbmc-primitives/same-object-01/test-no-cp.desc +++ b/regression/cbmc-primitives/same-object-01/test-no-cp.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --no-simplify --no-propagation ^EXIT=0$ diff --git a/regression/cbmc-primitives/same-object-01/test.desc b/regression/cbmc-primitives/same-object-01/test.desc index d32f40840c5..877ae606eb8 100644 --- a/regression/cbmc-primitives/same-object-01/test.desc +++ b/regression/cbmc-primitives/same-object-01/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c ^EXIT=0$ diff --git a/regression/cbmc/Pointer_comparison1/main.c b/regression/cbmc/Pointer_comparison1/main.c index 08022bf75fd..e45b7c1aa5e 100644 --- a/regression/cbmc/Pointer_comparison1/main.c +++ b/regression/cbmc/Pointer_comparison1/main.c @@ -10,8 +10,7 @@ int main() return 0; if( - (unsigned long)p > - 42) // unsoundly evaluates to true due to pointer encoding + (unsigned long)p > 1) // unsoundly evaluates to true due to pointer encoding { return 0; } diff --git a/regression/cbmc/address_space_size_limit1/test.desc b/regression/cbmc/address_space_size_limit1/test.desc index 3bc849b0cbf..9c02e15b09d 100644 --- a/regression/cbmc/address_space_size_limit1/test.desc +++ b/regression/cbmc/address_space_size_limit1/test.desc @@ -1,4 +1,4 @@ -CORE thorough-paths broken-smt-backend +KNOWNBUG thorough-paths broken-smt-backend test.c --no-simplify --unwind 300 --object-bits 8 too many addressed objects diff --git a/regression/cbmc/hex_trace/main.c b/regression/cbmc/hex_trace/main.c index 91e9de5a3d6..08938f6a71a 100644 --- a/regression/cbmc/hex_trace/main.c +++ b/regression/cbmc/hex_trace/main.c @@ -6,6 +6,7 @@ int main() char *p; a = 0; + b = 0; a = -100; a = 2147483647; b = a * 2; diff --git a/regression/cbmc/memory_allocation1/test.desc b/regression/cbmc/memory_allocation1/test.desc index 12560af6f29..c0eaa24df81 100644 --- a/regression/cbmc/memory_allocation1/test.desc +++ b/regression/cbmc/memory_allocation1/test.desc @@ -1,4 +1,4 @@ -CORE broken-smt-backend +KNOWNBUG broken-smt-backend main.c --pointer-check ^EXIT=10$ diff --git a/regression/cbmc/mm_io1/test.desc b/regression/cbmc/mm_io1/test.desc index 9efefbc7362..52168c7eba4 100644 --- a/regression/cbmc/mm_io1/test.desc +++ b/regression/cbmc/mm_io1/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c ^EXIT=0$ diff --git a/regression/cbmc/pointer-extra-checks/test.desc b/regression/cbmc/pointer-extra-checks/test.desc index b793e876bf8..4972482211b 100644 --- a/regression/cbmc/pointer-extra-checks/test.desc +++ b/regression/cbmc/pointer-extra-checks/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --pointer-check ^EXIT=10$ diff --git a/regression/contracts/assigns-enforce-malloc-zero/test.desc b/regression/contracts/assigns-enforce-malloc-zero/test.desc index eefba72ce5b..6940c67a633 100644 --- a/regression/contracts/assigns-enforce-malloc-zero/test.desc +++ b/regression/contracts/assigns-enforce-malloc-zero/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --enforce-contract foo _ --malloc-may-fail --malloc-fail-null ^\[foo.assigns.\d+\] line 9 Check that POINTER_OBJECT\(\(const void \*\)a\) is valid when a != \(\(char \*\)NULL\): SUCCESS$ diff --git a/regression/contracts/test_struct_member_enforce/test.desc b/regression/contracts/test_struct_member_enforce/test.desc index 7f7a8adf160..2b9112f2b03 100644 --- a/regression/contracts/test_struct_member_enforce/test.desc +++ b/regression/contracts/test_struct_member_enforce/test.desc @@ -1,4 +1,4 @@ -CORE +KNOWNBUG main.c --enforce-contract foo ^EXIT=0$ From 6f42b0e2f2a3d47869ac658e074e91e27a3c46ab Mon Sep 17 00:00:00 2001 From: Daniel Kroening Date: Thu, 28 Apr 2022 22:59:32 +0100 Subject: [PATCH 4/4] re-encode integers converted to pointers --- regression/cbmc-library/fprintf-01/test.desc | 2 +- .../test-no-cp.desc | 2 +- .../r_w_ok_inconsistent_invalid/test.desc | 2 +- regression/cbmc/memory_allocation1/test.desc | 2 +- regression/cbmc/mm_io1/test.desc | 2 +- .../cbmc/pointer-extra-checks/test.desc | 2 +- src/solvers/flattening/bv_pointers.cpp | 25 ++++++++++++------- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/regression/cbmc-library/fprintf-01/test.desc b/regression/cbmc-library/fprintf-01/test.desc index 9542d988e8d..96c9b4bcd7b 100644 --- a/regression/cbmc-library/fprintf-01/test.desc +++ b/regression/cbmc-library/fprintf-01/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --pointer-check --bounds-check ^EXIT=0$ diff --git a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc index 44db1c65414..ada56588c85 100644 --- a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc +++ b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test-no-cp.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --pointer-check --no-simplify --no-propagation ^EXIT=0$ diff --git a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc index 3c0504f372a..2b2871e6642 100644 --- a/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc +++ b/regression/cbmc-primitives/r_w_ok_inconsistent_invalid/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --pointer-check ^EXIT=0$ diff --git a/regression/cbmc/memory_allocation1/test.desc b/regression/cbmc/memory_allocation1/test.desc index c0eaa24df81..12560af6f29 100644 --- a/regression/cbmc/memory_allocation1/test.desc +++ b/regression/cbmc/memory_allocation1/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG broken-smt-backend +CORE broken-smt-backend main.c --pointer-check ^EXIT=10$ diff --git a/regression/cbmc/mm_io1/test.desc b/regression/cbmc/mm_io1/test.desc index 52168c7eba4..9efefbc7362 100644 --- a/regression/cbmc/mm_io1/test.desc +++ b/regression/cbmc/mm_io1/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c ^EXIT=0$ diff --git a/regression/cbmc/pointer-extra-checks/test.desc b/regression/cbmc/pointer-extra-checks/test.desc index 4972482211b..b793e876bf8 100644 --- a/regression/cbmc/pointer-extra-checks/test.desc +++ b/regression/cbmc/pointer-extra-checks/test.desc @@ -1,4 +1,4 @@ -KNOWNBUG +CORE main.c --pointer-check ^EXIT=10$ diff --git a/src/solvers/flattening/bv_pointers.cpp b/src/solvers/flattening/bv_pointers.cpp index 0e4f3e024af..1a0bf68a3f3 100644 --- a/src/solvers/flattening/bv_pointers.cpp +++ b/src/solvers/flattening/bv_pointers.cpp @@ -76,7 +76,7 @@ bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type) PRECONDITION(width == bv.size()); const auto result = prop.new_variables(width); - bvt match_found; + bvt match_found_disjuncts; for(std::size_t i = 0; i < numbered_pointers.size(); i++) { @@ -84,21 +84,21 @@ bvt bv_pointerst::object_literals(const bvt &bv, const pointer_typet &type) bv, bv_utilst::concatenate( bv_utilst::build_constant(i, width - 1), {const_literal(true)})); - match_found.push_back(cond); + match_found_disjuncts.push_back(cond); bv_utils.cond_implies_equal( cond, bv_utilst::zero_extension(numbered_pointers[i].first, width), result); } - auto within_bounds = prop.lor(match_found); + auto match_found = prop.lor(match_found_disjuncts); // The top bit distinguishes 'object only' vs. 'table encoded'. // When outside of the table, return an invalid object. return bv_utils.select( bv.back(), bv_utils.select( - within_bounds, + match_found, result, bv_utilst::build_constant(pointer_logic.get_invalid_object(), width)), bv); @@ -110,6 +110,7 @@ bvt bv_pointerst::offset_literals(const bvt &bv, const pointer_typet &type) PRECONDITION(width == bv.size()); const auto result = prop.new_variables(width); + bvt match_found_disjuncts; for(std::size_t i = 0; i < numbered_pointers.size(); i++) { @@ -117,14 +118,20 @@ bvt bv_pointerst::offset_literals(const bvt &bv, const pointer_typet &type) bv, bv_utilst::concatenate( bv_utilst::build_constant(i, width - 1), {const_literal(true)})); + match_found_disjuncts.push_back(cond); bv_utils.cond_implies_equal( cond, bv_utilst::sign_extension(numbered_pointers[i].second, width), result); } + auto match_found = prop.lor(match_found_disjuncts); + // the top bit distinguishes 'object only' vs. 'table encoded' - return bv_utils.select(bv.back(), result, bv_utilst::zeros(width)); + return bv_utils.select( + bv.back(), + bv_utils.select(match_found, result, bv_utilst::zeros(width)), + bv_utilst::zeros(width)); } bvt bv_pointerst::object_offset_encoding( @@ -436,11 +443,11 @@ bvt bv_pointerst::convert_pointer_type(const exprt &expr) op_type.id() == ID_c_enum || op_type.id() == ID_c_enum_tag) { // Cast from a bitvector type to pointer. - // We just do a zero extension. - + // We interpret as NULL + offset, where the offset is + // derived from the bitvector by zero extension. const bvt &op_bv=convert_bv(op); - - return bv_utils.zero_extension(op_bv, bits); + return object_offset_encoding( + bv_utilst::zeros(bits), bv_utilst::zero_extension(op_bv, bits), type); } } else if(expr.id()==ID_if)