Skip to content

Commit 2af983d

Browse files
authored
Merge pull request diffblue#5126 from danpoe/feature/constant-propagation-of-delete-char-at
Constant propagation of deleteCharAt()
2 parents 1b94092 + 193a29b commit 2af983d

File tree

14 files changed

+218
-0
lines changed

14 files changed

+218
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
public class Test
2+
{
3+
public void testSuccess()
4+
{
5+
StringBuffer sb = new StringBuffer("abc");
6+
sb.deleteCharAt(1);
7+
assert sb.toString().equals("ac");
8+
}
9+
10+
public void testNoPropagation(int index)
11+
{
12+
StringBuffer sb = new StringBuffer("abc");
13+
sb.deleteCharAt(index);
14+
assert sb.toString().equals("ac");
15+
}
16+
17+
public void testIndexOutOfBounds1()
18+
{
19+
StringBuffer sb = new StringBuffer("abc");
20+
sb.deleteCharAt(-1);
21+
assert sb.toString().equals("ac");
22+
}
23+
24+
public void testIndexOutOfBounds2()
25+
{
26+
StringBuffer sb = new StringBuffer("abc");
27+
sb.deleteCharAt(3);
28+
assert sb.toString().equals("ac");
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
--function Test.testIndexOutOfBounds1 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
--function Test.testIndexOutOfBounds2 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE symex-driven-lazy-loading-expected-failure
2+
Test.class
3+
--function Test.testNoPropagation --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar` --property 'java::Test.testNoPropagation:(I)V.assertion.1'
4+
^Generated [0-9]+ VCC\(s\), 1 remaining after simplification$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
^VERIFICATION FAILED$
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.testSuccess --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: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
public class Test
2+
{
3+
public void testSuccess()
4+
{
5+
StringBuilder sb = new StringBuilder("abc");
6+
sb.deleteCharAt(1);
7+
assert sb.toString().equals("ac");
8+
}
9+
10+
public void testNoPropagation(int index)
11+
{
12+
StringBuilder sb = new StringBuilder("abc");
13+
sb.deleteCharAt(index);
14+
assert sb.toString().equals("ac");
15+
}
16+
17+
public void testIndexOutOfBounds1()
18+
{
19+
StringBuilder sb = new StringBuilder("abc");
20+
sb.deleteCharAt(-1);
21+
assert sb.toString().equals("ac");
22+
}
23+
24+
public void testIndexOutOfBounds2()
25+
{
26+
StringBuilder sb = new StringBuilder("abc");
27+
sb.deleteCharAt(3);
28+
assert sb.toString().equals("ac");
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
--function Test.testIndexOutOfBounds1 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
--function Test.testIndexOutOfBounds2 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
8+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE symex-driven-lazy-loading-expected-failure
2+
Test.class
3+
--function Test.testNoPropagation --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar` --property 'java::Test.testNoPropagation:(I)V.assertion.1'
4+
^Generated [0-9]+ VCC\(s\), 1 remaining after simplification$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
^VERIFICATION FAILED$
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.testSuccess --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+
--

src/goto-symex/goto_symex.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ bool goto_symext::constant_propagate_assignment_with_side_effects(
191191
{
192192
return constant_propagate_integer_to_string(state, symex_assign, f_l1);
193193
}
194+
else if(func_id == ID_cprover_string_delete_char_at_func)
195+
{
196+
return constant_propagate_delete_char_at(state, symex_assign, f_l1);
197+
}
194198
}
195199
}
196200

@@ -588,3 +592,76 @@ bool goto_symext::constant_propagate_integer_to_string(
588592

589593
return true;
590594
}
595+
596+
bool goto_symext::constant_propagate_delete_char_at(
597+
statet &state,
598+
symex_assignt &symex_assign,
599+
const function_application_exprt &f_l1)
600+
{
601+
// The function application expression f_l1 takes the following arguments:
602+
// - result string length (output parameter)
603+
// - result string data array (output parameter)
604+
// - string to delete char from
605+
// - index of char to delete
606+
PRECONDITION(f_l1.arguments().size() == 4);
607+
608+
const auto &f_type = to_mathematical_function_type(f_l1.function().type());
609+
const auto &length_type = f_type.domain().at(0);
610+
const auto &char_type = to_pointer_type(f_type.domain().at(1)).subtype();
611+
612+
const refined_string_exprt &s = to_string_expr(f_l1.arguments().at(2));
613+
const auto s_data_opt = try_evaluate_constant_string(state, s.content());
614+
615+
if(!s_data_opt)
616+
{
617+
return false;
618+
}
619+
620+
const array_exprt &s_data = s_data_opt->get();
621+
622+
const auto &index_opt = try_evaluate_constant(state, f_l1.arguments().at(3));
623+
624+
if(!index_opt)
625+
{
626+
return false;
627+
}
628+
629+
const mp_integer index = numeric_cast_v<mp_integer>(index_opt->get());
630+
631+
if(index < 0 || index >= s_data.operands().size())
632+
{
633+
return false;
634+
}
635+
636+
const constant_exprt new_char_array_length =
637+
from_integer(s_data.operands().size() - 1, length_type);
638+
639+
const array_typet new_char_array_type(char_type, new_char_array_length);
640+
641+
exprt::operandst operands;
642+
operands.reserve(s_data.operands().size() - 1);
643+
644+
const std::size_t i = numeric_cast_v<std::size_t>(index);
645+
646+
operands.insert(
647+
operands.end(),
648+
s_data.operands().begin(),
649+
std::next(s_data.operands().begin(), i));
650+
651+
operands.insert(
652+
operands.end(),
653+
std::next(s_data.operands().begin(), i + 1),
654+
s_data.operands().end());
655+
656+
const array_exprt new_char_array(std::move(operands), new_char_array_type);
657+
658+
assign_string_constant(
659+
state,
660+
symex_assign,
661+
to_ssa_expr(f_l1.arguments().at(0)),
662+
new_char_array_length,
663+
to_ssa_expr(f_l1.arguments().at(1)),
664+
new_char_array);
665+
666+
return true;
667+
}

src/goto-symex/goto_symex.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,19 @@ class goto_symext
597597
symex_assignt &symex_assign,
598598
const function_application_exprt &f_l1);
599599

600+
/// Attempt to constant propagate deleting a character from a string
601+
///
602+
/// \param state: goto symex state
603+
/// \param symex_assign: object handling symbol assignments
604+
/// \param f_l1: application of function ID_cprover_string_delete_char_at_func
605+
/// with l1 renaming applied
606+
/// \return true if the operation could be evaluated to a constant string,
607+
/// false otherwise
608+
bool constant_propagate_delete_char_at(
609+
statet &state,
610+
symex_assignt &symex_assign,
611+
const function_application_exprt &f_l1);
612+
600613
/// Assign constant string length and string data given by a char array to
601614
/// given ssa variables
602615
///

0 commit comments

Comments
 (0)