Skip to content

Commit a966852

Browse files
committed
Constant propagation of CProverString.setCharAt()
Only minimal tests are added at this point. The error conditions (like index out of bounds) will be handled by the models. Once we have models that use CProverString.setCharAt(), more comprehensive tests will be added.
1 parent 88b8140 commit a966852

File tree

7 files changed

+128
-2
lines changed

7 files changed

+128
-2
lines changed
Binary file not shown.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import org.cprover.CProverString;
2+
3+
public class Test
4+
{
5+
public void testSuccess1()
6+
{
7+
StringBuffer sb = new StringBuffer("abc");
8+
CProverString.setCharAt(sb, 0, 'd');
9+
assert sb.toString().equals("dbc");
10+
}
11+
12+
public void testSuccess2()
13+
{
14+
StringBuffer sb = new StringBuffer("abc");
15+
CProverString.setCharAt(sb, 2, 'd');
16+
assert sb.toString().equals("abd");
17+
}
18+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
Test.class
3+
--function Test.testSuccess1 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^Generated [0-9]+ VCC\(s\), 0 remaining after simplification$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
^VERIFICATION SUCCESSFUL$
8+
--
9+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
Test.class
3+
--function Test.testSuccess2 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^Generated [0-9]+ VCC\(s\), 0 remaining after simplification$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
^VERIFICATION SUCCESSFUL$
8+
--
9+
--

jbmc/src/java_bytecode/java_string_library_preprocess.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,8 +1528,11 @@ void java_string_library_preprocesst::initialize_conversion_table()
15281528
["java::org.cprover.CProverString.offsetByCodePoints:(Ljava/lang/"
15291529
"String;II)I"] = ID_cprover_string_offset_by_code_point_func;
15301530
cprover_equivalent_to_java_assign_function
1531-
["java::org.cprover.CProverString.setCharAt:(Ljava/lang/String;IC)V"] =
1532-
ID_cprover_string_char_set_func;
1531+
["java::org.cprover.CProverString.setCharAt:(Ljava/lang/"
1532+
"StringBuffer;IC)V"] = ID_cprover_string_char_set_func;
1533+
cprover_equivalent_to_java_assign_function
1534+
["java::org.cprover.CProverString.setCharAt:(Ljava/lang/"
1535+
"StringBuilder;IC)V"] = ID_cprover_string_char_set_func;
15331536
cprover_equivalent_to_java_assign_function
15341537
["java::org.cprover.CProverString.setLength:(Ljava/lang/StringBuffer;I)V"] =
15351538
ID_cprover_string_set_length_func;

src/goto-symex/goto_symex.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ bool goto_symext::constant_propagate_assignment_with_side_effects(
203203
{
204204
return constant_propagate_set_length(state, symex_assign, f_l1);
205205
}
206+
else if(func_id == ID_cprover_string_char_set_func)
207+
{
208+
return constant_propagate_set_char_at(state, symex_assign, f_l1);
209+
}
206210
}
207211
}
208212

@@ -843,3 +847,73 @@ bool goto_symext::constant_propagate_set_length(
843847

844848
return true;
845849
}
850+
851+
bool goto_symext::constant_propagate_set_char_at(
852+
statet &state,
853+
symex_assignt &symex_assign,
854+
const function_application_exprt &f_l1)
855+
{
856+
// The function application expression f_l1 takes the following arguments:
857+
// - result string length (output parameter)
858+
// - result string data array (output parameter)
859+
// - current string
860+
// - index of char to set
861+
// - new char
862+
PRECONDITION(f_l1.arguments().size() == 5);
863+
864+
const auto &f_type = to_mathematical_function_type(f_l1.function().type());
865+
const auto &length_type = f_type.domain().at(0);
866+
const auto &char_type = to_pointer_type(f_type.domain().at(1)).subtype();
867+
868+
const refined_string_exprt &s = to_string_expr(f_l1.arguments().at(2));
869+
const auto s_data_opt = try_evaluate_constant_string(state, s.content());
870+
871+
if(!s_data_opt)
872+
{
873+
return false;
874+
}
875+
876+
array_exprt s_data = s_data_opt->get();
877+
878+
const auto &index_opt = try_evaluate_constant(state, f_l1.arguments().at(3));
879+
880+
if(!index_opt)
881+
{
882+
return false;
883+
}
884+
885+
const mp_integer index = numeric_cast_v<mp_integer>(index_opt->get());
886+
887+
if(index < 0 || index >= s_data.operands().size())
888+
{
889+
return false;
890+
}
891+
892+
const auto &new_char_opt =
893+
try_evaluate_constant(state, f_l1.arguments().at(4));
894+
895+
if(!new_char_opt)
896+
{
897+
return false;
898+
}
899+
900+
const constant_exprt new_char_array_length =
901+
from_integer(s_data.operands().size(), length_type);
902+
903+
const array_typet new_char_array_type(char_type, new_char_array_length);
904+
905+
s_data.operands()[numeric_cast_v<std::size_t>(index)] = new_char_opt->get();
906+
907+
const array_exprt new_char_array(
908+
std::move(s_data.operands()), new_char_array_type);
909+
910+
assign_string_constant(
911+
state,
912+
symex_assign,
913+
to_ssa_expr(f_l1.arguments().at(0)),
914+
new_char_array_length,
915+
to_ssa_expr(f_l1.arguments().at(1)),
916+
new_char_array);
917+
918+
return true;
919+
}

src/goto-symex/goto_symex.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,19 @@ class goto_symext
641641
symex_assignt &symex_assign,
642642
const function_application_exprt &f_l1);
643643

644+
/// Attempt to constant propagate setting the char at the given index
645+
///
646+
/// \param state: goto symex state
647+
/// \param symex_assign: object handling symbol assignments
648+
/// \param f_l1: application of function ID_cprover_string_char_set_func with
649+
/// l1 renaming applied
650+
/// \return true if the operation could be evaluated to a constant string,
651+
/// false otherwise
652+
bool constant_propagate_set_char_at(
653+
statet &state,
654+
symex_assignt &symex_assign,
655+
const function_application_exprt &f_l1);
656+
644657
/// Assign constant string length and string data given by a char array to
645658
/// given ssa variables
646659
///

0 commit comments

Comments
 (0)