Skip to content

Commit 2105ee9

Browse files
authored
Merge pull request #994 from allredj/pr/string-preprocess-improve-lengths
Improve length handling in string preprocessing
2 parents a308fb5 + 1613290 commit 2105ee9

File tree

8 files changed

+98
-13
lines changed

8 files changed

+98
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
CORE
22
test_length.class
33
--refine-strings
4-
^EXIT=0$
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
^VERIFICATION FAILED$
7+
[.*assertion.1] .* line 7 .*: SUCCESS
8+
[.*assertion.2] .* line 8 .*: FAILURE
79
--
Binary file not shown.

regression/strings-smoke-tests/java_length/test_length.java

+1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ public static void main(/*String[] argv*/)
55
String s = new String("Abc");
66
int l = s.length();
77
assert(l == 3);
8+
assert(l != 3);
89
}
910
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FUTURE
2+
test.class
3+
--refine-strings --function test.check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
This test currently fails because we do not handle the case where the argument
9+
's' is null. This should be handled in the String model.
10+
The issue number for that is: diffblue/test-gen#500
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public class test
2+
{
3+
public static int check(String s)
4+
{
5+
if(s.equals("abc")){
6+
assert s.length() == 3;
7+
return 0;
8+
}
9+
return 1;
10+
}
11+
}
12+

src/java_bytecode/java_string_library_preprocess.cpp

+66-11
Original file line numberDiff line numberDiff line change
@@ -1022,8 +1022,8 @@ Function: java_string_library_preprocesst::
10221022
Output: return the following code:
10231023
> lhs = { {Object}, length=rhs_length, data=rhs_array }
10241024
1025-
Purpose: Produce code for an assignemnrt of a string expr to a
1026-
Java string, component-wise.
1025+
Purpose: Produce code for an assignment of a string expr to a
1026+
Java string.
10271027
10281028
\*******************************************************************/
10291029

@@ -1862,8 +1862,7 @@ codet java_string_library_preprocesst::make_copy_string_code(
18621862

18631863
/*******************************************************************\
18641864
1865-
Function:
1866-
java_string_library_preprocesst::make_copy_constructor_code
1865+
Function: java_string_library_preprocesst::make_copy_constructor_code
18671866
18681867
Inputs:
18691868
type - type of the function
@@ -1911,6 +1910,52 @@ codet java_string_library_preprocesst::make_copy_constructor_code(
19111910

19121911
/*******************************************************************\
19131912
1913+
Function: java_string_library_preprocesst::make_string_length_code
1914+
1915+
Inputs:
1916+
type - type of the function
1917+
loc - location in the source
1918+
symbol_table - symbol table
1919+
1920+
Outputs: Code corresponding to:
1921+
> str_expr = java_string_to_string_expr(this)
1922+
> str_expr_sym = str_expr
1923+
> return this->length
1924+
1925+
Purpose: Generates code for the String.length method
1926+
1927+
\*******************************************************************/
1928+
1929+
codet java_string_library_preprocesst::make_string_length_code(
1930+
const code_typet &type,
1931+
const source_locationt &loc,
1932+
symbol_tablet &symbol_table)
1933+
{
1934+
// Code for the output
1935+
code_blockt code;
1936+
1937+
code_typet::parameterst params=type.parameters();
1938+
symbol_exprt arg_this(params[0].get_identifier(), params[0].type());
1939+
dereference_exprt deref(arg_this, arg_this.type().subtype());
1940+
1941+
// Create a new string_exprt to be picked up by the solver
1942+
string_exprt str_expr=fresh_string_expr(loc, symbol_table, code);
1943+
1944+
// Assign this to str_expr
1945+
code.add(
1946+
code_assign_java_string_to_string_expr(str_expr, arg_this, symbol_table));
1947+
1948+
// Assign str_expr to str_expr_sym for that expression to be present in the
1949+
// symbol table in order to be processed by the string solver
1950+
exprt str_expr_sym=fresh_string_expr_symbol(loc, symbol_table, code);
1951+
code.add(code_assignt(str_expr_sym, str_expr));
1952+
code.add(code_returnt(get_length(deref, symbol_table)));
1953+
1954+
return code;
1955+
}
1956+
1957+
/*******************************************************************\
1958+
19141959
Function: java_string_library_preprocesst::code_for_function
19151960
19161961
Inputs:
@@ -2110,9 +2155,14 @@ void java_string_library_preprocesst::initialize_conversion_table()
21102155
cprover_equivalent_to_java_function
21112156
["java::java.lang.String.lastIndexOf:(Ljava/lang/String;I)I"]=
21122157
ID_cprover_string_last_index_of_func;
2113-
cprover_equivalent_to_java_function
2158+
conversion_table
21142159
["java::java.lang.String.length:()I"]=
2115-
ID_cprover_string_length_func;
2160+
std::bind(
2161+
&java_string_library_preprocesst::make_string_length_code,
2162+
this,
2163+
std::placeholders::_1,
2164+
std::placeholders::_2,
2165+
std::placeholders::_3);
21162166
// Not supported "java.lang.String.matches"
21172167
cprover_equivalent_to_java_function
21182168
["java::java.lang.String.offsetByCodePoints:(II)I"]=
@@ -2305,9 +2355,9 @@ void java_string_library_preprocesst::initialize_conversion_table()
23052355
"Ljava/lang/StringBuilder;"]=
23062356
ID_cprover_string_insert_func;
23072357
// Not supported "java.lang.StringBuilder.lastIndexOf"
2308-
cprover_equivalent_to_java_function
2358+
conversion_table
23092359
["java::java.lang.StringBuilder.length:()I"]=
2310-
ID_cprover_string_length_func;
2360+
conversion_table["java::java.lang.String.length:()I"];
23112361
// Not supported "java.lang.StringBuilder.offsetByCodePoints"
23122362
// Not supported "java.lang.StringBuilder.replace"
23132363
// Not supported "java.lang.StringBuilder.reverse"
@@ -2432,9 +2482,9 @@ void java_string_library_preprocesst::initialize_conversion_table()
24322482
"Ljava/lang/StringBuffer;"]=
24332483
ID_cprover_string_insert_func;
24342484
// Not supported "java.lang.StringBuffer.lastIndexOf"
2435-
cprover_equivalent_to_java_function
2485+
conversion_table
24362486
["java::java.lang.StringBuffer.length:()I"]=
2437-
ID_cprover_string_length_func;
2487+
conversion_table["java::java.lang.String.length:()I"];
24382488
// Not supported "java.lang.StringBuffer.offsetByCodePoints"
24392489
// Not supported "java.lang.StringBuffer.replace"
24402490
// Not supported "java.lang.StringBuffer.reverse"
@@ -2461,7 +2511,7 @@ void java_string_library_preprocesst::initialize_conversion_table()
24612511
std::placeholders::_3);
24622512
// Not supported "java.lang.StringBuffer.trimToSize"
24632513

2464-
// Other libraries
2514+
// CharSequence library
24652515
cprover_equivalent_to_java_function
24662516
["java::java.lang.CharSequence.charAt:(I)C"]=
24672517
ID_cprover_string_char_at_func;
@@ -2473,6 +2523,11 @@ void java_string_library_preprocesst::initialize_conversion_table()
24732523
std::placeholders::_1,
24742524
std::placeholders::_2,
24752525
std::placeholders::_3);
2526+
conversion_table
2527+
["java::java.lang.CharSequence.length:()I"]=
2528+
conversion_table["java::java.lang.String.length:()I"];
2529+
2530+
// Other libraries
24762531
conversion_table
24772532
["java::java.lang.Float.toString:(F)Ljava/lang/String;"]=
24782533
std::bind(

src/java_bytecode/java_string_library_preprocess.h

+5
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ class java_string_library_preprocesst:public messaget
146146
const source_locationt &loc,
147147
symbol_tablet &symbol_table);
148148

149+
codet make_string_length_code(
150+
const code_typet &type,
151+
const source_locationt &loc,
152+
symbol_tablet &symbol_table);
153+
149154
// Auxiliary functions
150155
codet code_for_scientific_notation(
151156
const exprt &arg,

0 commit comments

Comments
 (0)