Skip to content

Commit 14f618c

Browse files
authored
Merge pull request #4489 from romainbrenguier/bugfix/string-solver-nil-array
Prevent potential string solver failures
2 parents 9669534 + 2c2c5ed commit 14f618c

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed
Binary file not shown.

jbmc/regression/jbmc-strings/StringConcat/Test.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,4 +312,15 @@ public String bufferNonDetLoop5(int cols, int columnWidth, String c, String data
312312
assert(false);
313313
return sb.toString();
314314
}
315+
316+
static boolean fromNonDetArray(String[] argv)
317+
{
318+
String s = argv[0];
319+
String u = s.concat("llo");
320+
if(u.equals("Hello")) {
321+
return true;
322+
}
323+
return false;
324+
}
325+
315326
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
--function Test.fromNonDetArray --depth 10000 --unwind 5 --throw-runtime-exceptions --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar` --trace
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED
7+
line 318 no uncaught exception: FAILURE
8+
java.lang.ArrayIndexOutOfBoundsException|java.lang.NullPointerException

src/solvers/strings/string_refinement.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,13 @@ decision_proceduret::resultt string_refinementt::dec_solve()
790790
for(const auto &instance : initial_instances)
791791
add_lemma(instance);
792792

793+
// All generated strings should have non-negative length
794+
for(const auto &string : generator.array_pool.created_strings())
795+
{
796+
add_lemma(binary_relation_exprt{
797+
string.length(), ID_ge, from_integer(0, string.length().type())});
798+
}
799+
793800
while((loop_bound_--) > 0)
794801
{
795802
dependencies.clean_cache();
@@ -2060,6 +2067,12 @@ exprt string_refinementt::get(const exprt &expr) const
20602067
}
20612068
const auto array = supert::get(current.get());
20622069
const auto index = get(index_expr->index());
2070+
2071+
// If the underlying solver does not know about the existence of an array,
2072+
// it can return nil, which cannot be used in the expression returned here.
2073+
if(array.is_nil())
2074+
return index_exprt(current, index);
2075+
20632076
const exprt unknown =
20642077
from_integer(CHARACTER_FOR_UNKNOWN, index_expr->type());
20652078
if(
@@ -2070,12 +2083,9 @@ exprt string_refinementt::get(const exprt &expr) const
20702083
return sparse_array->to_if_expression(index);
20712084
}
20722085

2073-
INVARIANT(
2074-
array.is_nil() || array.id() == ID_symbol ||
2075-
array.id() == ID_nondet_symbol,
2076-
std::string("apart from symbols, array valuations can be interpreted as "
2077-
"sparse arrays, id: ") +
2078-
id2string(array.id()));
2086+
INVARIANT(array.id() == ID_symbol || array.id() == ID_nondet_symbol,
2087+
"Apart from symbols, array valuations can be interpreted as "
2088+
"sparse arrays. Array model : " + array.pretty());
20792089
return index_exprt(array, index);
20802090
}
20812091

0 commit comments

Comments
 (0)