Skip to content

Commit a35c29e

Browse files
committed
Test for complexity limits
This test will fail if any of the features this relies upon has been broken, but has the side-affect that if things ARE broken it'll take a long time to fail. Not much to do about that, as this sort of long-running symex-destroying code is what this feature is meant for.
1 parent 0490f57 commit a35c29e

File tree

5 files changed

+137
-0
lines changed

5 files changed

+137
-0
lines changed
2.42 KB
Binary file not shown.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import java.util.*;
2+
3+
public class ComplexClass {
4+
5+
public void loopBlacklist(List<String> prop, int increment, int size) {
6+
while (size <= 1000)
7+
{
8+
if (size > 500)
9+
branchCancel(prop, increment, size);
10+
11+
size++;
12+
}
13+
}
14+
15+
public void branchCancel(List<String> prop, int increment, int size) {
16+
StringBuilder sb = new StringBuilder();
17+
for (String str : prop)
18+
{
19+
if (size >= 50)
20+
sb.append(str);
21+
22+
size+=increment;
23+
}
24+
}
25+
26+
private static Properties properties = new Properties();
27+
28+
public void process(Properties prop) {
29+
30+
properties = prop;
31+
32+
for (Enumeration<?> pe = properties.propertyNames(); pe.hasMoreElements(); )
33+
{
34+
String key = (String)pe.nextElement();
35+
String value = recurse(key, properties.getProperty(key), 1);
36+
if (value != null)
37+
{
38+
properties.setProperty(key, value);
39+
}
40+
}
41+
}
42+
43+
private static String recurse(String key, String value, int level)
44+
{
45+
if (level > 9)
46+
throw new IllegalArgumentException("Recursion level too deep.");
47+
48+
int from = 0;
49+
StringBuffer result = null;
50+
while (from < value.length()) {
51+
while (from < value.length()) {
52+
int start = value.indexOf("[", from);
53+
if (start >= 0) {
54+
int end = value.indexOf(']', start);
55+
if (end < 0) {
56+
break;
57+
}
58+
String var = value.substring(start + 1, end);
59+
if (result == null) {
60+
result = new StringBuffer(value.substring(from, start));
61+
} else {
62+
result.append(value.substring(from, start));
63+
}
64+
if (properties.containsKey(var)) {
65+
String val = recurse(var, properties.getProperty(var), level + 1);
66+
if (val != null) {
67+
result.append(val);
68+
properties.setProperty(var, val);
69+
} else {
70+
result.append((properties.getProperty(var)).trim());
71+
}
72+
}
73+
74+
from = end + 1;
75+
} else {
76+
break;
77+
}
78+
}
79+
}
80+
81+
if (result != null && from < value.length())
82+
{
83+
result.append(value.substring(from));
84+
}
85+
return (result == null) ? null : result.toString();
86+
}
87+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
CORE
2+
ComplexClass.class
3+
--function ComplexClass.branchCancel --symex-complexity-limit 1 --verbosity 9 --unwind 100 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^(\[symex-complexity\] Branch considered too complex|\[symex-complexity\] Loop operations considered too complex)
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
^VERIFICATION FAILED$
8+
--
9+
--
10+
This tests that we cancel out of a loop with huge unwind and low complexity limit.
11+
12+
The basis here is that the undeterministic incrementor and list mean that symex can't
13+
work out statically what's going on, and so both pieces of unknowability cause the
14+
guard to grow. Once that guard has reached a certain number, it'll be killed via
15+
the complexity module.
16+
17+
If this is broken it means that the heuristics used to generate a 'complexity'
18+
measure of code is broken and will need to be re-written. See complexity_limitert
19+
for the main block of code.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
ComplexClass.class
3+
--function ComplexClass.loopBlacklist --symex-complexity-limit 1 --symex-complexity-failed-child-loops-limit 1 --verbosity 9 --unwind 9 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^(\[symex-complexity\] Trying to enter blacklisted loop|\[symex-complexity\] Loop operations considered too complex)
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
^VERIFICATION FAILED$
8+
--
9+
--
10+
This tests that we cancel out of a loop with huge unwind, low complexity limit and low branch failure limit.
11+
12+
Same basis as branchCancel with nondeterministic values, but in this case we have an
13+
outer loop that we're also running 100 times that will cause the inner to be blacklisted.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CORE
2+
ComplexClass.class
3+
--function ComplexClass.process --symex-complexity-limit 2 --verbosity 9 --unwind 10 --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^\[symex-complexity\] Branch considered too complex|\[symex-complexity\] Trying to enter blacklisted loop|\[symex-complexity\] Loop operations considered too complex$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
^VERIFICATION FAILED$
8+
--
9+
--
10+
This tests that the complexity limits apply correctly and that each level of them are detected correctly:
11+
12+
Branch cancelling.
13+
Loop cancelling.
14+
Loop blacklisting.
15+
16+
When these don't work this test may take some time to run (and then fail), which is hard to
17+
restrict because this is the problem this feature is meant to solve. If this test is running
18+
slowly, high chance something has gone wrong.

0 commit comments

Comments
 (0)