diff --git a/regression/strings/cprover-string-hack.h b/regression/strings/cprover-string-hack.h index 1ec17bca535..56bb66f7960 100644 --- a/regression/strings/cprover-string-hack.h +++ b/regression/strings/cprover-string-hack.h @@ -1,6 +1,5 @@ -typedef struct __CPROVER_string { char *s; } __CPROVER_string; -//typedef struct __CPROVER_char { char c; } __CPROVER_char; -typedef unsigned char __CPROVER_char; +typedef struct __attribute__((__packed__)) __CPROVER_refined_string_type { int length; char content[]; } __CPROVER_refined_string_type; +typedef __CPROVER_refined_string_type __CPROVER_string; /****************************************************************************** * CPROVER string functions @@ -54,19 +53,19 @@ typedef unsigned char __CPROVER_char; /****************************************************************************** * don't use these directly ******************************************************************************/ -extern __CPROVER_char __CPROVER_uninterpreted_string_char_at_func(__CPROVER_string str, int pos); +extern char __CPROVER_uninterpreted_string_char_at_func(__CPROVER_string str, int pos); extern __CPROVER_bool __CPROVER_uninterpreted_string_equal_func(__CPROVER_string str1, __CPROVER_string str2); extern __CPROVER_string __CPROVER_uninterpreted_string_literal_func(char * str); -extern __CPROVER_char __CPROVER_uninterpreted_char_literal_func(); +extern char __CPROVER_uninterpreted_char_literal_func(); extern __CPROVER_string __CPROVER_uninterpreted_string_concat_func(__CPROVER_string str1, __CPROVER_string str2); extern int __CPROVER_uninterpreted_string_length_func(__CPROVER_string str); extern __CPROVER_string __CPROVER_uninterpreted_string_substring_func(__CPROVER_string str, int i, int j); extern __CPROVER_bool __CPROVER_uninterpreted_string_is_prefix_func(__CPROVER_string pref, __CPROVER_string str); extern __CPROVER_bool __CPROVER_uninterpreted_string_is_suffix_func(__CPROVER_string suff, __CPROVER_string str); extern __CPROVER_bool __CPROVER_uninterpreted_string_contains_func(__CPROVER_string str1, __CPROVER_string str2); -extern int __CPROVER_uninterpreted_string_index_of_func(__CPROVER_string str, __CPROVER_char c); -extern int __CPROVER_uninterpreted_string_last_index_of_func(__CPROVER_string str, __CPROVER_char c); -extern __CPROVER_string __CPROVER_uninterpreted_string_char_set_func(__CPROVER_string str, int pos, __CPROVER_char c); +extern int __CPROVER_uninterpreted_string_index_of_func(__CPROVER_string str, char c); +extern int __CPROVER_uninterpreted_string_last_index_of_func(__CPROVER_string str, char c); +extern __CPROVER_string __CPROVER_uninterpreted_string_char_set_func(__CPROVER_string str, int pos, char c); extern __CPROVER_string __CPROVER_uninterpreted_string_copy_func(__CPROVER_string str); extern int __CPROVER_uninterpreted_string_parse_int_func(__CPROVER_string str); extern __CPROVER_string __CPROVER_uninterpreted_string_of_int_func(int i); diff --git a/regression/strings/fixed_bugs/Makefile b/regression/strings/fixed_bugs/Makefile new file mode 100644 index 00000000000..185be13bd7b --- /dev/null +++ b/regression/strings/fixed_bugs/Makefile @@ -0,0 +1,9 @@ + +test: + @../../test.pl -c ../../../../src/cbmc/cbmc + +testfuture: + @../../test.pl -c ../../../../src/cbmc/cbmc -CF + +testall: + @../../test.pl -c ../../../../src/cbmc/cbmc -CFTK diff --git a/regression/strings/fixed_bugs/test-gen-095/test.class b/regression/strings/fixed_bugs/test-gen-095/test.class new file mode 100644 index 00000000000..3895d218c3d Binary files /dev/null and b/regression/strings/fixed_bugs/test-gen-095/test.class differ diff --git a/regression/strings/fixed_bugs/test-gen-095/test.desc b/regression/strings/fixed_bugs/test-gen-095/test.desc new file mode 100644 index 00000000000..2f1edf3ab8d --- /dev/null +++ b/regression/strings/fixed_bugs/test-gen-095/test.desc @@ -0,0 +1,7 @@ +KNOWNBUG +test.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/fixed_bugs/test-gen-095/test.java b/regression/strings/fixed_bugs/test-gen-095/test.java new file mode 100644 index 00000000000..a6910527551 --- /dev/null +++ b/regression/strings/fixed_bugs/test-gen-095/test.java @@ -0,0 +1,10 @@ +public class test +{ + public static void main(String[] args) + { + StringBuilder sb = new StringBuilder(args[0]); + sb.append("Z"); + String s = sb.toString(); + assert(s.equals("fg")); + } +} diff --git a/regression/strings/java_case/test.desc b/regression/strings/java_case/test.desc deleted file mode 100644 index 9f48288c694..00000000000 --- a/regression/strings/java_case/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_case.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_case.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_case.java line 12: SUCCESS$ -^\[assertion.3\] assertion at file test_case.java line 13: SUCCESS$ -^\[assertion.4\] assertion at file test_case.java line 14: FAILURE$ --- diff --git a/regression/strings/java_case/test_case.class b/regression/strings/java_case/test_case.class deleted file mode 100644 index 8579881de17..00000000000 Binary files a/regression/strings/java_case/test_case.class and /dev/null differ diff --git a/regression/strings/java_case/test_case.java b/regression/strings/java_case/test_case.java deleted file mode 100644 index ce3a51814c8..00000000000 --- a/regression/strings/java_case/test_case.java +++ /dev/null @@ -1,16 +0,0 @@ -public class test_case { - - public static void main(String[] argv) { - - String s = new String("AbcCdE"); - String l = s.toLowerCase(); - System.out.println(l); - - String u = s.toUpperCase(); - System.out.println(u); - assert(l.equals("abccde")); - assert(u.equals("ABCCDE")); - assert(s.equalsIgnoreCase("ABccDe")); - assert(!l.equals("abccde") || !u.equals("ABCCDE")); - } -} diff --git a/regression/strings/java_char_array/test.desc b/regression/strings/java_char_array/test.desc deleted file mode 100644 index 8282b808b84..00000000000 --- a/regression/strings/java_char_array/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -test_char_array.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_char_array.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_char_array.java line 12: SUCCESS$ -^\[assertion.3\] assertion at file test_char_array.java line 13: FAILURE$ --- diff --git a/regression/strings/java_char_array/test_char_array.class b/regression/strings/java_char_array/test_char_array.class deleted file mode 100644 index 836942da134..00000000000 Binary files a/regression/strings/java_char_array/test_char_array.class and /dev/null differ diff --git a/regression/strings/java_char_array/test_char_array.java b/regression/strings/java_char_array/test_char_array.java deleted file mode 100644 index 3cfd4000d3a..00000000000 --- a/regression/strings/java_char_array/test_char_array.java +++ /dev/null @@ -1,15 +0,0 @@ -public class test_char_array { - - public static void main(String[] argv) - { - String s = "abc"; - char [] str = s.toCharArray(); - int[] test = new int[312]; - char c = str[2]; - String t = argv[0]; - char d = t.charAt(0); - assert(str.length == 3); - assert(c == 'c'); - assert(c == d || d < 'a' || d > 'z' ); - } -} diff --git a/regression/strings/java_char_array_init/test.desc b/regression/strings/java_char_array_init/test.desc deleted file mode 100644 index fe5ffae7238..00000000000 --- a/regression/strings/java_char_array_init/test.desc +++ /dev/null @@ -1,11 +0,0 @@ -FUTURE -test_init.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_init.java line 16: SUCCESS$ -^\[assertion.2\] assertion at file test_init.java line 17: SUCCESS$ -^\[assertion.3\] assertion at file test_init.java line 18: SUCCESS$ -^\[assertion.4\] assertion at file test_init.java line 20: SUCCESS$ -^\[assertion.5\] assertion at file test_init.java line 21: FAILURE$ --- diff --git a/regression/strings/java_char_array_init/test_init.class b/regression/strings/java_char_array_init/test_init.class deleted file mode 100644 index be3baee56bd..00000000000 Binary files a/regression/strings/java_char_array_init/test_init.class and /dev/null differ diff --git a/regression/strings/java_char_array_init/test_init.java b/regression/strings/java_char_array_init/test_init.java deleted file mode 100644 index 5f4e220844c..00000000000 --- a/regression/strings/java_char_array_init/test_init.java +++ /dev/null @@ -1,23 +0,0 @@ -public class test_init { - - public static void main(String[] argv) - { - char [] str = new char[10]; - str[0] = 'H'; - str[1] = 'e'; - str[2] = 'l'; - str[3] = 'l'; - str[4] = 'o'; - String s = new String(str); - String t = new String(str,1,2); - - System.out.println(s); - System.out.println(s.length()); - assert(s.startsWith("Hello")); - assert(s.length() == 10); - assert(t.equals("el")); - String u = String.valueOf(str,3,2); - assert(u.equals("lo")); - assert(s.equals("Hello") || !t.equals("el") || !u.equals("lo")); - } -} diff --git a/regression/strings/java_char_at/test.desc b/regression/strings/java_char_at/test.desc deleted file mode 100644 index 6f206a0f22f..00000000000 --- a/regression/strings/java_char_at/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -test_char_at.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_char_at.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_char_at.java line 13: FAILURE$ -^\[assertion.3\] assertion at file test_char_at.java line 15: SUCCESS$ --- diff --git a/regression/strings/java_char_at/test_char_at.class b/regression/strings/java_char_at/test_char_at.class deleted file mode 100644 index 7d1f07fad7d..00000000000 Binary files a/regression/strings/java_char_at/test_char_at.class and /dev/null differ diff --git a/regression/strings/java_char_at/test_char_at.java b/regression/strings/java_char_at/test_char_at.java deleted file mode 100644 index 337c6524099..00000000000 --- a/regression/strings/java_char_at/test_char_at.java +++ /dev/null @@ -1,17 +0,0 @@ -public class test_char_at { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - char c = s.charAt(4); - StringBuilder sb = new StringBuilder(s); - sb.setCharAt(5,'-'); - s = sb.toString(); - - if(argv.length==1) - assert(c == 'o'); - else if(argv.length==2) - assert(c == 'p'); - else - assert(s.equals("Hello-World!")); - } -} diff --git a/regression/strings/java_code_point/test.desc b/regression/strings/java_code_point/test.desc deleted file mode 100644 index 35ca0cd6f4b..00000000000 --- a/regression/strings/java_code_point/test.desc +++ /dev/null @@ -1,11 +0,0 @@ -FUTURE -test_code_point.class ---string-refine -^EXIT=0$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_code_point.java line 5: SUCCESS$ -^\[assertion.2\] assertion at file test_code_point.java line 6: SUCCESS$ -^\[assertion.3\] assertion at file test_code_point.java line 7: SUCCESS$ -^\[assertion.4\] assertion at file test_code_point.java line 8: SUCCESS$ -^\[assertion.5\] assertion at file test_code_point.java line 11: SUCCESS$ --- diff --git a/regression/strings/java_code_point/test_code_point.class b/regression/strings/java_code_point/test_code_point.class deleted file mode 100644 index c257f0633ec..00000000000 Binary files a/regression/strings/java_code_point/test_code_point.class and /dev/null differ diff --git a/regression/strings/java_code_point/test_code_point.java b/regression/strings/java_code_point/test_code_point.java deleted file mode 100644 index c27a56f575c..00000000000 --- a/regression/strings/java_code_point/test_code_point.java +++ /dev/null @@ -1,13 +0,0 @@ -public class test_code_point { - - public static void main(String[] argv) { - String s = "!𐤇𐤄𐤋𐤋𐤅"; - assert(s.codePointAt(1) == 67847); - assert(s.codePointBefore(3) == 67847); - assert(s.codePointCount(1,5) >= 2); - assert(s.offsetByCodePoints(1,2) >= 3); - StringBuilder sb = new StringBuilder(); - sb.appendCodePoint(0x10907); - assert(s.charAt(1) == sb.charAt(0)); - } -} diff --git a/regression/strings/java_compare/test.desc b/regression/strings/java_compare/test.desc deleted file mode 100644 index 517b208c3e4..00000000000 --- a/regression/strings/java_compare/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_compare.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_compare.java line 6: SUCCESS$ -^\[assertion.2\] assertion at file test_compare.java line 8: FAILURE$ -^\[assertion.3\] assertion at file test_compare.java line 11: SUCCESS$ -^\[assertion.4\] assertion at file test_compare.java line 12: FAILURE$ --- diff --git a/regression/strings/java_compare/test_compare.class b/regression/strings/java_compare/test_compare.class deleted file mode 100644 index 5616013c523..00000000000 Binary files a/regression/strings/java_compare/test_compare.class and /dev/null differ diff --git a/regression/strings/java_compare/test_compare.java b/regression/strings/java_compare/test_compare.java deleted file mode 100644 index 8c1d4b71a0c..00000000000 --- a/regression/strings/java_compare/test_compare.java +++ /dev/null @@ -1,18 +0,0 @@ -public class test_compare { - - public static void main(String[] argv) { - String s1 = "abc"; - String s2 = "aac"; - assert(s1.compareTo(s2) == 1); - - assert(s2.compareTo(argv[0]) != -1); - - String s3 = "abc"; - assert(s3.hashCode() == s1.hashCode()); - assert(s3.hashCode() == s2.hashCode()); - - /*String x = s1.intern(); - String y = s3.intern(); - assert(x == y);*/ - } -} diff --git a/regression/strings/java_concat/test.desc b/regression/strings/java_concat/test.desc deleted file mode 100644 index 8ef2898e0d7..00000000000 --- a/regression/strings/java_concat/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_concat.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_concat.java line 9: SUCCESS$ -^\[assertion.2\] assertion at file test_concat.java line 10: FAILURE$ --- diff --git a/regression/strings/java_concat/test_concat.class b/regression/strings/java_concat/test_concat.class deleted file mode 100644 index a6d4008aa26..00000000000 Binary files a/regression/strings/java_concat/test_concat.class and /dev/null differ diff --git a/regression/strings/java_concat/test_concat.java b/regression/strings/java_concat/test_concat.java deleted file mode 100644 index d714ea89538..00000000000 --- a/regression/strings/java_concat/test_concat.java +++ /dev/null @@ -1,12 +0,0 @@ -public class test_concat { - - public static void main(String[] argv) { - String s = new String("pi"); - int i = s.length(); - String t = new String("ppo"); - String u = s.concat(t); - char c = u.charAt(i); - assert(c == 'p'); - assert(c == 'o'); - } -} diff --git a/regression/strings/java_contains/test.desc b/regression/strings/java_contains/test.desc deleted file mode 100644 index 4e7a3bd4f7d..00000000000 --- a/regression/strings/java_contains/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_contains.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_contains.java line 7: SUCCESS$ -^\[assertion.2\] assertion at file test_contains.java line 8: FAILURE$ --- diff --git a/regression/strings/java_contains/test_contains.class b/regression/strings/java_contains/test_contains.class deleted file mode 100644 index 855ab828393..00000000000 Binary files a/regression/strings/java_contains/test_contains.class and /dev/null differ diff --git a/regression/strings/java_contains/test_contains.java b/regression/strings/java_contains/test_contains.java deleted file mode 100644 index fce2ee63047..00000000000 --- a/regression/strings/java_contains/test_contains.java +++ /dev/null @@ -1,10 +0,0 @@ -public class test_contains { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - String u = "o W"; - String t = "W o"; - assert(s.contains(u)); - assert(s.contains(t)); - } -} diff --git a/regression/strings/java_delete/test.desc b/regression/strings/java_delete/test.desc deleted file mode 100644 index c6c608c0955..00000000000 --- a/regression/strings/java_delete/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_delete.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_delete.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_delete.java line 12: FAILURE$ --- diff --git a/regression/strings/java_delete/test_delete.class b/regression/strings/java_delete/test_delete.class deleted file mode 100644 index 6d30024f108..00000000000 Binary files a/regression/strings/java_delete/test_delete.class and /dev/null differ diff --git a/regression/strings/java_delete/test_delete.java b/regression/strings/java_delete/test_delete.java deleted file mode 100644 index c91b16c5b89..00000000000 --- a/regression/strings/java_delete/test_delete.java +++ /dev/null @@ -1,15 +0,0 @@ -public class test_delete { - - public static void main(String[] argv) { - StringBuilder s = new StringBuilder(); - s.append("Hello World!"); - s.delete(4,6); - s.deleteCharAt(1); - - String str = s.toString(); - System.out.println(str); - assert(str.equals("HllWorld!")); - assert(!str.equals("HllWorld!")); - - } -} diff --git a/regression/strings/java_easychair/easychair.java b/regression/strings/java_easychair/easychair.java deleted file mode 100644 index 55ca2a31bb3..00000000000 --- a/regression/strings/java_easychair/easychair.java +++ /dev/null @@ -1,34 +0,0 @@ -public class easychair { - - public static void main(String[] argv) { - if(argv.length > 1){ - String str = new String(argv[1]); - if(str.length() < 40){ - - // containing "/" and containing "EasyChair" - int lastSlash = str.lastIndexOf('/'); - if(lastSlash < 0) return ; - - String rest = str.substring(lastSlash + 1); - // warning: removed this because contains is not efficient at the moment - if(! rest.contains("EasyChair")) return ; - // (2) Check that str starts with "http://" - if(! str.startsWith("http://")) return ; - // (3) Take the string between "http://" and the last "/". - // if it starts with "www." strip the "www." off - String t = str.substring("http://".length(),lastSlash - "http://".length()); - if(t.startsWith("www.")) - t = t.substring("www.".length()); - - // - //(4) Check that after stripping we have either "live.com" - // or "google.com" - if(!t.equals("live.com") && !t.equals("google.com")) - return ; - // s survived all checks - assert(false); //return true; - } - } - } - -} diff --git a/regression/strings/java_easychair/test.desc b/regression/strings/java_easychair/test.desc deleted file mode 100644 index 8680af72c5a..00000000000 --- a/regression/strings/java_easychair/test.desc +++ /dev/null @@ -1,7 +0,0 @@ -FUTURE -easychair.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file easychair.java line 29: FAILURE$ --- diff --git a/regression/strings/java_empty/test.desc b/regression/strings/java_empty/test.desc deleted file mode 100644 index cab514b80b5..00000000000 --- a/regression/strings/java_empty/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_empty.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_empty.java line 4: SUCCESS$ -^\[assertion.2\] assertion at file test_empty.java line 5: FAILURE$ --- diff --git a/regression/strings/java_empty/test_empty.class b/regression/strings/java_empty/test_empty.class deleted file mode 100644 index f0ced290ee3..00000000000 Binary files a/regression/strings/java_empty/test_empty.class and /dev/null differ diff --git a/regression/strings/java_empty/test_empty.java b/regression/strings/java_empty/test_empty.java deleted file mode 100644 index 2465fb16e41..00000000000 --- a/regression/strings/java_empty/test_empty.java +++ /dev/null @@ -1,7 +0,0 @@ -public class test_empty { - public static void main(String[] argv) { - String empty = " "; - assert(empty.trim().isEmpty()); - assert(empty.isEmpty()); - } -} diff --git a/regression/strings/java_equal/test.desc b/regression/strings/java_equal/test.desc deleted file mode 100644 index d66c30b26fe..00000000000 --- a/regression/strings/java_equal/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_equal.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_equal.java line 7: FAILURE$ -^\[assertion.2\] assertion at file test_equal.java line 8: SUCCESS$ --- diff --git a/regression/strings/java_equal/test_equal.java b/regression/strings/java_equal/test_equal.java deleted file mode 100644 index 151162a106d..00000000000 --- a/regression/strings/java_equal/test_equal.java +++ /dev/null @@ -1,10 +0,0 @@ -public class test_equal { - - public static void main(String[] argv) { - String s = new String("pi"); - String t = new String("po"); - String u = "po"; - assert(s.equals(t)); - assert(t.equals(u)); - } -} diff --git a/regression/strings/java_float/test.desc b/regression/strings/java_float/test.desc deleted file mode 100644 index 955f0358eab..00000000000 --- a/regression/strings/java_float/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_float.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_float.java line 14: SUCCESS$ -^\[assertion.2\] assertion at file test_float.java line 15: SUCCESS$ -^\[assertion.3\] assertion at file test_float.java line 16: SUCCESS$ -^\[assertion.4\] assertion at file test_float.java line 17: FAILURE$ --- diff --git a/regression/strings/java_float/test_float.java b/regression/strings/java_float/test_float.java deleted file mode 100644 index e59c631d91e..00000000000 --- a/regression/strings/java_float/test_float.java +++ /dev/null @@ -1,20 +0,0 @@ -public class test_float { - - public static void main(String[] arg) { - float inf = 100.0f / 0.0f; - float minus_inf = -100.0f / 0.0f; - float nan = 0.0f / 0.0f; - String inf_string = Float.toString(inf); - String mininf_string = Float.toString(minus_inf); - String nan_string = Float.toString(nan); - //String arg1 = arg[0]; - System.out.println(nan_string); - System.out.println(inf_string); - System.out.println(mininf_string); - assert(nan_string.equals("NaN")); - assert(inf_string.equals("Infinity")); - assert(mininf_string.equals("-Infinity")); - assert(!nan_string.equals("NaN") || !inf_string.equals("Infinity") - || !mininf_string.equals("-Infinity")); - } -} diff --git a/regression/strings/java_index_of/test.desc b/regression/strings/java_index_of/test.desc deleted file mode 100644 index daa6c32493b..00000000000 --- a/regression/strings/java_index_of/test.desc +++ /dev/null @@ -1,16 +0,0 @@ -FUTURE -test_index_of.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_index_of.java line 13: SUCCESS$ -^\[assertion.2\] assertion at file test_index_of.java line 14: FAILURE$ -^\[assertion.3\] assertion at file test_index_of.java line 17: SUCCESS$ -^\[assertion.4\] assertion at file test_index_of.java line 18: FAILURE$ -^\[assertion.5\] assertion at file test_index_of.java line 21: SUCCESS$ -^\[assertion.6\] assertion at file test_index_of.java line 22: FAILURE$ -^\[assertion.7\] assertion at file test_index_of.java line 25: SUCCESS$ -^\[assertion.8\] assertion at file test_index_of.java line 26: FAILURE$ -^\[assertion.9\] assertion at file test_index_of.java line 28: SUCCESS$ -^\[assertion.10\] assertion at file test_index_of.java line 29: SUCCESS$ --- diff --git a/regression/strings/java_index_of/test_index_of.class b/regression/strings/java_index_of/test_index_of.class deleted file mode 100644 index 8b3b7525f1a..00000000000 Binary files a/regression/strings/java_index_of/test_index_of.class and /dev/null differ diff --git a/regression/strings/java_index_of/test_index_of.java b/regression/strings/java_index_of/test_index_of.java deleted file mode 100644 index bbe06d279ec..00000000000 --- a/regression/strings/java_index_of/test_index_of.java +++ /dev/null @@ -1,32 +0,0 @@ -public class test_index_of { - - public static void main(String[] argv) { - String s = "Hello World!"; - char c = 'o'; - int i = s.indexOf(c); - int j = s.lastIndexOf('o'); - int k = s.indexOf(c,5); - int l = s.lastIndexOf(c,5); - int m = s.indexOf("lo"); - int n = s.lastIndexOf("lo"); - if(argv.length == 1){ - assert(i == 4); - assert(i != 4); - } - else if(argv.length == 2){ - assert(j == 7); - assert(j != 7); - } - else if(argv.length == 3){ - assert(k == 7); - assert(k != 7); - } - else if(argv.length == 4){ - assert(l == 4); - assert(l != 4); - } else { - assert(m != 2); - assert(n != 2); - } - } -} diff --git a/regression/strings/java_insert/test_insert.class b/regression/strings/java_insert/test_insert.class deleted file mode 100644 index 5fa0f425061..00000000000 Binary files a/regression/strings/java_insert/test_insert.class and /dev/null differ diff --git a/regression/strings/java_insert/test_insert.java b/regression/strings/java_insert/test_insert.java deleted file mode 100644 index 6871a51716c..00000000000 --- a/regression/strings/java_insert/test_insert.java +++ /dev/null @@ -1,19 +0,0 @@ -public class test_insert { - - public static void main(String[] argv) { - int i = 123; - long j = 123; - char c = '/'; - boolean b = true; - StringBuilder sb = new StringBuilder("hello"); - sb.insert(2,i); - sb.insert(2,c); - sb.insert(2,j); - sb.insert(2,b); - sb.insert(2,"abc"); - String s = sb.toString(); - System.out.println(s); - assert(s.equals("heabctrue123/123llo")); - assert(!s.equals("heabctrue123/123llo")); - } -} diff --git a/regression/strings/java_insert/test_insert1.class b/regression/strings/java_insert/test_insert1.class deleted file mode 100644 index 80091936cea..00000000000 Binary files a/regression/strings/java_insert/test_insert1.class and /dev/null differ diff --git a/regression/strings/java_insert/test_insert1.java b/regression/strings/java_insert/test_insert1.java deleted file mode 100644 index 54e754302c5..00000000000 --- a/regression/strings/java_insert/test_insert1.java +++ /dev/null @@ -1,23 +0,0 @@ -public class test_insert1 { - - public static void main(String[] argv) { - int i = 123; - long j = 123; - char c = '/'; - boolean b = true; - StringBuilder sb = new StringBuilder("hello"); - sb.insert(2,i); - - /* - sb.insert(2,c); - sb.insert(2,j); - sb.insert(2,b); - sb.insert(2,"abc"); - */ - String s = sb.toString(); - System.out.println(s); - assert(s.equals("he123llo")); - //assert(s.equals("heabctrue123/123llo")); - //assert(!s.equals("heabctrue123/123llo")); - } -} diff --git a/regression/strings/java_int/test.desc b/regression/strings/java_int/test.desc deleted file mode 100644 index ae60dd78af0..00000000000 --- a/regression/strings/java_int/test.desc +++ /dev/null @@ -1,13 +0,0 @@ -FUTURE -test_int.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_int.java line 8: SUCCESS$ -^\[assertion.2\] assertion at file test_int.java line 9: SUCCESS$ -^\[assertion.3\] assertion at file test_int.java line 12: SUCCESS$ -^\[assertion.4\] assertion at file test_int.java line 15: SUCCESS$ -^\[assertion.5\] assertion at file test_int.java line 18: SUCCESS$ -^\[assertion.6\] assertion at file test_int.java line 21: SUCCESS$ -^\[assertion.7\] assertion at file test_int.java line 23: FAILURE$ --- diff --git a/regression/strings/java_int/test_int.class b/regression/strings/java_int/test_int.class deleted file mode 100644 index 643d7eca09c..00000000000 Binary files a/regression/strings/java_int/test_int.class and /dev/null differ diff --git a/regression/strings/java_int/test_int.java b/regression/strings/java_int/test_int.java deleted file mode 100644 index 620ae638dce..00000000000 --- a/regression/strings/java_int/test_int.java +++ /dev/null @@ -1,25 +0,0 @@ -public class test_int { - - public static void main(String[] argv) { - String s = Integer.toString(2345); - char c = s.charAt(1); - char d = s.charAt(2); - char e = s.charAt(3); - assert(c == '3'); - assert(d == '4'); - - int i = Integer.parseInt("1234"); - assert(i == 1234); - - String t = Integer.toString(-2345); - assert(t.charAt(0) == '-'); - - int j = Integer.parseInt("-4231"); - assert(j == -4231); - - String u = Integer.toHexString(43981); - assert(u.equals("abcd")); - - assert(e == '2' || i < 1234 || t.charAt(0) != '-' || j != -4231 || !u.equals("abcd")); - } -} diff --git a/regression/strings/java_prefix/test.desc b/regression/strings/java_prefix/test.desc deleted file mode 100644 index 175f934ca1d..00000000000 --- a/regression/strings/java_prefix/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_prefix.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_prefix.java line 14: SUCCESS$ -^\[assertion.2\] assertion at file test_prefix.java line 16: FAILURE$ -^\[assertion.3\] assertion at file test_prefix.java line 18: SUCCESS$ -^\[assertion.4\] assertion at file test_prefix.java line 20: FAILURE$ --- diff --git a/regression/strings/java_prefix/test_prefix.class b/regression/strings/java_prefix/test_prefix.class deleted file mode 100644 index 6f5f4025932..00000000000 Binary files a/regression/strings/java_prefix/test_prefix.class and /dev/null differ diff --git a/regression/strings/java_prefix/test_prefix.java b/regression/strings/java_prefix/test_prefix.java deleted file mode 100644 index c9b5fa72fcf..00000000000 --- a/regression/strings/java_prefix/test_prefix.java +++ /dev/null @@ -1,23 +0,0 @@ -public class test_prefix { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - //String t = new String("Hello"); - //String u = new String("Wello"); - String u = "Wello"; - boolean b = s.startsWith("Hello"); - //boolean c = s.startsWith("Wello"); - //boolean b = s.startsWith(t); - boolean c = s.startsWith(u); - boolean d = s.startsWith("lo",3); - if(argv.length == 1){ - assert(b); - } else if(argv.length == 2){ - assert(c); - } else if(argv.length == 3){ - assert(d); - } else if(argv.length == 4){ - assert(!d); - } - } -} diff --git a/regression/strings/java_replace/test.desc b/regression/strings/java_replace/test.desc deleted file mode 100644 index 1e89ebe37b4..00000000000 --- a/regression/strings/java_replace/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_replace.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_replace.java line 6: SUCCESS$ -^\[assertion.2\] assertion at file test_replace.java line 8: FAILURE$ --- diff --git a/regression/strings/java_replace/test_replace.class b/regression/strings/java_replace/test_replace.class deleted file mode 100644 index c795826dc15..00000000000 Binary files a/regression/strings/java_replace/test_replace.class and /dev/null differ diff --git a/regression/strings/java_replace/test_replace.java b/regression/strings/java_replace/test_replace.java deleted file mode 100644 index 342bf9afddc..00000000000 --- a/regression/strings/java_replace/test_replace.java +++ /dev/null @@ -1,10 +0,0 @@ -public class test_replace { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - String t = s.replace('o','u'); - assert(t.equals("Hellu Wurld!")); - System.out.println(t); - assert(!t.equals("Hellu Wurld!")); - } -} diff --git a/regression/strings/java_set_length/test.desc b/regression/strings/java_set_length/test.desc deleted file mode 100644 index 43f82a648fd..00000000000 --- a/regression/strings/java_set_length/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -test_set_length.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_set_length.java line 8: SUCCESS$ -^\[assertion.2\] assertion at file test_set_length.java line 9: SUCCESS$ -^\[assertion.3\] assertion at file test_set_length.java line 10: FAILURE$ --- diff --git a/regression/strings/java_set_length/test_set_length.class b/regression/strings/java_set_length/test_set_length.class deleted file mode 100644 index 8836640967a..00000000000 Binary files a/regression/strings/java_set_length/test_set_length.class and /dev/null differ diff --git a/regression/strings/java_set_length/test_set_length.java b/regression/strings/java_set_length/test_set_length.java deleted file mode 100644 index 97b20f2332d..00000000000 --- a/regression/strings/java_set_length/test_set_length.java +++ /dev/null @@ -1,12 +0,0 @@ -public class test_set_length { - - public static void main(String[] argv) { - - StringBuilder s = new StringBuilder("abc"); - s.setLength(10); - String t = s.toString(); - assert(t.startsWith("abc")); - assert(t.length() == 10); - assert(t.length() == 3); - } -} diff --git a/regression/strings/java_string_builder/test.desc b/regression/strings/java_string_builder/test.desc deleted file mode 100644 index 9712205b104..00000000000 --- a/regression/strings/java_string_builder/test.desc +++ /dev/null @@ -1,9 +0,0 @@ -FUTURE -test_string_builder.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_string_builder.java line 11: SUCCESS$ -^\[assertion.2\] assertion at file test_string_builder.java line 12: SUCCESS$ -^\[assertion.3\] assertion at file test_string_builder.java line 13: FAILURE$ --- diff --git a/regression/strings/java_string_builder/test_string_builder.class b/regression/strings/java_string_builder/test_string_builder.class deleted file mode 100644 index 7a61d1f02be..00000000000 Binary files a/regression/strings/java_string_builder/test_string_builder.class and /dev/null differ diff --git a/regression/strings/java_string_builder/test_string_builder.java b/regression/strings/java_string_builder/test_string_builder.java deleted file mode 100644 index 1d76b34e9f8..00000000000 --- a/regression/strings/java_string_builder/test_string_builder.java +++ /dev/null @@ -1,16 +0,0 @@ -public class test_string_builder { - public static void main(String[] argv) { - if(argv.length > 2) { - StringBuilder tmp = new StringBuilder(); - tmp.append("prefix "); - tmp.append(argv[1]); - tmp.append(" middle ").append(argv[2]).append(" end"); - //StringBuilder tmp1 = tmp.append(argv[2]); - //tmp1.append(" end"); - String r = tmp.toString(); - assert(r.startsWith("pref")); - assert(r.endsWith("end")); - assert(r.startsWith("pr3f")); - } - } -} diff --git a/regression/strings/java_string_builder_insert/test.desc b/regression/strings/java_string_builder_insert/test.desc deleted file mode 100644 index 2655f846da1..00000000000 --- a/regression/strings/java_string_builder_insert/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_insert.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_insert.java line 17: SUCCESS$ -^\[assertion.2\] assertion at file test_insert.java line 18: FAILURE$ --- diff --git a/regression/strings/java_string_builder_insert/test_insert.class b/regression/strings/java_string_builder_insert/test_insert.class deleted file mode 100644 index 69a32d7f93f..00000000000 Binary files a/regression/strings/java_string_builder_insert/test_insert.class and /dev/null differ diff --git a/regression/strings/java_string_builder_insert/test_insert.java b/regression/strings/java_string_builder_insert/test_insert.java deleted file mode 100644 index 1fac897c5ed..00000000000 --- a/regression/strings/java_string_builder_insert/test_insert.java +++ /dev/null @@ -1,20 +0,0 @@ -public class test_insert { - - public static void main(String[] argv) - { - char [] str = new char[5]; - str[0] = 'H'; - str[1] = 'e'; - str[2] = 'l'; - str[3] = 'l'; - str[4] = 'o'; - - - StringBuilder sb = new StringBuilder(" world"); - sb.insert(0,str); - String s = sb.toString(); - System.out.println(s); - assert(s.equals("Hello world")); - assert(!s.equals("Hello world")); - } -} diff --git a/regression/strings/java_string_builder_length/test.desc b/regression/strings/java_string_builder_length/test.desc deleted file mode 100644 index c4720992571..00000000000 --- a/regression/strings/java_string_builder_length/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_sb_length.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -\[assertion.1\] assertion at file test_sb_length.java line 6: SUCCESS$ -\[assertion.2\] assertion at file test_sb_length.java line 8: FAILURE$ --- diff --git a/regression/strings/java_string_builder_length/test_sb_length.class b/regression/strings/java_string_builder_length/test_sb_length.class deleted file mode 100644 index 586e8f71935..00000000000 Binary files a/regression/strings/java_string_builder_length/test_sb_length.class and /dev/null differ diff --git a/regression/strings/java_string_builder_length/test_sb_length.java b/regression/strings/java_string_builder_length/test_sb_length.java deleted file mode 100644 index 652b72cdc90..00000000000 --- a/regression/strings/java_string_builder_length/test_sb_length.java +++ /dev/null @@ -1,11 +0,0 @@ -public class test_sb_length { - public static void main(String[] argv) { - StringBuilder tmp = new StringBuilder("prefix"); - //tmp.append("prefix"); - tmp.append("end"); - assert(tmp.length() == 9); - if(argv.length > 1) { - assert(tmp.length() == 12); - } - } -} diff --git a/regression/strings/java_strlen/test.desc b/regression/strings/java_strlen/test.desc deleted file mode 100644 index b98e6f76f0a..00000000000 --- a/regression/strings/java_strlen/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_length.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_length.java line 10: SUCCESS$ -^\[assertion.2\] assertion at file test_length.java line 11: FAILURE$ --- diff --git a/regression/strings/java_strlen/test_length.class b/regression/strings/java_strlen/test_length.class deleted file mode 100644 index 7f1c10c02ca..00000000000 Binary files a/regression/strings/java_strlen/test_length.class and /dev/null differ diff --git a/regression/strings/java_strlen/test_length.java b/regression/strings/java_strlen/test_length.java deleted file mode 100644 index 9410315db38..00000000000 --- a/regression/strings/java_strlen/test_length.java +++ /dev/null @@ -1,14 +0,0 @@ -public class test_length { - - public static void main(String[] argv) { - String s = new String("hello"); - if(argv.length > 1) { - String t = argv[1]; - int i = t.length(); - String u = t.concat(s); - char c = u.charAt(i); - assert(c == 'h'); - assert(c == 'o'); - } - } -} diff --git a/regression/strings/java_substring/test.desc b/regression/strings/java_substring/test.desc deleted file mode 100644 index bd54a8204fe..00000000000 --- a/regression/strings/java_substring/test.desc +++ /dev/null @@ -1,10 +0,0 @@ -FUTURE -test_substring.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_substring.java line 12: SUCCESS$ -^\[assertion.2\] assertion at file test_substring.java line 13: FAILURE$ -^\[assertion.3\] assertion at file test_substring.java line 20: SUCCESS$ -^\[assertion.4\] assertion at file test_substring.java line 21: FAILURE$ --- diff --git a/regression/strings/java_substring/test_substring.class b/regression/strings/java_substring/test_substring.class deleted file mode 100644 index e6532aca43e..00000000000 Binary files a/regression/strings/java_substring/test_substring.class and /dev/null differ diff --git a/regression/strings/java_substring/test_substring.java b/regression/strings/java_substring/test_substring.java deleted file mode 100644 index 8a2ac883cca..00000000000 --- a/regression/strings/java_substring/test_substring.java +++ /dev/null @@ -1,27 +0,0 @@ -public class test_substring { - - public static void main(String[] argv) { - if(argv.length > 1) { - String t = argv[1]; - - if(t.length() == 6) { - String u = t.substring(2,4); - char c = u.charAt(1); - char d = t.charAt(3); - char e = t.charAt(4); - assert(c == d); - assert(c == e); - } - else if(t.length() == 5){ - CharSequence u = t.subSequence(2,4); - char c = u.charAt(1); - char d = t.charAt(3); - char e = t.charAt(4); - assert(c == d); - assert(c == e); - } - - - } - } -} diff --git a/regression/strings/java_suffix/test.desc b/regression/strings/java_suffix/test.desc deleted file mode 100644 index 2740e87d6e4..00000000000 --- a/regression/strings/java_suffix/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_suffix.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_suffix.java line 12: SUCCESS$ -^\[assertion.2\] assertion at file test_suffix.java line 13: FAILURE$ --- diff --git a/regression/strings/java_suffix/test_suffix.class b/regression/strings/java_suffix/test_suffix.class deleted file mode 100644 index 557acd02653..00000000000 Binary files a/regression/strings/java_suffix/test_suffix.class and /dev/null differ diff --git a/regression/strings/java_suffix/test_suffix.java b/regression/strings/java_suffix/test_suffix.java deleted file mode 100644 index f61b0b8ba36..00000000000 --- a/regression/strings/java_suffix/test_suffix.java +++ /dev/null @@ -1,15 +0,0 @@ -public class test_suffix { - - public static void main(String[] argv) { - String s = new String("Hello World!"); - //String t = new String("Hello"); - //String u = new String("Wello"); - String u = "Wello!"; - boolean b = s.endsWith("World!"); - //boolean c = s.startsWith("Wello"); - //boolean b = s.startsWith(t); - boolean c = s.startsWith(u); - assert(b); - assert(c); - } -} diff --git a/regression/strings/java_trim/test.desc b/regression/strings/java_trim/test.desc deleted file mode 100644 index 7c0f1a87978..00000000000 --- a/regression/strings/java_trim/test.desc +++ /dev/null @@ -1,8 +0,0 @@ -FUTURE -test_trim.class ---string-refine -^EXIT=10$ -^SIGNAL=0$ -^\[assertion.1\] assertion at file test_trim.java line 5: SUCCESS$ -^\[assertion.2\] assertion at file test_trim.java line 6: FAILURE$ --- diff --git a/regression/strings/java_trim/test_trim.class b/regression/strings/java_trim/test_trim.class deleted file mode 100644 index 8e6a923dcbc..00000000000 Binary files a/regression/strings/java_trim/test_trim.class and /dev/null differ diff --git a/regression/strings/java_trim/test_trim.java b/regression/strings/java_trim/test_trim.java deleted file mode 100644 index 8d8d41cb29a..00000000000 --- a/regression/strings/java_trim/test_trim.java +++ /dev/null @@ -1,8 +0,0 @@ -public class test_trim { - public static void main(String[] argv) { - String t = " a b c "; - String x = t.trim(); - assert(x.equals("a b c")); - assert(x.equals("abc ")); - } -} diff --git a/regression/strings/performance_tests/Makefile b/regression/strings/performance_tests/Makefile new file mode 100644 index 00000000000..185be13bd7b --- /dev/null +++ b/regression/strings/performance_tests/Makefile @@ -0,0 +1,9 @@ + +test: + @../../test.pl -c ../../../../src/cbmc/cbmc + +testfuture: + @../../test.pl -c ../../../../src/cbmc/cbmc -CF + +testall: + @../../test.pl -c ../../../../src/cbmc/cbmc -CFTK diff --git a/regression/strings/performance_tests/java_append_char/test.desc b/regression/strings/performance_tests/java_append_char/test.desc new file mode 100644 index 00000000000..98e40b87b87 --- /dev/null +++ b/regression/strings/performance_tests/java_append_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_char.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 15.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_append_char/test_append_char.class b/regression/strings/performance_tests/java_append_char/test_append_char.class new file mode 100644 index 00000000000..c0b1491423b Binary files /dev/null and b/regression/strings/performance_tests/java_append_char/test_append_char.class differ diff --git a/regression/strings/performance_tests/java_append_char/test_append_char.java b/regression/strings/performance_tests/java_append_char/test_append_char.java new file mode 100644 index 00000000000..90e9ab089a2 --- /dev/null +++ b/regression/strings/performance_tests/java_append_char/test_append_char.java @@ -0,0 +1,17 @@ +public class test_append_char +{ + public static void main(/*String[] args*/) + { + char[] diff = {'d', 'i', 'f', 'f'}; + char[] blue = {'b', 'l', 'u', 'e'}; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert(!tmp.equals("diffblue")); + } +} diff --git a/regression/strings/performance_tests/java_append_int/test.desc b/regression/strings/performance_tests/java_append_int/test.desc new file mode 100644 index 00000000000..32659f65d7b --- /dev/null +++ b/regression/strings/performance_tests/java_append_int/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_int.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_append_int/test_append_int.class b/regression/strings/performance_tests/java_append_int/test_append_int.class new file mode 100644 index 00000000000..d9ee5046e7d Binary files /dev/null and b/regression/strings/performance_tests/java_append_int/test_append_int.class differ diff --git a/regression/strings/performance_tests/java_append_int/test_append_int.java b/regression/strings/performance_tests/java_append_int/test_append_int.java new file mode 100644 index 00000000000..cf550211ad7 --- /dev/null +++ b/regression/strings/performance_tests/java_append_int/test_append_int.java @@ -0,0 +1,11 @@ +public class test_append_int +{ + public static void main(/*String[] args*/) + { + StringBuilder diffblue = new StringBuilder(); + diffblue.append("d"); + diffblue.append(4); + String s = diffblue.toString(); + assert(!s.equals("d4")); + } +} diff --git a/regression/strings/performance_tests/java_append_object/test.desc b/regression/strings/performance_tests/java_append_object/test.desc new file mode 100644 index 00000000000..cdfe4e20ecd --- /dev/null +++ b/regression/strings/performance_tests/java_append_object/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_object.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 15.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_append_object/test_append_object.class b/regression/strings/performance_tests/java_append_object/test_append_object.class new file mode 100644 index 00000000000..fbfec51a3f5 Binary files /dev/null and b/regression/strings/performance_tests/java_append_object/test_append_object.class differ diff --git a/regression/strings/performance_tests/java_append_object/test_append_object.java b/regression/strings/performance_tests/java_append_object/test_append_object.java new file mode 100644 index 00000000000..e139a01679a --- /dev/null +++ b/regression/strings/performance_tests/java_append_object/test_append_object.java @@ -0,0 +1,17 @@ +public class test_append_object +{ + public static void main(/*String[] args*/) + { + Object diff = "diff"; + Object blue = "blue"; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert(!tmp.equals("diffblue")); + } +} diff --git a/regression/strings/performance_tests/java_append_string/test.desc b/regression/strings/performance_tests/java_append_string/test.desc new file mode 100644 index 00000000000..ed5b593bd66 --- /dev/null +++ b/regression/strings/performance_tests/java_append_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_string.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 12.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_append_string/test_append_string.class b/regression/strings/performance_tests/java_append_string/test_append_string.class new file mode 100644 index 00000000000..f2cb5cf8bea Binary files /dev/null and b/regression/strings/performance_tests/java_append_string/test_append_string.class differ diff --git a/regression/strings/performance_tests/java_append_string/test_append_string.java b/regression/strings/performance_tests/java_append_string/test_append_string.java new file mode 100644 index 00000000000..54665da29cc --- /dev/null +++ b/regression/strings/performance_tests/java_append_string/test_append_string.java @@ -0,0 +1,14 @@ +public class test_append_string +{ + public static void main(/*String[] args*/) + { + String di = new String("di"); + StringBuilder diff = new StringBuilder(); + diff.append(di); + diff.append("ff"); + System.out.println(diff); + String s = diff.toString(); + System.out.println(s); + assert (!s.equals("diff")); + } +} diff --git a/regression/strings/performance_tests/java_case/test.desc b/regression/strings/performance_tests/java_case/test.desc new file mode 100644 index 00000000000..9a90f47dafc --- /dev/null +++ b/regression/strings/performance_tests/java_case/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_case.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_case/test_case.class b/regression/strings/performance_tests/java_case/test_case.class new file mode 100644 index 00000000000..5887b496986 Binary files /dev/null and b/regression/strings/performance_tests/java_case/test_case.class differ diff --git a/regression/strings/performance_tests/java_case/test_case.java b/regression/strings/performance_tests/java_case/test_case.java new file mode 100644 index 00000000000..309abfc07b9 --- /dev/null +++ b/regression/strings/performance_tests/java_case/test_case.java @@ -0,0 +1,12 @@ +public class test_case +{ + public static void main(/*String[] argv*/) + { + String s = new String("Ab"); + String l = s.toLowerCase(); + String u = s.toUpperCase(); + assert(!l.equals("ab") || + !u.equals("AB") || + !s.equalsIgnoreCase("aB")); + } +} diff --git a/regression/strings/performance_tests/java_char_array/test.desc b/regression/strings/performance_tests/java_char_array/test.desc new file mode 100644 index 00000000000..bf03b8ecf4f --- /dev/null +++ b/regression/strings/performance_tests/java_char_array/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_char_array.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_char_array/test_char_array.class b/regression/strings/performance_tests/java_char_array/test_char_array.class new file mode 100644 index 00000000000..38a7ecf41ed Binary files /dev/null and b/regression/strings/performance_tests/java_char_array/test_char_array.class differ diff --git a/regression/strings/performance_tests/java_char_array/test_char_array.java b/regression/strings/performance_tests/java_char_array/test_char_array.java new file mode 100644 index 00000000000..96e250fb030 --- /dev/null +++ b/regression/strings/performance_tests/java_char_array/test_char_array.java @@ -0,0 +1,13 @@ +public class test_char_array +{ + public static void main(/*String[] argv*/) + { + String s = "abc"; + char [] str = s.toCharArray(); + char c = str[2]; + char a = s.charAt(0); + assert(str.length != 3 || + a != 'a' || + c != 'c'); + } +} diff --git a/regression/strings/performance_tests/java_char_array_init/test.desc b/regression/strings/performance_tests/java_char_array_init/test.desc new file mode 100644 index 00000000000..e3d08208c4e --- /dev/null +++ b/regression/strings/performance_tests/java_char_array_init/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_init.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 14.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_char_array_init/test_init.class b/regression/strings/performance_tests/java_char_array_init/test_init.class new file mode 100644 index 00000000000..ff9c64510da Binary files /dev/null and b/regression/strings/performance_tests/java_char_array_init/test_init.class differ diff --git a/regression/strings/performance_tests/java_char_array_init/test_init.java b/regression/strings/performance_tests/java_char_array_init/test_init.java new file mode 100644 index 00000000000..b27030b1306 --- /dev/null +++ b/regression/strings/performance_tests/java_char_array_init/test_init.java @@ -0,0 +1,18 @@ +public class test_init { + + public static void main(/*String[] argv*/) + { + char [] str = new char[10]; + str[0] = 'H'; + str[1] = 'e'; + str[2] = 'l'; + str[3] = 'l'; + str[4] = 'o'; + String s = new String(str); + String t = new String(str,1,2); + + assert(s.length() != 10 || + !t.equals("el") || + !s.startsWith("Hello")); + } +} diff --git a/regression/strings/performance_tests/java_char_at/test.desc b/regression/strings/performance_tests/java_char_at/test.desc new file mode 100644 index 00000000000..477c006b597 --- /dev/null +++ b/regression/strings/performance_tests/java_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_char_at.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 5.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_char_at/test_char_at.class b/regression/strings/performance_tests/java_char_at/test_char_at.class new file mode 100644 index 00000000000..dc9ed32f19f Binary files /dev/null and b/regression/strings/performance_tests/java_char_at/test_char_at.class differ diff --git a/regression/strings/performance_tests/java_char_at/test_char_at.java b/regression/strings/performance_tests/java_char_at/test_char_at.java new file mode 100644 index 00000000000..9ae02733fb8 --- /dev/null +++ b/regression/strings/performance_tests/java_char_at/test_char_at.java @@ -0,0 +1,7 @@ +public class test_char_at { + + public static void main(/*String[] argv*/) { + String s = new String("abc"); + assert(s.charAt(2)!='c'); + } +} diff --git a/regression/strings/performance_tests/java_code_point/test.desc b/regression/strings/performance_tests/java_code_point/test.desc new file mode 100644 index 00000000000..d10b960e1d9 --- /dev/null +++ b/regression/strings/performance_tests/java_code_point/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_code_point.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_code_point/test_code_point.class b/regression/strings/performance_tests/java_code_point/test_code_point.class new file mode 100644 index 00000000000..f2f5fbad63a Binary files /dev/null and b/regression/strings/performance_tests/java_code_point/test_code_point.class differ diff --git a/regression/strings/performance_tests/java_code_point/test_code_point.java b/regression/strings/performance_tests/java_code_point/test_code_point.java new file mode 100644 index 00000000000..345dc1fa08b --- /dev/null +++ b/regression/strings/performance_tests/java_code_point/test_code_point.java @@ -0,0 +1,14 @@ +public class test_code_point +{ + public static void main(/*String[] argv*/) + { + String s = "!𐤇𐤄𐤋𐤋𐤅"; + StringBuilder sb = new StringBuilder(); + sb.appendCodePoint(0x10907); + assert(s.codePointAt(1) != 67847 || + s.codePointBefore(3) != 67847 || + s.codePointCount(1,5) < 2 || + s.offsetByCodePoints(1,2) < 3 || + s.charAt(1) != sb.charAt(0)); + } +} diff --git a/regression/strings/performance_tests/java_compare/test.desc b/regression/strings/performance_tests/java_compare/test.desc new file mode 100644 index 00000000000..351eb7f4536 --- /dev/null +++ b/regression/strings/performance_tests/java_compare/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_compare.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_compare/test_compare.class b/regression/strings/performance_tests/java_compare/test_compare.class new file mode 100644 index 00000000000..67f18914ea6 Binary files /dev/null and b/regression/strings/performance_tests/java_compare/test_compare.class differ diff --git a/regression/strings/performance_tests/java_compare/test_compare.java b/regression/strings/performance_tests/java_compare/test_compare.java new file mode 100644 index 00000000000..0a535fd0bf3 --- /dev/null +++ b/regression/strings/performance_tests/java_compare/test_compare.java @@ -0,0 +1,9 @@ +public class test_compare +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "aa"; + assert(s1.compareTo(s2) != 1); + } +} diff --git a/regression/strings/performance_tests/java_concat/test.desc b/regression/strings/performance_tests/java_concat/test.desc new file mode 100644 index 00000000000..9bfb8fb9ced --- /dev/null +++ b/regression/strings/performance_tests/java_concat/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_concat.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 10.* SUCCESS$ +^\[.*assertion.2\].* line 11.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_concat/test_concat.class b/regression/strings/performance_tests/java_concat/test_concat.class new file mode 100644 index 00000000000..a69c05921f6 Binary files /dev/null and b/regression/strings/performance_tests/java_concat/test_concat.class differ diff --git a/regression/strings/performance_tests/java_concat/test_concat.java b/regression/strings/performance_tests/java_concat/test_concat.java new file mode 100644 index 00000000000..6bbe753b2e4 --- /dev/null +++ b/regression/strings/performance_tests/java_concat/test_concat.java @@ -0,0 +1,13 @@ +public class test_concat +{ + public static void main(/*String[] argv*/) + { + String s = new String("pi"); + int i = s.length(); + String t = new String("ppo"); + String u = s.concat(t); + char c = u.charAt(i); + assert(c == 'p'); + assert(c != 'p'); + } +} diff --git a/regression/strings/performance_tests/java_contains/test.desc b/regression/strings/performance_tests/java_contains/test.desc new file mode 100644 index 00000000000..95576273607 --- /dev/null +++ b/regression/strings/performance_tests/java_contains/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_contains.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_contains/test_contains.class b/regression/strings/performance_tests/java_contains/test_contains.class new file mode 100644 index 00000000000..9bbccb03775 Binary files /dev/null and b/regression/strings/performance_tests/java_contains/test_contains.class differ diff --git a/regression/strings/performance_tests/java_contains/test_contains.java b/regression/strings/performance_tests/java_contains/test_contains.java new file mode 100644 index 00000000000..6f4c60a1a2e --- /dev/null +++ b/regression/strings/performance_tests/java_contains/test_contains.java @@ -0,0 +1,9 @@ +public class test_contains +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + String u = "bc"; + assert(!s.contains(u)); + } +} diff --git a/regression/strings/performance_tests/java_delete/test.desc b/regression/strings/performance_tests/java_delete/test.desc new file mode 100644 index 00000000000..0ac1a72411b --- /dev/null +++ b/regression/strings/performance_tests/java_delete/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_delete/test_delete.class b/regression/strings/performance_tests/java_delete/test_delete.class new file mode 100644 index 00000000000..7036ce13c90 Binary files /dev/null and b/regression/strings/performance_tests/java_delete/test_delete.class differ diff --git a/regression/strings/performance_tests/java_delete/test_delete.java b/regression/strings/performance_tests/java_delete/test_delete.java new file mode 100644 index 00000000000..ea846cd215a --- /dev/null +++ b/regression/strings/performance_tests/java_delete/test_delete.java @@ -0,0 +1,10 @@ +public class test_delete +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder("Abc"); + s.delete(1,2); + String str = s.toString(); + assert(!str.equals("Ac")); + } +} diff --git a/regression/strings/performance_tests/java_delete_char_at/test.desc b/regression/strings/performance_tests/java_delete_char_at/test.desc new file mode 100644 index 00000000000..8dc189360ff --- /dev/null +++ b/regression/strings/performance_tests/java_delete_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete_char_at.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_delete_char_at/test_delete_char_at.class b/regression/strings/performance_tests/java_delete_char_at/test_delete_char_at.class new file mode 100644 index 00000000000..ed3148e2f7e Binary files /dev/null and b/regression/strings/performance_tests/java_delete_char_at/test_delete_char_at.class differ diff --git a/regression/strings/performance_tests/java_delete_char_at/test_delete_char_at.java b/regression/strings/performance_tests/java_delete_char_at/test_delete_char_at.java new file mode 100644 index 00000000000..5f2c995b56b --- /dev/null +++ b/regression/strings/performance_tests/java_delete_char_at/test_delete_char_at.java @@ -0,0 +1,11 @@ +public class test_delete_char_at +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder(); + s.append("Abc"); + s.deleteCharAt(1); + String str = s.toString(); + assert(!str.equals("Ac")); + } +} diff --git a/regression/strings/java_easychair/easychair.class b/regression/strings/performance_tests/java_easychair/easychair.class similarity index 84% rename from regression/strings/java_easychair/easychair.class rename to regression/strings/performance_tests/java_easychair/easychair.class index e47900cc0b2..e6c5f66c42d 100644 Binary files a/regression/strings/java_easychair/easychair.class and b/regression/strings/performance_tests/java_easychair/easychair.class differ diff --git a/regression/strings/performance_tests/java_easychair/easychair.java b/regression/strings/performance_tests/java_easychair/easychair.java new file mode 100644 index 00000000000..caed962fb46 --- /dev/null +++ b/regression/strings/performance_tests/java_easychair/easychair.java @@ -0,0 +1,34 @@ +public class easychair +{ + public static void main(String[] argv) + { + if(argv.length > 1) + { + String str = new String(argv[1]); + if(str.length() < 40) + { + // containing "/" and containing "EasyChair" + int lastSlash = str.lastIndexOf('/'); + if(lastSlash < 0) return ; + + String rest = str.substring(lastSlash + 1); + // warning: removed this because contains is not efficient at the moment + if(! rest.contains("EasyChair")) return ; + // (2) Check that str starts with "http://" + if(! str.startsWith("http://")) return ; + // (3) Take the string between "http://" and the last "/". + // if it starts with "www." strip the "www." off + String t = str.substring("http://".length(),lastSlash - "http://".length()); + if(t.startsWith("www.")) + t = t.substring("www.".length()); + + //(4) Check that after stripping we have either "live.com" + // or "google.com" + if(!t.equals("live.com") && !t.equals("google.com")) + return ; + // s survived all checks + assert(false); //return true; + } + } + } +} diff --git a/regression/strings/performance_tests/java_easychair/test.desc b/regression/strings/performance_tests/java_easychair/test.desc new file mode 100644 index 00000000000..a7fff1aa0ac --- /dev/null +++ b/regression/strings/performance_tests/java_easychair/test.desc @@ -0,0 +1,7 @@ +THOROUGH +easychair.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 30.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_empty/test.desc b/regression/strings/performance_tests/java_empty/test.desc new file mode 100644 index 00000000000..eabc07fed57 --- /dev/null +++ b/regression/strings/performance_tests/java_empty/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_empty.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 6.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_empty/test_empty.class b/regression/strings/performance_tests/java_empty/test_empty.class new file mode 100644 index 00000000000..147a2b628fe Binary files /dev/null and b/regression/strings/performance_tests/java_empty/test_empty.class differ diff --git a/regression/strings/performance_tests/java_empty/test_empty.java b/regression/strings/performance_tests/java_empty/test_empty.java new file mode 100644 index 00000000000..18fde4a115e --- /dev/null +++ b/regression/strings/performance_tests/java_empty/test_empty.java @@ -0,0 +1,8 @@ +public class test_empty +{ + public static void main(/*String[] argv*/) + { + String empty = ""; + assert(!empty.isEmpty()); + } +} diff --git a/regression/strings/performance_tests/java_endswith/test.desc b/regression/strings/performance_tests/java_endswith/test.desc new file mode 100644 index 00000000000..25f4b7cac14 --- /dev/null +++ b/regression/strings/performance_tests/java_endswith/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_endswith.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_endswith/test_endswith.class b/regression/strings/performance_tests/java_endswith/test_endswith.class new file mode 100644 index 00000000000..e3d453c444f Binary files /dev/null and b/regression/strings/performance_tests/java_endswith/test_endswith.class differ diff --git a/regression/strings/performance_tests/java_endswith/test_endswith.java b/regression/strings/performance_tests/java_endswith/test_endswith.java new file mode 100644 index 00000000000..fabf6f8dde0 --- /dev/null +++ b/regression/strings/performance_tests/java_endswith/test_endswith.java @@ -0,0 +1,9 @@ +public class test_endswith +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abcd"); + String suff = "cd"; + assert(!s.endsWith(suff)); + } +} diff --git a/regression/strings/performance_tests/java_equal/test.desc b/regression/strings/performance_tests/java_equal/test.desc new file mode 100644 index 00000000000..a72c9315fd2 --- /dev/null +++ b/regression/strings/performance_tests/java_equal/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_equal.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/java_equal/test_equal.class b/regression/strings/performance_tests/java_equal/test_equal.class similarity index 77% rename from regression/strings/java_equal/test_equal.class rename to regression/strings/performance_tests/java_equal/test_equal.class index 26ee19e6cb1..e0fc6db8aaf 100644 Binary files a/regression/strings/java_equal/test_equal.class and b/regression/strings/performance_tests/java_equal/test_equal.class differ diff --git a/regression/strings/performance_tests/java_equal/test_equal.java b/regression/strings/performance_tests/java_equal/test_equal.java new file mode 100644 index 00000000000..e8c9ac7cb1a --- /dev/null +++ b/regression/strings/performance_tests/java_equal/test_equal.java @@ -0,0 +1,9 @@ +public class test_equal +{ + public static void main(String[] argv) + { + String s = new String("pi"); + String t = new String("po"); + assert(!s.equals(t)); + } +} diff --git a/regression/strings/performance_tests/java_float/test.desc b/regression/strings/performance_tests/java_float/test.desc new file mode 100644 index 00000000000..4acb121e634 --- /dev/null +++ b/regression/strings/performance_tests/java_float/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_float.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 15.* FAILURE$ +-- diff --git a/regression/strings/java_float/test_float.class b/regression/strings/performance_tests/java_float/test_float.class similarity index 57% rename from regression/strings/java_float/test_float.class rename to regression/strings/performance_tests/java_float/test_float.class index 356d0e17871..00e8622e2ac 100644 Binary files a/regression/strings/java_float/test_float.class and b/regression/strings/performance_tests/java_float/test_float.class differ diff --git a/regression/strings/performance_tests/java_float/test_float.java b/regression/strings/performance_tests/java_float/test_float.java new file mode 100644 index 00000000000..312f1aeaf10 --- /dev/null +++ b/regression/strings/performance_tests/java_float/test_float.java @@ -0,0 +1,17 @@ +public class test_float +{ + public static void main(/*String[] arg*/) + { + float inf = 100.0f / 0.0f; + float minus_inf = -100.0f / 0.0f; + float nan = 0.0f / 0.0f; + String inf_string = Float.toString(inf); + String mininf_string = Float.toString(minus_inf); + String nan_string = Float.toString(nan); + System.out.println(nan_string); + System.out.println(inf_string); + System.out.println(mininf_string); + assert(!nan_string.equals("NaN") || !inf_string.equals("Infinity") + || !mininf_string.equals("-Infinity")); + } +} diff --git a/regression/strings/performance_tests/java_hash_code/test.desc b/regression/strings/performance_tests/java_hash_code/test.desc new file mode 100644 index 00000000000..313c5e4104c --- /dev/null +++ b/regression/strings/performance_tests/java_hash_code/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_hash_code.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_hash_code/test_hash_code.class b/regression/strings/performance_tests/java_hash_code/test_hash_code.class new file mode 100644 index 00000000000..d9b3e2b2f3d Binary files /dev/null and b/regression/strings/performance_tests/java_hash_code/test_hash_code.class differ diff --git a/regression/strings/performance_tests/java_hash_code/test_hash_code.java b/regression/strings/performance_tests/java_hash_code/test_hash_code.java new file mode 100644 index 00000000000..fbc15f0b4c2 --- /dev/null +++ b/regression/strings/performance_tests/java_hash_code/test_hash_code.java @@ -0,0 +1,9 @@ +public class test_hash_code +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "ab"; + assert(s1.hashCode() != s2.hashCode()); + } +} diff --git a/regression/strings/performance_tests/java_index_of/test.desc b/regression/strings/performance_tests/java_index_of/test.desc new file mode 100644 index 00000000000..2651a60d73f --- /dev/null +++ b/regression/strings/performance_tests/java_index_of/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_index_of/test_index_of.class b/regression/strings/performance_tests/java_index_of/test_index_of.class new file mode 100644 index 00000000000..cae397a79fb Binary files /dev/null and b/regression/strings/performance_tests/java_index_of/test_index_of.class differ diff --git a/regression/strings/performance_tests/java_index_of/test_index_of.java b/regression/strings/performance_tests/java_index_of/test_index_of.java new file mode 100644 index 00000000000..b607ba79570 --- /dev/null +++ b/regression/strings/performance_tests/java_index_of/test_index_of.java @@ -0,0 +1,10 @@ +public class test_index_of +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + String bc = "bc"; + int i = s.indexOf(bc); + assert(i != 1); + } +} diff --git a/regression/strings/performance_tests/java_index_of_char/test.desc b/regression/strings/performance_tests/java_index_of_char/test.desc new file mode 100644 index 00000000000..e1159295558 --- /dev/null +++ b/regression/strings/performance_tests/java_index_of_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of_char.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_index_of_char/test_index_of_char.class b/regression/strings/performance_tests/java_index_of_char/test_index_of_char.class new file mode 100644 index 00000000000..bf4fa6e946e Binary files /dev/null and b/regression/strings/performance_tests/java_index_of_char/test_index_of_char.class differ diff --git a/regression/strings/performance_tests/java_index_of_char/test_index_of_char.java b/regression/strings/performance_tests/java_index_of_char/test_index_of_char.java new file mode 100644 index 00000000000..92d75b3b07d --- /dev/null +++ b/regression/strings/performance_tests/java_index_of_char/test_index_of_char.java @@ -0,0 +1,10 @@ +public class test_index_of_char +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + char c = 'c'; + int i = s.indexOf(c); + assert(i != 2); + } +} diff --git a/regression/strings/performance_tests/java_insert_char/test.desc b/regression/strings/performance_tests/java_insert_char/test.desc new file mode 100644 index 00000000000..8056f171ad1 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_insert_char/test_insert_char.class b/regression/strings/performance_tests/java_insert_char/test_insert_char.class new file mode 100644 index 00000000000..fbf4a82070b Binary files /dev/null and b/regression/strings/performance_tests/java_insert_char/test_insert_char.class differ diff --git a/regression/strings/performance_tests/java_insert_char/test_insert_char.java b/regression/strings/performance_tests/java_insert_char/test_insert_char.java new file mode 100644 index 00000000000..3a83f03b332 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_char/test_insert_char.java @@ -0,0 +1,10 @@ +public class test_insert_char +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ac"); + sb.insert(1, 'b'); + String s = sb.toString(); + assert(!s.equals("abc")); + } +} diff --git a/regression/strings/performance_tests/java_insert_char_array/test.desc b/regression/strings/performance_tests/java_insert_char_array/test.desc new file mode 100644 index 00000000000..17d5e5da8d5 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_char_array/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char_array.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 12.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_insert_char_array/test_insert_char_array.class b/regression/strings/performance_tests/java_insert_char_array/test_insert_char_array.class new file mode 100644 index 00000000000..bc1a23a7496 Binary files /dev/null and b/regression/strings/performance_tests/java_insert_char_array/test_insert_char_array.class differ diff --git a/regression/strings/performance_tests/java_insert_char_array/test_insert_char_array.java b/regression/strings/performance_tests/java_insert_char_array/test_insert_char_array.java new file mode 100644 index 00000000000..079dbd2fee6 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_char_array/test_insert_char_array.java @@ -0,0 +1,14 @@ +public class test_insert_char_array +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + char[] array = new char[2]; + array[0] = 'b'; + array[1] = 'c'; + sb.insert(1, array); + String s = sb.toString(); + System.out.println(s); + assert(!s.equals("abcd")); + } +} diff --git a/regression/strings/performance_tests/java_insert_int/test.desc b/regression/strings/performance_tests/java_insert_int/test.desc new file mode 100644 index 00000000000..8158b444763 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_int/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_int.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_insert_int/test_insert_int.class b/regression/strings/performance_tests/java_insert_int/test_insert_int.class new file mode 100644 index 00000000000..cd355c86546 Binary files /dev/null and b/regression/strings/performance_tests/java_insert_int/test_insert_int.class differ diff --git a/regression/strings/performance_tests/java_insert_int/test_insert_int.java b/regression/strings/performance_tests/java_insert_int/test_insert_int.java new file mode 100644 index 00000000000..15a7a2d53f6 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_int/test_insert_int.java @@ -0,0 +1,10 @@ +public class test_insert_int +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ac"); + sb.insert(1, 42); + String s = sb.toString(); + assert(!s.equals("a42c")); + } +} diff --git a/regression/strings/performance_tests/java_insert_multiple/test.desc b/regression/strings/performance_tests/java_insert_multiple/test.desc new file mode 100644 index 00000000000..2aeab10a917 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_multiple/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_multiple.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_insert_multiple/test_insert_multiple.class b/regression/strings/performance_tests/java_insert_multiple/test_insert_multiple.class new file mode 100644 index 00000000000..d6b470a1f72 Binary files /dev/null and b/regression/strings/performance_tests/java_insert_multiple/test_insert_multiple.class differ diff --git a/regression/strings/performance_tests/java_insert_multiple/test_insert_multiple.java b/regression/strings/performance_tests/java_insert_multiple/test_insert_multiple.java new file mode 100644 index 00000000000..c976ddd807f --- /dev/null +++ b/regression/strings/performance_tests/java_insert_multiple/test_insert_multiple.java @@ -0,0 +1,11 @@ +public class test_insert_multiple +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, 'c'); + sb.insert(1, "b"); + String s = sb.toString(); + assert(!s.equals("abcd")); + } +} diff --git a/regression/strings/performance_tests/java_insert_string/test.desc b/regression/strings/performance_tests/java_insert_string/test.desc new file mode 100644 index 00000000000..4df1aeedf35 --- /dev/null +++ b/regression/strings/performance_tests/java_insert_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_string.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/performance_tests/java_insert_string/test_insert_string.class b/regression/strings/performance_tests/java_insert_string/test_insert_string.class new file mode 100644 index 00000000000..be8f7ad0f79 Binary files /dev/null and b/regression/strings/performance_tests/java_insert_string/test_insert_string.class differ diff --git a/regression/strings/performance_tests/java_insert_string/test_insert_string.java b/regression/strings/performance_tests/java_insert_string/test_insert_string.java new file mode 100644 index 00000000000..028a348122b --- /dev/null +++ b/regression/strings/performance_tests/java_insert_string/test_insert_string.java @@ -0,0 +1,10 @@ +public class test_insert_string +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, "bc"); + String s = sb.toString(); + assert(!s.equals("abcd")); + } +} diff --git a/regression/strings/smoke_tests/Makefile b/regression/strings/smoke_tests/Makefile new file mode 100644 index 00000000000..185be13bd7b --- /dev/null +++ b/regression/strings/smoke_tests/Makefile @@ -0,0 +1,9 @@ + +test: + @../../test.pl -c ../../../../src/cbmc/cbmc + +testfuture: + @../../test.pl -c ../../../../src/cbmc/cbmc -CF + +testall: + @../../test.pl -c ../../../../src/cbmc/cbmc -CFTK diff --git a/regression/strings/smoke_tests/java_append_char/test.desc b/regression/strings/smoke_tests/java_append_char/test.desc new file mode 100644 index 00000000000..afedb9a2fa0 --- /dev/null +++ b/regression/strings/smoke_tests/java_append_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_char.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_append_char/test_append_char.class b/regression/strings/smoke_tests/java_append_char/test_append_char.class new file mode 100644 index 00000000000..00c40aef6f6 Binary files /dev/null and b/regression/strings/smoke_tests/java_append_char/test_append_char.class differ diff --git a/regression/strings/smoke_tests/java_append_char/test_append_char.java b/regression/strings/smoke_tests/java_append_char/test_append_char.java new file mode 100644 index 00000000000..3eec4f30abe --- /dev/null +++ b/regression/strings/smoke_tests/java_append_char/test_append_char.java @@ -0,0 +1,17 @@ +public class test_append_char +{ + public static void main(/*String[] args*/) + { + char[] diff = {'d', 'i', 'f', 'f'}; + char[] blue = {'b', 'l', 'u', 'e'}; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert tmp.equals("diffblue"); + } +} diff --git a/regression/strings/smoke_tests/java_append_int/test.desc b/regression/strings/smoke_tests/java_append_int/test.desc new file mode 100644 index 00000000000..d72294910fd --- /dev/null +++ b/regression/strings/smoke_tests/java_append_int/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_int.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_append_int/test_append_int.class b/regression/strings/smoke_tests/java_append_int/test_append_int.class new file mode 100644 index 00000000000..16948397e03 Binary files /dev/null and b/regression/strings/smoke_tests/java_append_int/test_append_int.class differ diff --git a/regression/strings/smoke_tests/java_append_int/test_append_int.java b/regression/strings/smoke_tests/java_append_int/test_append_int.java new file mode 100644 index 00000000000..963f3d7c063 --- /dev/null +++ b/regression/strings/smoke_tests/java_append_int/test_append_int.java @@ -0,0 +1,11 @@ +public class test_append_int +{ + public static void main(/*String[] args*/) + { + StringBuilder diffblue = new StringBuilder(); + diffblue.append("d"); + diffblue.append(4); + String s = diffblue.toString(); + assert s.equals("d4"); + } +} diff --git a/regression/strings/smoke_tests/java_append_object/test.desc b/regression/strings/smoke_tests/java_append_object/test.desc new file mode 100644 index 00000000000..dfc96352e21 --- /dev/null +++ b/regression/strings/smoke_tests/java_append_object/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_object.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_append_object/test_append_object.class b/regression/strings/smoke_tests/java_append_object/test_append_object.class new file mode 100644 index 00000000000..ed6942a1fa6 Binary files /dev/null and b/regression/strings/smoke_tests/java_append_object/test_append_object.class differ diff --git a/regression/strings/smoke_tests/java_append_object/test_append_object.java b/regression/strings/smoke_tests/java_append_object/test_append_object.java new file mode 100644 index 00000000000..121690451ca --- /dev/null +++ b/regression/strings/smoke_tests/java_append_object/test_append_object.java @@ -0,0 +1,17 @@ +public class test_append_object +{ + public static void main(/*String[] args*/) + { + Object diff = "diff"; + Object blue = "blue"; + + StringBuilder buffer = new StringBuilder(); + + buffer.append(diff) + .append(blue); + + String tmp=buffer.toString(); + System.out.println(tmp); + assert tmp.equals("diffblue"); + } +} diff --git a/regression/strings/smoke_tests/java_append_string/test.desc b/regression/strings/smoke_tests/java_append_string/test.desc new file mode 100644 index 00000000000..52db03ff482 --- /dev/null +++ b/regression/strings/smoke_tests/java_append_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_append_string.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_append_string/test_append_string.class b/regression/strings/smoke_tests/java_append_string/test_append_string.class new file mode 100644 index 00000000000..622e08467f9 Binary files /dev/null and b/regression/strings/smoke_tests/java_append_string/test_append_string.class differ diff --git a/regression/strings/smoke_tests/java_append_string/test_append_string.java b/regression/strings/smoke_tests/java_append_string/test_append_string.java new file mode 100644 index 00000000000..e7f961172fa --- /dev/null +++ b/regression/strings/smoke_tests/java_append_string/test_append_string.java @@ -0,0 +1,14 @@ +public class test_append_string +{ + public static void main(/*String[] args*/) + { + String di = new String("di"); + StringBuilder diff = new StringBuilder(); + diff.append(di); + diff.append("ff"); + System.out.println(diff); + String s = diff.toString(); + System.out.println(s); + assert s.equals("diff"); + } +} diff --git a/regression/strings/smoke_tests/java_case/test.desc b/regression/strings/smoke_tests/java_case/test.desc new file mode 100644 index 00000000000..56568251dcd --- /dev/null +++ b/regression/strings/smoke_tests/java_case/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_case.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_case/test_case.class b/regression/strings/smoke_tests/java_case/test_case.class new file mode 100644 index 00000000000..9f7eaab446c Binary files /dev/null and b/regression/strings/smoke_tests/java_case/test_case.class differ diff --git a/regression/strings/smoke_tests/java_case/test_case.java b/regression/strings/smoke_tests/java_case/test_case.java new file mode 100644 index 00000000000..b3437a6f83e --- /dev/null +++ b/regression/strings/smoke_tests/java_case/test_case.java @@ -0,0 +1,12 @@ +public class test_case +{ + public static void main(/*String[] argv*/) + { + String s = new String("Ab"); + String l = s.toLowerCase(); + String u = s.toUpperCase(); + assert(l.equals("ab")); + assert(u.equals("AB")); + assert(s.equalsIgnoreCase("aB")); + } +} diff --git a/regression/strings/smoke_tests/java_char_array/test.desc b/regression/strings/smoke_tests/java_char_array/test.desc new file mode 100644 index 00000000000..22ca7708ef2 --- /dev/null +++ b/regression/strings/smoke_tests/java_char_array/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_char_array.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_char_array/test_char_array.class b/regression/strings/smoke_tests/java_char_array/test_char_array.class new file mode 100644 index 00000000000..0d2056042ca Binary files /dev/null and b/regression/strings/smoke_tests/java_char_array/test_char_array.class differ diff --git a/regression/strings/smoke_tests/java_char_array/test_char_array.java b/regression/strings/smoke_tests/java_char_array/test_char_array.java new file mode 100644 index 00000000000..017fe704124 --- /dev/null +++ b/regression/strings/smoke_tests/java_char_array/test_char_array.java @@ -0,0 +1,13 @@ +public class test_char_array +{ + public static void main(/*String[] argv*/) + { + String s = "abc"; + char [] str = s.toCharArray(); + char c = str[2]; + char a = s.charAt(0); + assert(str.length == 3); + assert(a == 'a'); + assert(c == 'c'); + } +} diff --git a/regression/strings/smoke_tests/java_char_array_init/test.desc b/regression/strings/smoke_tests/java_char_array_init/test.desc new file mode 100644 index 00000000000..94d8faa7afc --- /dev/null +++ b/regression/strings/smoke_tests/java_char_array_init/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_init.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_char_array_init/test_init.class b/regression/strings/smoke_tests/java_char_array_init/test_init.class new file mode 100644 index 00000000000..48075eb9187 Binary files /dev/null and b/regression/strings/smoke_tests/java_char_array_init/test_init.class differ diff --git a/regression/strings/smoke_tests/java_char_array_init/test_init.java b/regression/strings/smoke_tests/java_char_array_init/test_init.java new file mode 100644 index 00000000000..8e0f656e3e8 --- /dev/null +++ b/regression/strings/smoke_tests/java_char_array_init/test_init.java @@ -0,0 +1,21 @@ +public class test_init { + + public static void main(/*String[] argv*/) + { + char [] str = new char[10]; + str[0] = 'H'; + str[1] = 'e'; + str[2] = 'l'; + str[3] = 'l'; + str[4] = 'o'; + String s = new String(str); + String t = new String(str,1,2); + + System.out.println(s.length()); + assert(s.length() == 10); + System.out.println(s); + System.out.println(t); + assert(t.equals("el")); + assert(s.startsWith("Hello")); + } +} diff --git a/regression/strings/smoke_tests/java_char_at/test.desc b/regression/strings/smoke_tests/java_char_at/test.desc new file mode 100644 index 00000000000..0f8bcdf6e8f --- /dev/null +++ b/regression/strings/smoke_tests/java_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_char_at.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_char_at/test_char_at.class b/regression/strings/smoke_tests/java_char_at/test_char_at.class new file mode 100644 index 00000000000..de5fe888245 Binary files /dev/null and b/regression/strings/smoke_tests/java_char_at/test_char_at.class differ diff --git a/regression/strings/smoke_tests/java_char_at/test_char_at.java b/regression/strings/smoke_tests/java_char_at/test_char_at.java new file mode 100644 index 00000000000..3b8663d62ae --- /dev/null +++ b/regression/strings/smoke_tests/java_char_at/test_char_at.java @@ -0,0 +1,7 @@ +public class test_char_at { + + public static void main(/*String[] argv*/) { + String s = new String("abc"); + assert(s.charAt(2)=='c'); + } +} diff --git a/regression/strings/smoke_tests/java_code_point/test.desc b/regression/strings/smoke_tests/java_code_point/test.desc new file mode 100644 index 00000000000..12c9d0f4d60 --- /dev/null +++ b/regression/strings/smoke_tests/java_code_point/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_code_point.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_code_point/test_code_point.class b/regression/strings/smoke_tests/java_code_point/test_code_point.class new file mode 100644 index 00000000000..1d5d2269325 Binary files /dev/null and b/regression/strings/smoke_tests/java_code_point/test_code_point.class differ diff --git a/regression/strings/smoke_tests/java_code_point/test_code_point.java b/regression/strings/smoke_tests/java_code_point/test_code_point.java new file mode 100644 index 00000000000..faf9a2051d5 --- /dev/null +++ b/regression/strings/smoke_tests/java_code_point/test_code_point.java @@ -0,0 +1,14 @@ +public class test_code_point +{ + public static void main(/*String[] argv*/) + { + String s = "!𐤇𐤄𐤋𐤋𐤅"; + assert(s.codePointAt(1) == 67847); + assert(s.codePointBefore(3) == 67847); + assert(s.codePointCount(1,5) >= 2); + assert(s.offsetByCodePoints(1,2) >= 3); + StringBuilder sb = new StringBuilder(); + sb.appendCodePoint(0x10907); + assert(s.charAt(1) == sb.charAt(0)); + } +} diff --git a/regression/strings/smoke_tests/java_compare/test.desc b/regression/strings/smoke_tests/java_compare/test.desc new file mode 100644 index 00000000000..76ca1c4c282 --- /dev/null +++ b/regression/strings/smoke_tests/java_compare/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_compare.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_compare/test_compare.class b/regression/strings/smoke_tests/java_compare/test_compare.class new file mode 100644 index 00000000000..3a807f4d203 Binary files /dev/null and b/regression/strings/smoke_tests/java_compare/test_compare.class differ diff --git a/regression/strings/smoke_tests/java_compare/test_compare.java b/regression/strings/smoke_tests/java_compare/test_compare.java new file mode 100644 index 00000000000..c052ed429bd --- /dev/null +++ b/regression/strings/smoke_tests/java_compare/test_compare.java @@ -0,0 +1,9 @@ +public class test_compare +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "aa"; + assert(s1.compareTo(s2) == 1); + } +} diff --git a/regression/strings/smoke_tests/java_concat/test.desc b/regression/strings/smoke_tests/java_concat/test.desc new file mode 100644 index 00000000000..9bfb8fb9ced --- /dev/null +++ b/regression/strings/smoke_tests/java_concat/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_concat.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 10.* SUCCESS$ +^\[.*assertion.2\].* line 11.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_concat/test_concat.class b/regression/strings/smoke_tests/java_concat/test_concat.class new file mode 100644 index 00000000000..e4143c15773 Binary files /dev/null and b/regression/strings/smoke_tests/java_concat/test_concat.class differ diff --git a/regression/strings/smoke_tests/java_concat/test_concat.java b/regression/strings/smoke_tests/java_concat/test_concat.java new file mode 100644 index 00000000000..b9909c723d4 --- /dev/null +++ b/regression/strings/smoke_tests/java_concat/test_concat.java @@ -0,0 +1,13 @@ +public class test_concat +{ + public static void main(/*String[] argv*/) + { + String s = new String("pi"); + int i = s.length(); + String t = new String("ppo"); + String u = s.concat(t); + char c = u.charAt(i); + assert(c == 'p'); + assert(c == 'o'); + } +} diff --git a/regression/strings/smoke_tests/java_contains/test.desc b/regression/strings/smoke_tests/java_contains/test.desc new file mode 100644 index 00000000000..169a5f19e73 --- /dev/null +++ b/regression/strings/smoke_tests/java_contains/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_contains.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* SUCCESS$ +^\[.*assertion.2\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_contains/test_contains.class b/regression/strings/smoke_tests/java_contains/test_contains.class new file mode 100644 index 00000000000..adf0ece000a Binary files /dev/null and b/regression/strings/smoke_tests/java_contains/test_contains.class differ diff --git a/regression/strings/smoke_tests/java_contains/test_contains.java b/regression/strings/smoke_tests/java_contains/test_contains.java new file mode 100644 index 00000000000..5112c344c09 --- /dev/null +++ b/regression/strings/smoke_tests/java_contains/test_contains.java @@ -0,0 +1,11 @@ +public class test_contains +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + String u = "bc"; + String t = "ab"; + assert(s.contains(u)); + assert(s.contains(t)); + } +} diff --git a/regression/strings/smoke_tests/java_delete/test.desc b/regression/strings/smoke_tests/java_delete/test.desc new file mode 100644 index 00000000000..81e6a1a4685 --- /dev/null +++ b/regression/strings/smoke_tests/java_delete/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_delete/test_delete.class b/regression/strings/smoke_tests/java_delete/test_delete.class new file mode 100644 index 00000000000..f18891851b1 Binary files /dev/null and b/regression/strings/smoke_tests/java_delete/test_delete.class differ diff --git a/regression/strings/smoke_tests/java_delete/test_delete.java b/regression/strings/smoke_tests/java_delete/test_delete.java new file mode 100644 index 00000000000..13bd09cd075 --- /dev/null +++ b/regression/strings/smoke_tests/java_delete/test_delete.java @@ -0,0 +1,10 @@ +public class test_delete +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder("Abc"); + s.delete(1,2); + String str = s.toString(); + assert(str.equals("Ac")); + } +} diff --git a/regression/strings/smoke_tests/java_delete_char_at/test.desc b/regression/strings/smoke_tests/java_delete_char_at/test.desc new file mode 100644 index 00000000000..2d8832804ff --- /dev/null +++ b/regression/strings/smoke_tests/java_delete_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_delete_char_at.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_delete_char_at/test_delete_char_at.class b/regression/strings/smoke_tests/java_delete_char_at/test_delete_char_at.class new file mode 100644 index 00000000000..cfd8561e596 Binary files /dev/null and b/regression/strings/smoke_tests/java_delete_char_at/test_delete_char_at.class differ diff --git a/regression/strings/smoke_tests/java_delete_char_at/test_delete_char_at.java b/regression/strings/smoke_tests/java_delete_char_at/test_delete_char_at.java new file mode 100644 index 00000000000..94787c5283d --- /dev/null +++ b/regression/strings/smoke_tests/java_delete_char_at/test_delete_char_at.java @@ -0,0 +1,11 @@ +public class test_delete_char_at +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder(); + s.append("Abc"); + s.deleteCharAt(1); + String str = s.toString(); + assert(str.equals("Ac")); + } +} diff --git a/regression/strings/smoke_tests/java_empty/test.desc b/regression/strings/smoke_tests/java_empty/test.desc new file mode 100644 index 00000000000..839354fab72 --- /dev/null +++ b/regression/strings/smoke_tests/java_empty/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_empty.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_empty/test_empty.class b/regression/strings/smoke_tests/java_empty/test_empty.class new file mode 100644 index 00000000000..8e9a17d387e Binary files /dev/null and b/regression/strings/smoke_tests/java_empty/test_empty.class differ diff --git a/regression/strings/smoke_tests/java_empty/test_empty.java b/regression/strings/smoke_tests/java_empty/test_empty.java new file mode 100644 index 00000000000..47c335e16fa --- /dev/null +++ b/regression/strings/smoke_tests/java_empty/test_empty.java @@ -0,0 +1,8 @@ +public class test_empty +{ + public static void main(/*String[] argv*/) + { + String empty = ""; + assert(empty.isEmpty()); + } +} diff --git a/regression/strings/smoke_tests/java_endswith/test.desc b/regression/strings/smoke_tests/java_endswith/test.desc new file mode 100644 index 00000000000..0f094d139b5 --- /dev/null +++ b/regression/strings/smoke_tests/java_endswith/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_endswith.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* SUCCESS$ +^\[.*assertion.2\].* line 10.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_endswith/test_endswith.class b/regression/strings/smoke_tests/java_endswith/test_endswith.class new file mode 100644 index 00000000000..1f86e94431d Binary files /dev/null and b/regression/strings/smoke_tests/java_endswith/test_endswith.class differ diff --git a/regression/strings/smoke_tests/java_endswith/test_endswith.java b/regression/strings/smoke_tests/java_endswith/test_endswith.java new file mode 100644 index 00000000000..f7729ef6a40 --- /dev/null +++ b/regression/strings/smoke_tests/java_endswith/test_endswith.java @@ -0,0 +1,12 @@ +public class test_endswith +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abcd"); + String suff = "cd"; + String bad_suff = "bc"; + + assert(s.endsWith(suff)); + assert(s.endsWith(bad_suff)); + } +} diff --git a/regression/strings/smoke_tests/java_equal/test.desc b/regression/strings/smoke_tests/java_equal/test.desc new file mode 100644 index 00000000000..b1ccbc69d2d --- /dev/null +++ b/regression/strings/smoke_tests/java_equal/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_equal.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* FAILURE$ +^\[.*assertion.2\].* line 9.* SUCCESS$ +-- diff --git a/regression/strings/smoke_tests/java_equal/test_equal.class b/regression/strings/smoke_tests/java_equal/test_equal.class new file mode 100644 index 00000000000..e0fc6db8aaf Binary files /dev/null and b/regression/strings/smoke_tests/java_equal/test_equal.class differ diff --git a/regression/strings/smoke_tests/java_equal/test_equal.java b/regression/strings/smoke_tests/java_equal/test_equal.java new file mode 100644 index 00000000000..a3acb0ebda5 --- /dev/null +++ b/regression/strings/smoke_tests/java_equal/test_equal.java @@ -0,0 +1,11 @@ +public class test_equal +{ + public static void main(String[] argv) + { + String s = new String("pi"); + String t = new String("po"); + String u = "po"; + assert(s.equals(t)); + assert(t.equals(u)); + } +} diff --git a/regression/strings/smoke_tests/java_float/test.desc b/regression/strings/smoke_tests/java_float/test.desc new file mode 100644 index 00000000000..09df1150e77 --- /dev/null +++ b/regression/strings/smoke_tests/java_float/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_float.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_float/test_float.class b/regression/strings/smoke_tests/java_float/test_float.class new file mode 100644 index 00000000000..e4448d41558 Binary files /dev/null and b/regression/strings/smoke_tests/java_float/test_float.class differ diff --git a/regression/strings/smoke_tests/java_float/test_float.java b/regression/strings/smoke_tests/java_float/test_float.java new file mode 100644 index 00000000000..d2791d5c343 --- /dev/null +++ b/regression/strings/smoke_tests/java_float/test_float.java @@ -0,0 +1,15 @@ +public class test_float +{ + public static void main(/*String[] arg*/) + { + float inf = 100.0f / 0.0f; + float minus_inf = -100.0f / 0.0f; + float nan = 0.0f / 0.0f; + String inf_string = Float.toString(inf); + String mininf_string = Float.toString(minus_inf); + String nan_string = Float.toString(nan); + assert(nan_string.equals("NaN")); + assert(inf_string.equals("Infinity")); + assert(mininf_string.equals("-Infinity")); + } +} diff --git a/regression/strings/smoke_tests/java_hash_code/test.desc b/regression/strings/smoke_tests/java_hash_code/test.desc new file mode 100644 index 00000000000..c1f3f1d57b1 --- /dev/null +++ b/regression/strings/smoke_tests/java_hash_code/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_hash_code.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* SUCCESS$ +^\[.*assertion.2\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_hash_code/test_hash_code.class b/regression/strings/smoke_tests/java_hash_code/test_hash_code.class new file mode 100644 index 00000000000..21bc5d96ca9 Binary files /dev/null and b/regression/strings/smoke_tests/java_hash_code/test_hash_code.class differ diff --git a/regression/strings/smoke_tests/java_hash_code/test_hash_code.java b/regression/strings/smoke_tests/java_hash_code/test_hash_code.java new file mode 100644 index 00000000000..d9f42b7ff9d --- /dev/null +++ b/regression/strings/smoke_tests/java_hash_code/test_hash_code.java @@ -0,0 +1,11 @@ +public class test_hash_code +{ + public static void main(/*String[] argv*/) + { + String s1 = "ab"; + String s2 = "ab"; + String s3 = "aa"; + assert(s1.hashCode() == s2.hashCode()); + assert(s1.hashCode() == s3.hashCode()); + } +} diff --git a/regression/strings/smoke_tests/java_index_of/test.desc b/regression/strings/smoke_tests/java_index_of/test.desc new file mode 100644 index 00000000000..cbed0db8d2e --- /dev/null +++ b/regression/strings/smoke_tests/java_index_of/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_index_of/test_index_of.class b/regression/strings/smoke_tests/java_index_of/test_index_of.class new file mode 100644 index 00000000000..1acb3335d57 Binary files /dev/null and b/regression/strings/smoke_tests/java_index_of/test_index_of.class differ diff --git a/regression/strings/smoke_tests/java_index_of/test_index_of.java b/regression/strings/smoke_tests/java_index_of/test_index_of.java new file mode 100644 index 00000000000..270267196c5 --- /dev/null +++ b/regression/strings/smoke_tests/java_index_of/test_index_of.java @@ -0,0 +1,10 @@ +public class test_index_of +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + String bc = "bc"; + int i = s.indexOf(bc); + assert(i == 1); + } +} diff --git a/regression/strings/smoke_tests/java_index_of_char/test.desc b/regression/strings/smoke_tests/java_index_of_char/test.desc new file mode 100644 index 00000000000..3a2619c1ecd --- /dev/null +++ b/regression/strings/smoke_tests/java_index_of_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_index_of_char.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_index_of_char/test_index_of_char.class b/regression/strings/smoke_tests/java_index_of_char/test_index_of_char.class new file mode 100644 index 00000000000..f87a1026683 Binary files /dev/null and b/regression/strings/smoke_tests/java_index_of_char/test_index_of_char.class differ diff --git a/regression/strings/smoke_tests/java_index_of_char/test_index_of_char.java b/regression/strings/smoke_tests/java_index_of_char/test_index_of_char.java new file mode 100644 index 00000000000..6a5d3d60bd6 --- /dev/null +++ b/regression/strings/smoke_tests/java_index_of_char/test_index_of_char.java @@ -0,0 +1,10 @@ +public class test_index_of_char +{ + public static void main(/*String[] argv*/) + { + String s = "Abc"; + char c = 'c'; + int i = s.indexOf(c); + assert(i == 2); + } +} diff --git a/regression/strings/smoke_tests/java_insert_char/test.desc b/regression/strings/smoke_tests/java_insert_char/test.desc new file mode 100644 index 00000000000..fef348968cb --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_insert_char/test_insert_char.class b/regression/strings/smoke_tests/java_insert_char/test_insert_char.class new file mode 100644 index 00000000000..481304a9f6d Binary files /dev/null and b/regression/strings/smoke_tests/java_insert_char/test_insert_char.class differ diff --git a/regression/strings/smoke_tests/java_insert_char/test_insert_char.java b/regression/strings/smoke_tests/java_insert_char/test_insert_char.java new file mode 100644 index 00000000000..ac6beb4ffcf --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_char/test_insert_char.java @@ -0,0 +1,10 @@ +public class test_insert_char +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ac"); + sb.insert(1, 'b'); + String s = sb.toString(); + assert(s.equals("abc")); + } +} diff --git a/regression/strings/smoke_tests/java_insert_char_array/test.desc b/regression/strings/smoke_tests/java_insert_char_array/test.desc new file mode 100644 index 00000000000..27c5ef241a1 --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_char_array/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_char_array.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_insert_char_array/test_insert_char_array.class b/regression/strings/smoke_tests/java_insert_char_array/test_insert_char_array.class new file mode 100644 index 00000000000..3c0b5329230 Binary files /dev/null and b/regression/strings/smoke_tests/java_insert_char_array/test_insert_char_array.class differ diff --git a/regression/strings/smoke_tests/java_insert_char_array/test_insert_char_array.java b/regression/strings/smoke_tests/java_insert_char_array/test_insert_char_array.java new file mode 100644 index 00000000000..2c2840df672 --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_char_array/test_insert_char_array.java @@ -0,0 +1,14 @@ +public class test_insert_char_array +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + char[] array = new char[2]; + array[0] = 'b'; + array[1] = 'c'; + sb.insert(1, array); + String s = sb.toString(); + System.out.println(s); + assert(s.equals("abcd")); + } +} diff --git a/regression/strings/smoke_tests/java_insert_int/test.desc b/regression/strings/smoke_tests/java_insert_int/test.desc new file mode 100644 index 00000000000..3c1a954bf96 --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_int/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_int.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_insert_int/test_insert_int.class b/regression/strings/smoke_tests/java_insert_int/test_insert_int.class new file mode 100644 index 00000000000..8b0121ec681 Binary files /dev/null and b/regression/strings/smoke_tests/java_insert_int/test_insert_int.class differ diff --git a/regression/strings/smoke_tests/java_insert_int/test_insert_int.java b/regression/strings/smoke_tests/java_insert_int/test_insert_int.java new file mode 100644 index 00000000000..b787141e51a --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_int/test_insert_int.java @@ -0,0 +1,10 @@ +public class test_insert_int +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ac"); + sb.insert(1, 42); + String s = sb.toString(); + assert(s.equals("a42c")); + } +} diff --git a/regression/strings/smoke_tests/java_insert_multiple/.test_insert.java.swp b/regression/strings/smoke_tests/java_insert_multiple/.test_insert.java.swp new file mode 100644 index 00000000000..5596a2c906d Binary files /dev/null and b/regression/strings/smoke_tests/java_insert_multiple/.test_insert.java.swp differ diff --git a/regression/strings/smoke_tests/java_insert_multiple/test.desc b/regression/strings/smoke_tests/java_insert_multiple/test.desc new file mode 100644 index 00000000000..dc3c5dae10d --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_multiple/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_multiple.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_insert_multiple/test_insert_multiple.class b/regression/strings/smoke_tests/java_insert_multiple/test_insert_multiple.class new file mode 100644 index 00000000000..17ced6ec67c Binary files /dev/null and b/regression/strings/smoke_tests/java_insert_multiple/test_insert_multiple.class differ diff --git a/regression/strings/smoke_tests/java_insert_multiple/test_insert_multiple.java b/regression/strings/smoke_tests/java_insert_multiple/test_insert_multiple.java new file mode 100644 index 00000000000..cce6881ca7d --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_multiple/test_insert_multiple.java @@ -0,0 +1,11 @@ +public class test_insert_multiple +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, 'c'); + sb.insert(1, "b"); + String s = sb.toString(); + assert(s.equals("abcd")); + } +} diff --git a/regression/strings/smoke_tests/java_insert_string/test.desc b/regression/strings/smoke_tests/java_insert_string/test.desc new file mode 100644 index 00000000000..c8c942bb00e --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_insert_string.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_insert_string/test_insert_string.class b/regression/strings/smoke_tests/java_insert_string/test_insert_string.class new file mode 100644 index 00000000000..39cc969a902 Binary files /dev/null and b/regression/strings/smoke_tests/java_insert_string/test_insert_string.class differ diff --git a/regression/strings/smoke_tests/java_insert_string/test_insert_string.java b/regression/strings/smoke_tests/java_insert_string/test_insert_string.java new file mode 100644 index 00000000000..7c161205131 --- /dev/null +++ b/regression/strings/smoke_tests/java_insert_string/test_insert_string.java @@ -0,0 +1,10 @@ +public class test_insert_string +{ + public static void main(/*String[] argv*/) + { + StringBuilder sb = new StringBuilder("ad"); + sb.insert(1, "bc"); + String s = sb.toString(); + assert(s.equals("abcd")); + } +} diff --git a/regression/strings/smoke_tests/java_int_to_string/test.desc b/regression/strings/smoke_tests/java_int_to_string/test.desc new file mode 100644 index 00000000000..66afed35808 --- /dev/null +++ b/regression/strings/smoke_tests/java_int_to_string/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_int.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_int_to_string/test_int.class b/regression/strings/smoke_tests/java_int_to_string/test_int.class new file mode 100644 index 00000000000..eff0e5a422e Binary files /dev/null and b/regression/strings/smoke_tests/java_int_to_string/test_int.class differ diff --git a/regression/strings/smoke_tests/java_int_to_string/test_int.java b/regression/strings/smoke_tests/java_int_to_string/test_int.java new file mode 100644 index 00000000000..f46411ed166 --- /dev/null +++ b/regression/strings/smoke_tests/java_int_to_string/test_int.java @@ -0,0 +1,11 @@ +public class test_int +{ + public static void main(/*String[] argv*/) + { + String s = Integer.toString(12); + assert(s.equals("12")); + String t = Integer.toString(-23); + System.out.println(t); + assert(t.equals("-23")); + } +} diff --git a/regression/strings/smoke_tests/java_intern/test.desc b/regression/strings/smoke_tests/java_intern/test.desc new file mode 100644 index 00000000000..fead2e1d408 --- /dev/null +++ b/regression/strings/smoke_tests/java_intern/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_intern.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 9.* SUCCESS$ +-- diff --git a/regression/strings/smoke_tests/java_intern/test_intern.class b/regression/strings/smoke_tests/java_intern/test_intern.class new file mode 100644 index 00000000000..894615c0a9a Binary files /dev/null and b/regression/strings/smoke_tests/java_intern/test_intern.class differ diff --git a/regression/strings/smoke_tests/java_intern/test_intern.java b/regression/strings/smoke_tests/java_intern/test_intern.java new file mode 100644 index 00000000000..7f9d5283597 --- /dev/null +++ b/regression/strings/smoke_tests/java_intern/test_intern.java @@ -0,0 +1,11 @@ +public class test_intern +{ + public static void main(/*String[] argv*/) + { + String s1 = "abc"; + String s3 = "abc"; + String x = s1.intern(); + String y = s3.intern(); + assert(x == y); + } +} diff --git a/regression/strings/smoke_tests/java_last_index_of/test.desc b/regression/strings/smoke_tests/java_last_index_of/test.desc new file mode 100644 index 00000000000..744861fe5a7 --- /dev/null +++ b/regression/strings/smoke_tests/java_last_index_of/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_last_index_of.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_last_index_of/test_last_index_of.class b/regression/strings/smoke_tests/java_last_index_of/test_last_index_of.class new file mode 100644 index 00000000000..4455da4d179 Binary files /dev/null and b/regression/strings/smoke_tests/java_last_index_of/test_last_index_of.class differ diff --git a/regression/strings/smoke_tests/java_last_index_of/test_last_index_of.java b/regression/strings/smoke_tests/java_last_index_of/test_last_index_of.java new file mode 100644 index 00000000000..8b3a0904d5b --- /dev/null +++ b/regression/strings/smoke_tests/java_last_index_of/test_last_index_of.java @@ -0,0 +1,10 @@ +public class test_last_index_of +{ + public static void main(/*String[] argv*/) + { + String s = "abcab"; + String ab = "ab"; + int i = s.lastIndexOf(ab); + assert(i == 3); + } +} diff --git a/regression/strings/smoke_tests/java_last_index_of_char/test.desc b/regression/strings/smoke_tests/java_last_index_of_char/test.desc new file mode 100644 index 00000000000..707d804dc4a --- /dev/null +++ b/regression/strings/smoke_tests/java_last_index_of_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_last_index_of_char.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_last_index_of_char/test_last_index_of_char.class b/regression/strings/smoke_tests/java_last_index_of_char/test_last_index_of_char.class new file mode 100644 index 00000000000..388717f4261 Binary files /dev/null and b/regression/strings/smoke_tests/java_last_index_of_char/test_last_index_of_char.class differ diff --git a/regression/strings/smoke_tests/java_last_index_of_char/test_last_index_of_char.java b/regression/strings/smoke_tests/java_last_index_of_char/test_last_index_of_char.java new file mode 100644 index 00000000000..029d59c9d68 --- /dev/null +++ b/regression/strings/smoke_tests/java_last_index_of_char/test_last_index_of_char.java @@ -0,0 +1,9 @@ +public class test_last_index_of_char +{ + public static void main(/*String[] argv*/) + { + String s = "abcab"; + int n = s.lastIndexOf('a'); + assert(n == 3); + } +} diff --git a/regression/strings/smoke_tests/java_length/test.desc b/regression/strings/smoke_tests/java_length/test.desc new file mode 100644 index 00000000000..dd19ec73e6b --- /dev/null +++ b/regression/strings/smoke_tests/java_length/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_length.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_length/test_length.class b/regression/strings/smoke_tests/java_length/test_length.class new file mode 100644 index 00000000000..9273d09869b Binary files /dev/null and b/regression/strings/smoke_tests/java_length/test_length.class differ diff --git a/regression/strings/smoke_tests/java_length/test_length.java b/regression/strings/smoke_tests/java_length/test_length.java new file mode 100644 index 00000000000..4222414fa80 --- /dev/null +++ b/regression/strings/smoke_tests/java_length/test_length.java @@ -0,0 +1,9 @@ +public class test_length +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + int l = s.length(); + assert(l == 3); + } +} diff --git a/regression/strings/smoke_tests/java_parseint/test.desc b/regression/strings/smoke_tests/java_parseint/test.desc new file mode 100644 index 00000000000..00726803b43 --- /dev/null +++ b/regression/strings/smoke_tests/java_parseint/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_parseint.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 7.* SUCCESS$ +^\[.*assertion.2\].* line 8.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_parseint/test_parseint.class b/regression/strings/smoke_tests/java_parseint/test_parseint.class new file mode 100644 index 00000000000..e1ffe0c7210 Binary files /dev/null and b/regression/strings/smoke_tests/java_parseint/test_parseint.class differ diff --git a/regression/strings/smoke_tests/java_parseint/test_parseint.java b/regression/strings/smoke_tests/java_parseint/test_parseint.java new file mode 100644 index 00000000000..f278f273675 --- /dev/null +++ b/regression/strings/smoke_tests/java_parseint/test_parseint.java @@ -0,0 +1,10 @@ +public class test_parseint +{ + public static void main(String[] argv) + { + String twelve = new String("12"); + int parsed = Integer.parseInt(twelve); + assert(parsed == 12); + assert(parsed != 12); + } +} diff --git a/regression/strings/smoke_tests/java_replace/test.desc b/regression/strings/smoke_tests/java_replace/test.desc new file mode 100644 index 00000000000..e26eda70fc0 --- /dev/null +++ b/regression/strings/smoke_tests/java_replace/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_replace.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_replace/test_replace.class b/regression/strings/smoke_tests/java_replace/test_replace.class new file mode 100644 index 00000000000..d15509ee8ac Binary files /dev/null and b/regression/strings/smoke_tests/java_replace/test_replace.class differ diff --git a/regression/strings/smoke_tests/java_replace/test_replace.java b/regression/strings/smoke_tests/java_replace/test_replace.java new file mode 100644 index 00000000000..07e7ac036b9 --- /dev/null +++ b/regression/strings/smoke_tests/java_replace/test_replace.java @@ -0,0 +1,13 @@ +public class test_replace +{ + public static void main(/*String[] argv*/) + { + String s = new String("abcabd"); + String u = s.replace("d","z"); + System.out.println(u); + assert(u.equals("abcabz")); + String v = u.replace("ab","w"); + System.out.println(v); + assert(v.equals("wcwz")); + } +} diff --git a/regression/strings/smoke_tests/java_replace_char/test.desc b/regression/strings/smoke_tests/java_replace_char/test.desc new file mode 100644 index 00000000000..376013e006e --- /dev/null +++ b/regression/strings/smoke_tests/java_replace_char/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_replace_char.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_replace_char/test_replace_char.class b/regression/strings/smoke_tests/java_replace_char/test_replace_char.class new file mode 100644 index 00000000000..64626b3b09d Binary files /dev/null and b/regression/strings/smoke_tests/java_replace_char/test_replace_char.class differ diff --git a/regression/strings/smoke_tests/java_replace_char/test_replace_char.java b/regression/strings/smoke_tests/java_replace_char/test_replace_char.java new file mode 100644 index 00000000000..82a023924e2 --- /dev/null +++ b/regression/strings/smoke_tests/java_replace_char/test_replace_char.java @@ -0,0 +1,9 @@ +public class test_replace_char +{ + public static void main(/*String[] argv*/) + { + String s = new String("abcabd"); + String t = s.replace('b','m'); + assert(t.equals("amcamd")); + } +} diff --git a/regression/strings/smoke_tests/java_set_char_at/test.desc b/regression/strings/smoke_tests/java_set_char_at/test.desc new file mode 100644 index 00000000000..dea9f3f84e3 --- /dev/null +++ b/regression/strings/smoke_tests/java_set_char_at/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_set_char_at.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_set_char_at/test_set_char_at.class b/regression/strings/smoke_tests/java_set_char_at/test_set_char_at.class new file mode 100644 index 00000000000..6e843afbe2a Binary files /dev/null and b/regression/strings/smoke_tests/java_set_char_at/test_set_char_at.class differ diff --git a/regression/strings/smoke_tests/java_set_char_at/test_set_char_at.java b/regression/strings/smoke_tests/java_set_char_at/test_set_char_at.java new file mode 100644 index 00000000000..fd1d1fbf9e2 --- /dev/null +++ b/regression/strings/smoke_tests/java_set_char_at/test_set_char_at.java @@ -0,0 +1,13 @@ +public class test_set_char_at +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abc"); + char c = s.charAt(1); + StringBuilder sb = new StringBuilder(s); + sb.setCharAt(1,'w'); + s = sb.toString(); + assert(s.equals("Awc")); + assert(s.charAt(2)=='c'); + } +} diff --git a/regression/strings/smoke_tests/java_set_length/test.desc b/regression/strings/smoke_tests/java_set_length/test.desc new file mode 100644 index 00000000000..70dd8c9c073 --- /dev/null +++ b/regression/strings/smoke_tests/java_set_length/test.desc @@ -0,0 +1,9 @@ +FUTURE +test_set_length.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* SUCCESS$ +^\[.*assertion.2\].* line 9.* SUCCESS$ +^\[.*assertion.3\].* line 10.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_set_length/test_set_length.class b/regression/strings/smoke_tests/java_set_length/test_set_length.class new file mode 100644 index 00000000000..8cb9e416191 Binary files /dev/null and b/regression/strings/smoke_tests/java_set_length/test_set_length.class differ diff --git a/regression/strings/smoke_tests/java_set_length/test_set_length.java b/regression/strings/smoke_tests/java_set_length/test_set_length.java new file mode 100644 index 00000000000..5894b27beeb --- /dev/null +++ b/regression/strings/smoke_tests/java_set_length/test_set_length.java @@ -0,0 +1,12 @@ +public class test_set_length +{ + public static void main(/*String[] argv*/) + { + StringBuilder s = new StringBuilder("abc"); + s.setLength(10); + String t = s.toString(); + assert(t.startsWith("abc")); + assert(t.length() == 10); + assert(t.length() == 3); + } +} diff --git a/regression/strings/smoke_tests/java_starts_with/test.desc b/regression/strings/smoke_tests/java_starts_with/test.desc new file mode 100644 index 00000000000..8f099a2841e --- /dev/null +++ b/regression/strings/smoke_tests/java_starts_with/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_starts_with.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 8.* SUCCESS$ +^\[.*assertion.2\].* line 9.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_starts_with/test_starts_with.class b/regression/strings/smoke_tests/java_starts_with/test_starts_with.class new file mode 100644 index 00000000000..da1decd8d35 Binary files /dev/null and b/regression/strings/smoke_tests/java_starts_with/test_starts_with.class differ diff --git a/regression/strings/smoke_tests/java_starts_with/test_starts_with.java b/regression/strings/smoke_tests/java_starts_with/test_starts_with.java new file mode 100644 index 00000000000..aba79d846c0 --- /dev/null +++ b/regression/strings/smoke_tests/java_starts_with/test_starts_with.java @@ -0,0 +1,11 @@ +public class test_starts_with +{ + public static void main(/*String[] argv*/) + { + String s = new String("Abcd"); + String pref = "Ab"; + String bad_pref = "bc"; + assert(s.startsWith(pref)); + assert(s.startsWith(bad_pref)); + } +} diff --git a/regression/strings/smoke_tests/java_string_builder_length/test.desc b/regression/strings/smoke_tests/java_string_builder_length/test.desc new file mode 100644 index 00000000000..c52a492c90c --- /dev/null +++ b/regression/strings/smoke_tests/java_string_builder_length/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_sb_length.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_string_builder_length/test_sb_length.class b/regression/strings/smoke_tests/java_string_builder_length/test_sb_length.class new file mode 100644 index 00000000000..cfc35874d26 Binary files /dev/null and b/regression/strings/smoke_tests/java_string_builder_length/test_sb_length.class differ diff --git a/regression/strings/smoke_tests/java_string_builder_length/test_sb_length.java b/regression/strings/smoke_tests/java_string_builder_length/test_sb_length.java new file mode 100644 index 00000000000..b616749ffb4 --- /dev/null +++ b/regression/strings/smoke_tests/java_string_builder_length/test_sb_length.java @@ -0,0 +1,9 @@ +public class test_sb_length +{ + public static void main(/*String[] argv*/) + { + StringBuilder x = new StringBuilder("abc"); + x.append("de"); + assert(x.length() == 5); + } +} diff --git a/regression/strings/smoke_tests/java_subsequence/test.desc b/regression/strings/smoke_tests/java_subsequence/test.desc new file mode 100644 index 00000000000..8ce502d7b11 --- /dev/null +++ b/regression/strings/smoke_tests/java_subsequence/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_subsequence.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_subsequence/test_subsequence.class b/regression/strings/smoke_tests/java_subsequence/test_subsequence.class new file mode 100644 index 00000000000..0f8410939e1 Binary files /dev/null and b/regression/strings/smoke_tests/java_subsequence/test_subsequence.class differ diff --git a/regression/strings/smoke_tests/java_subsequence/test_subsequence.java b/regression/strings/smoke_tests/java_subsequence/test_subsequence.java new file mode 100644 index 00000000000..4d8d79cb381 --- /dev/null +++ b/regression/strings/smoke_tests/java_subsequence/test_subsequence.java @@ -0,0 +1,14 @@ +public class test_subsequence +{ + public static void main(/*String[] argv*/) + { + String abcdef = "AbcDef"; + CharSequence cde = abcdef.subSequence(2,5); + char c = cde.charAt(0); + char d = cde.charAt(1); + char e = cde.charAt(2); + assert(c == 'c'); + assert(d == 'D'); + assert(e == 'e'); + } +} diff --git a/regression/strings/smoke_tests/java_substring/test.desc b/regression/strings/smoke_tests/java_substring/test.desc new file mode 100644 index 00000000000..52073b4334f --- /dev/null +++ b/regression/strings/smoke_tests/java_substring/test.desc @@ -0,0 +1,7 @@ +FUTURE +test_substring.class +--string-refine +^EXIT=0$ +^SIGNAL=0$ +^VERIFICATION SUCCESSFUL$ +-- diff --git a/regression/strings/smoke_tests/java_substring/test_substring.class b/regression/strings/smoke_tests/java_substring/test_substring.class new file mode 100644 index 00000000000..3ba0b60e7f2 Binary files /dev/null and b/regression/strings/smoke_tests/java_substring/test_substring.class differ diff --git a/regression/strings/smoke_tests/java_substring/test_substring.java b/regression/strings/smoke_tests/java_substring/test_substring.java new file mode 100644 index 00000000000..03a33fdbebd --- /dev/null +++ b/regression/strings/smoke_tests/java_substring/test_substring.java @@ -0,0 +1,14 @@ +public class test_substring +{ + public static void main(/*String[] argv*/) + { + String abcdef = "AbcDef"; + String cde = abcdef.substring(2,5); + char c = cde.charAt(0); + char d = cde.charAt(1); + char e = cde.charAt(2); + assert(c == 'c'); + assert(d == 'D'); + assert(e == 'e'); + } +} diff --git a/regression/strings/smoke_tests/java_trim/test.desc b/regression/strings/smoke_tests/java_trim/test.desc new file mode 100644 index 00000000000..1d25121cbbc --- /dev/null +++ b/regression/strings/smoke_tests/java_trim/test.desc @@ -0,0 +1,8 @@ +FUTURE +test_trim.class +--string-refine +^EXIT=10$ +^SIGNAL=0$ +^\[.*assertion.1\].* line 6.* SUCCESS$ +^\[.*assertion.2\].* line 7.* FAILURE$ +-- diff --git a/regression/strings/smoke_tests/java_trim/test_trim.class b/regression/strings/smoke_tests/java_trim/test_trim.class new file mode 100644 index 00000000000..33b34714ae2 Binary files /dev/null and b/regression/strings/smoke_tests/java_trim/test_trim.class differ diff --git a/regression/strings/smoke_tests/java_trim/test_trim.java b/regression/strings/smoke_tests/java_trim/test_trim.java new file mode 100644 index 00000000000..20dd7ba2796 --- /dev/null +++ b/regression/strings/smoke_tests/java_trim/test_trim.java @@ -0,0 +1,9 @@ +public class test_trim +{ + public static void main(/*String[] argv*/) + { + String empty = " "; + assert(empty.trim().isEmpty()); + assert(empty.isEmpty()); + } +} diff --git a/regression/strings/test3.4/test.desc b/regression/strings/test3.4/test.desc index d88e1c83744..94d8faa7afc 100644 --- a/regression/strings/test3.4/test.desc +++ b/regression/strings/test3.4/test.desc @@ -1,7 +1,7 @@ FUTURE -test.c +test_init.class --string-refine -^EXIT=10$ +^EXIT=0$ ^SIGNAL=0$ -^VERIFICATION FAILED$ +^VERIFICATION SUCCESSFUL$ -- diff --git a/regression/strings/test_char_set/test.desc b/regression/strings/test_char_set/test.desc index 99f3cfd81de..c9516dd694a 100644 --- a/regression/strings/test_char_set/test.desc +++ b/regression/strings/test_char_set/test.desc @@ -3,6 +3,6 @@ test.c --string-refine ^EXIT=10$ ^SIGNAL=0$ -^\[main.assertion.1\] assertion __CPROVER_string_equal\(t, __CPROVER_string_literal\("apc"\)): SUCCESS$ -^\[main.assertion.2\] assertion __CPROVER_string_equal\(t, __CPROVER_string_literal\("abc"\)): FAILURE$ +^\[.*assertion.1\].* SUCCESS$ +^\[.*assertion.2\].* FAILURE$ -- diff --git a/regression/strings/test_equal/test.desc b/regression/strings/test_equal/test.desc index 5fbe05f8fdd..34906b377a0 100644 --- a/regression/strings/test_equal/test.desc +++ b/regression/strings/test_equal/test.desc @@ -3,6 +3,6 @@ test.c --string-refine ^EXIT=10$ ^SIGNAL=0$ -^\[main.assertion.1\] assertion __CPROVER_string_equal\(s, __CPROVER_string_literal\("pippo"\)): SUCCESS$ -^\[main.assertion.2\] assertion __CPROVER_string_equal\(s, __CPROVER_string_literal\("mippo"\)): FAILURE$ +^\[.*.assertion.1\].* SUCCESS$ +^\[.*.assertion.2\].* FAILURE$ -- diff --git a/regression/strings/test_substring/test.desc b/regression/strings/test_substring/test.desc index a32376aca23..c600dbf19e6 100644 --- a/regression/strings/test_substring/test.desc +++ b/regression/strings/test_substring/test.desc @@ -3,8 +3,8 @@ test.c --string-refine ^EXIT=10$ ^SIGNAL=0$ -^\[main.assertion.1\] assertion __CPROVER_string_equal\(t,__CPROVER_string_literal\("cd"\)): SUCCESS$ -^\[main.assertion.2\] assertion __CPROVER_string_equal\(t,__CPROVER_string_literal\("cc"\)): FAILURE$ -^\[main.assertion.3\] assertion !__CPROVER_string_equal\(t,__CPROVER_string_literal\("bc"\)): SUCCESS$ -^\[main.assertion.4\] assertion !__CPROVER_string_equal\(t,__CPROVER_string_literal\("cd"\)): FAILURE$ +^\[.*assertion.1\].* SUCCESS$ +^\[.*assertion.2\].* FAILURE$ +^\[.*assertion.3\].* SUCCESS$ +^\[.*assertion.4\].* FAILURE$ -- diff --git a/src/cbmc/cbmc_parse_options.cpp b/src/cbmc/cbmc_parse_options.cpp index e33e700e0ca..a910614844c 100644 --- a/src/cbmc/cbmc_parse_options.cpp +++ b/src/cbmc/cbmc_parse_options.cpp @@ -20,6 +20,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include @@ -310,6 +311,17 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options) options.set_option("refine-arithmetic", true); } + + if(cmdline.isset("string-refine")) + { + options.set_option("string-refine", true); + options.set_option("string-non-empty", cmdline.isset("string-non-empty")); + options.set_option("string-printable", cmdline.isset("string-printable")); + if(cmdline.isset("string-max-length")) + options.set_option( + "string-max-length", cmdline.get_value("string-max-length")); + } + if(cmdline.isset("max-node-refinement")) options.set_option( "max-node-refinement", @@ -904,6 +916,14 @@ bool cbmc_parse_optionst::process_goto_program( status() << "Partial Inlining" << eom; goto_partial_inline(goto_functions, ns, ui_message_handler); + + if(cmdline.isset("string-refine")) + { + status() << "Preprocessing for string refinement" << eom; + string_refine_preprocesst( + symbol_table, goto_functions, ui_message_handler); + } + // remove returns, gcc vectors, complex remove_returns(symbol_table, goto_functions); remove_vector(symbol_table, goto_functions); @@ -1191,6 +1211,10 @@ void cbmc_parse_optionst::help() " --yices use Yices\n" " --z3 use Z3\n" " --refine use refinement procedure (experimental)\n" + " --string-refine use string refinement (experimental)\n" + " --string-non-empty add constraint that strings are non empty (experimental)\n" // NOLINT(*) + " --string-printable add constraint that strings are printable (experimental)\n" // NOLINT(*) + " --string-max-length add constraint on the length of strings (experimental)\n" // NOLINT(*) " --outfile filename output formula to given file\n" " --arrays-uf-never never turn arrays into uninterpreted functions\n" // NOLINT(*) " --arrays-uf-always always turn arrays into uninterpreted functions\n" // NOLINT(*) diff --git a/src/cbmc/cbmc_parse_options.h b/src/cbmc/cbmc_parse_options.h index a3fc5e7e7d3..e2ce96ba43f 100644 --- a/src/cbmc/cbmc_parse_options.h +++ b/src/cbmc/cbmc_parse_options.h @@ -37,6 +37,7 @@ class optionst; "(no-sat-preprocessor)" \ "(no-pretty-names)(beautify)" \ "(dimacs)(refine)(max-node-refinement):(refine-arrays)(refine-arithmetic)"\ + "(string-refine)(string-non-empty)(string-printable)(string-max-length):" \ "(aig)(16)(32)(64)(LP64)(ILP64)(LLP64)(ILP32)(LP32)" \ "(little-endian)(big-endian)" \ "(show-goto-functions)(show-loops)" \ diff --git a/src/cbmc/cbmc_solvers.cpp b/src/cbmc/cbmc_solvers.cpp index ccd660dc586..dace046cc17 100644 --- a/src/cbmc/cbmc_solvers.cpp +++ b/src/cbmc/cbmc_solvers.cpp @@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com #include #include +#include #include #include #include @@ -213,6 +214,39 @@ cbmc_solverst::solvert* cbmc_solverst::get_bv_refinement() /*******************************************************************\ +Function: cbmc_solverst::get_string_refinement + + Outputs: a solver for cbmc + + Purpose: the string refinement adds to the bit vector refinement + specifications for functions from the Java string library + +\*******************************************************************/ + +cbmc_solverst::solvert* cbmc_solverst::get_string_refinement() +{ + propt *prop; + prop=new satcheck_no_simplifiert(); + prop->set_message_handler(get_message_handler()); + + string_refinementt *string_refinement=new string_refinementt( + ns, *prop, MAX_NB_REFINEMENT); + string_refinement->set_ui(ui); + + string_refinement->do_concretizing=options.get_bool_option("trace"); + if(options.get_bool_option("string-max-length")) + string_refinement->set_max_string_length( + options.get_signed_int_option("string-max-length")); + if(options.get_bool_option("string-non-empty")) + string_refinement->enforce_non_empty_string(); + if(options.get_bool_option("string-printable")) + string_refinement->enforce_printable_characters(); + + return new solvert(string_refinement, prop); +} + +/*******************************************************************\ + Function: cbmc_solverst::get_smt1 Inputs: diff --git a/src/cbmc/cbmc_solvers.h b/src/cbmc/cbmc_solvers.h index 42d47fcaed3..be4a0e0ccde 100644 --- a/src/cbmc/cbmc_solvers.h +++ b/src/cbmc/cbmc_solvers.h @@ -111,15 +111,17 @@ class cbmc_solverst:public messaget solvert *solver; if(options.get_bool_option("dimacs")) - solver = get_dimacs(); + solver=get_dimacs(); else if(options.get_bool_option("refine")) - solver = get_bv_refinement(); + solver=get_bv_refinement(); + else if(options.get_bool_option("string-refine")) + solver=get_string_refinement(); else if(options.get_bool_option("smt1")) - solver = get_smt1(get_smt1_solver_type()); + solver=get_smt1(get_smt1_solver_type()); else if(options.get_bool_option("smt2")) - solver = get_smt2(get_smt2_solver_type()); + solver=get_smt2(get_smt2_solver_type()); else - solver = get_default(); + solver=get_default(); return std::unique_ptr(solver); } @@ -141,6 +143,7 @@ class cbmc_solverst:public messaget solvert *get_default(); solvert *get_dimacs(); solvert *get_bv_refinement(); + solvert *get_string_refinement(); solvert *get_smt1(smt1_dect::solvert solver); solvert *get_smt2(smt2_dect::solvert solver); diff --git a/src/goto-programs/Makefile b/src/goto-programs/Makefile index d5cc5ea25eb..f23a0e387ed 100644 --- a/src/goto-programs/Makefile +++ b/src/goto-programs/Makefile @@ -20,7 +20,8 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \ slice_global_inits.cpp goto_inline_class.cpp class_identifier.cpp \ show_goto_functions_json.cpp \ show_goto_functions_xml.cpp \ - remove_static_init_loops.cpp remove_instanceof.cpp + remove_static_init_loops.cpp remove_instanceof.cpp \ + string_refine_preprocess.cpp INCLUDES= -I .. diff --git a/src/goto-programs/string_refine_preprocess.cpp b/src/goto-programs/string_refine_preprocess.cpp new file mode 100644 index 00000000000..bf7a0083902 --- /dev/null +++ b/src/goto-programs/string_refine_preprocess.cpp @@ -0,0 +1,1401 @@ +/*******************************************************************\ + +Module: Preprocess a goto-programs so that calls to the java String + library are recognized by the string solver + +Author: Romain Brenguier + +Date: September 2016 + +\*******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "string_refine_preprocess.h" + +/*******************************************************************\ + +Function: string_refine_preprocesst::check_java_type + + Inputs: a type and a string + + Outputs: Boolean telling whether the type is a struct with the given + tag or a symbolic type with the tag prefixed by "java::" + +\*******************************************************************/ + +bool string_refine_preprocesst::check_java_type( + const typet &type, const std::string &tag) +{ + if(type.id()==ID_symbol) + { + irep_idt tag_id=to_symbol_type(type).get_identifier(); + return tag_id=="java::"+tag; + } + else if(type.id()==ID_struct) + { + irep_idt tag_id=to_struct_type(type).get_tag(); + return tag_id==tag; + } + return false; +} +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string pointers + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_pointer_type(const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_string_type(subtype); + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_type(const typet &type) +{ + return check_java_type(type, "java.lang.String"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_builder_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java string builder + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_builder_type(const typet &type) +{ + return check_java_type(type, "java.lang.StringBuilder"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_string_builder_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java StringBuilder + pointers + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_string_builder_pointer_type( + const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_string_builder_type(subtype); + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_sequence_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java char sequence + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_sequence_type(const typet &type) +{ + return check_java_type(type, "java.lang.CharSequence"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_sequence_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of a pointer + to a java char sequence + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_sequence_pointer_type( + const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_char_sequence_type(subtype); + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_array_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of java char array + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_array_type(const typet &type) +{ + return check_java_type(type, "array[char]"); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::is_java_char_array_pointer_type + + Inputs: a type + + Outputs: Boolean telling whether the type is that of a pointer + to a java char array + +\*******************************************************************/ + +bool string_refine_preprocesst::is_java_char_array_pointer_type( + const typet &type) +{ + if(type.id()==ID_pointer) + { + const pointer_typet &pt=to_pointer_type(type); + const typet &subtype=pt.subtype(); + return is_java_char_array_type(subtype); + } + return false; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::new_tmp_symbol + + Inputs: a name and a type + + Outputs: a new symbol + + Purpose: add a temporary symbol with the given name and type to the + symbol table and returns it + +\*******************************************************************/ + +symbol_exprt string_refine_preprocesst::new_tmp_symbol( + const std::string &prefix, const typet &type) +{ + // TODO : this method should be replaced by a call to get_fresh_aux_symbol + // once fresh symbol generation has been factored out + auxiliary_symbolt tmp_symbol; + std::ostringstream buf; + buf << "string_preprocess_tmp" << (next_symbol_id++) << "$" << prefix; + std::string name=buf.str(); + tmp_symbol.base_name=name; + tmp_symbol.is_static_lifetime=false; + tmp_symbol.mode=ID_java; + tmp_symbol.name=name; + tmp_symbol.type=type; + symbol_table.add(tmp_symbol); + return tmp_symbol.symbol_expr(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::new_symbol + + Inputs: a name and a type + + Outputs: a new symbol + + Purpose: add a symbol with the given name and type to the symbol table + and returns it + +\*******************************************************************/ + +symbol_exprt string_refine_preprocesst::new_symbol( + const std::string &prefix, const typet &type, bool static_lifetime) +{ + symbolt tmp_symbol; + std::ostringstream buf; + buf << "string_preprocess" << (next_symbol_id++) << "$" << prefix; + std::string name=buf.str(); + tmp_symbol.base_name=name; + tmp_symbol.is_static_lifetime=static_lifetime; + tmp_symbol.is_state_var=static_lifetime; + tmp_symbol.is_type=false; + tmp_symbol.is_lvalue=true; + tmp_symbol.mode=ID_java; + tmp_symbol.name=name; + tmp_symbol.type=type; + symbol_table.add(tmp_symbol); + return tmp_symbol.symbol_expr(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::declare_function + + Inputs: a name and a type + + Purpose: declare a function with the given name and type + +\*******************************************************************/ + +void string_refine_preprocesst::declare_function( + irep_idt function_name, const typet &type) +{ + auxiliary_symbolt func_symbol; + func_symbol.base_name=function_name; + func_symbol.is_static_lifetime=false; + func_symbol.mode=ID_java; + func_symbol.name=function_name; + func_symbol.type=type; + symbol_table.add(func_symbol); + goto_functions.function_map[function_name]; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::get_data_and_length_type_of_char_array + + Inputs: an expression, a reference to a data type and a reference to a + length type + + Purpose: assuming the expression is a char array, figure out what + the types for length and data are and put them into the references + given as argument + +\*******************************************************************/ + +void string_refine_preprocesst::get_data_and_length_type_of_char_array( + const exprt &expr, typet &data_type, typet &length_type) +{ + typet object_type=ns.follow(expr.type()); + assert(object_type.id()==ID_struct); + const struct_typet &struct_type=to_struct_type(object_type); + for(auto component : struct_type.components()) + if(component.get_name()=="length") + length_type=component.type(); + else if(component.get_name()=="data") + data_type=component.type(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::get_data_and_length_type_of_string + + Inputs: an expression, a reference to a data type and a reference to a + length type + + Purpose: assuming the expression is a java string, figure out what + the types for length and data are and put them into the references + given as argument + +\*******************************************************************/ + +void string_refine_preprocesst::get_data_and_length_type_of_string( + const exprt &expr, typet &data_type, typet &length_type) +{ + assert(is_java_string_type(expr.type()) || + is_java_string_builder_type(expr.type()) || + is_java_char_sequence_type(expr.type())); + typet object_type=ns.follow(expr.type()); + const struct_typet &struct_type=to_struct_type(object_type); + for(const auto &component : struct_type.components()) + if(component.get_name()=="length") + length_type=component.type(); + else if(component.get_name()=="data") + data_type=component.type(); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_cprover_string_assign + + Inputs: a goto_program, a position in this program, an expression and a + location + + Outputs: an expression + + Purpose: Introduce a temporary variable for cprover strings; + returns the cprover_string corresponding to rhs if it is a string + pointer and the original rhs otherwise. + +\*******************************************************************/ + +exprt string_refine_preprocesst::make_cprover_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location) +{ + if(implements_java_char_sequence(rhs.type())) + { + // We do the following assignments: + // 1 cprover_string_length= *(rhs->length) + // 2 cprover_string_array = *(rhs->data) + // 3 cprover_string = { cprover_string_length; cprover_string_array } + + dereference_exprt deref(rhs, rhs.type().subtype()); + typet data_type, length_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + std::list assignments; + + // 1) cprover_string_length= *(rhs->length) + symbol_exprt length_lhs=new_symbol( + "cprover_string_length", length_type); + + member_exprt deref_length(deref, "length", length_type); + assignments.emplace_back(length_lhs, deref_length); + + // 2) cprover_string_array = *(rhs->data) + symbol_exprt array_lhs=new_symbol( + "cprover_string_array", data_type.subtype()); + member_exprt data(deref, "data", data_type); + dereference_exprt deref_data(data, data_type.subtype()); + assignments.emplace_back(array_lhs, deref_data); + + // 3) cprover_string = { cprover_string_length; cprover_string_array } + // This assignment is useful for finding witnessing strings for counter + // examples + refined_string_typet ref_type(length_type, java_char_type()); + string_exprt new_rhs(length_lhs, array_lhs, ref_type); + + symbol_exprt lhs=new_symbol("cprover_string", new_rhs.type()); + assignments.emplace_back(lhs, new_rhs); + + insert_assignments( + goto_program, target, target->function, location, assignments); + target=goto_program.insert_after(target); + return new_rhs; + } + else if(rhs.id()==ID_typecast && + implements_java_char_sequence(rhs.op0().type())) + { + exprt new_rhs=make_cprover_string_assign( + goto_program, target, rhs.op0(), location); + return typecast_exprt(new_rhs, rhs.type()); + } + else + return rhs; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_cprover_char_array_assign + + Inputs: a goto_program, a position in this program, an expression of + type char array pointer and a location + + Outputs: a string expression + + Purpose: Introduce a temporary variable for cprover strings; + returns the cprover_string corresponding to rhs + +\*******************************************************************/ + +string_exprt string_refine_preprocesst::make_cprover_char_array_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location) +{ + assert(is_java_char_array_pointer_type(rhs.type())); + + // We do the following assignments: + // deref=*(rhs->data) + // array= typecast(&deref); + // string={ rhs->length; array } + + dereference_exprt deref(rhs, rhs.type().subtype()); + typet length_type, data_type; + get_data_and_length_type_of_char_array(deref, data_type, length_type); + assert(data_type.id()==ID_pointer); + typet char_type=to_pointer_type(data_type).subtype(); + + refined_string_typet ref_type(length_type, java_char_type()); + typet content_type=ref_type.get_content_type(); + std::list assignments; + + // deref=*(rhs->data) + member_exprt array_rhs(deref, "data", data_type); + dereference_exprt deref_array(array_rhs, data_type.subtype()); + symbol_exprt lhs_deref=new_symbol("char_array_assign$deref", + data_type.subtype()); + assignments.emplace_back(lhs_deref, deref_array); + + // array=convert_pointer_to_char_array(*rhs->data) + declare_function(ID_cprover_string_array_of_char_pointer_func, content_type); + function_application_exprt fun_app(symbol_exprt( + ID_cprover_string_array_of_char_pointer_func), content_type); + fun_app.arguments().push_back(deref_array); + symbol_exprt array=new_symbol("char_array_assign$array", content_type); + assignments.emplace_back(array, fun_app); + + // string={ rhs->length; string_array } + string_exprt new_rhs(get_length(deref, length_type), array, ref_type); + symbol_exprt lhs=new_symbol("char_array_assign$string", ref_type); + assignments.emplace_back(lhs, new_rhs); + + insert_assignments( + goto_program, target, target->function, location, assignments); + target=goto_program.insert_after(target); + return new_rhs; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_normal_assign + + Inputs: a goto_program, a position in this program, an expression lhs, + a function type, a function name, a vector of arguments, a location + and a signature + + Purpose: replace the current instruction by: + > lhs=function_name(arguments) : return_type @ location + If given, signature can force String conversion of given arguments. + The convention for signature is one character by argument + and 'S' denotes string. + +\*******************************************************************/ + +void string_refine_preprocesst::make_normal_assign( + goto_programt &goto_program, + goto_programt::targett target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + function_application_exprt rhs( + symbol_exprt(function_name), function_type.return_type()); + rhs.add_source_location()=location; + declare_function(function_name, function_type); + + exprt::operandst processed_arguments=process_arguments( + goto_program, target, arguments, location, signature); + rhs.arguments()=processed_arguments; + + code_assignt assignment(lhs, rhs); + assignment.add_source_location()=location; + target->make_assignment(); + target->code=assignment; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::insert_assignments + + Inputs: a goto_program, a position in this program, a list of assignments + + Purpose: add the assignments to the program in the order they are given + +\*******************************************************************/ + +void string_refine_preprocesst::insert_assignments( + goto_programt &goto_program, + goto_programt::targett &target, + irep_idt function, + source_locationt location, + const std::list &va) +{ + if(va.empty()) + return; + + auto i=va.begin(); + target->make_assignment(); + target->code=*i; + target->function=function; + target->source_location=location; + for(i++; i!=va.end(); i++) + { + target=goto_program.insert_after(target); + target->make_assignment(); + target->code=*i; + target->function=function; + target->source_location=location; + } +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_assign + + Inputs: a goto_program, a position in this program, an expression lhs, + a function type, a function name, a vector of arguments, a location + and a signature + + Purpose: replace the current instruction by: + > lhs=malloc(String *) + > lhs->length=function_name_length(arguments) + > tmp_data=function_name_data(arguments) + > lhs->data=&tmp_data + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + assert(implements_java_char_sequence(function_type.return_type())); + dereference_exprt deref(lhs, lhs.type().subtype()); + typet object_type=ns.follow(deref.type()); + exprt object_size=size_of_expr(object_type, ns); + typet length_type, data_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + + std::string fnamel=id2string(function_name)+"_length"; + std::string fnamed=id2string(function_name)+"_data"; + declare_function(fnamel, length_type); + declare_function(fnamed, data_type); + function_application_exprt rhs_length(symbol_exprt(fnamel), length_type); + function_application_exprt rhs_data( + symbol_exprt(fnamed), data_type.subtype()); + + exprt::operandst processed_arguments=process_arguments( + goto_program, target, arguments, location, signature); + rhs_length.arguments()=processed_arguments; + rhs_data.arguments()=processed_arguments; + + symbol_exprt tmp_length=new_tmp_symbol("tmp_length", length_type); + symbol_exprt tmp_array=new_tmp_symbol("tmp_array", data_type.subtype()); + member_exprt lhs_length(deref, "length", length_type); + member_exprt lhs_data(deref, "data", tmp_array.type()); + + // lhs=malloc(String *) + assert(object_size.is_not_nil()); // got nil object_size + side_effect_exprt malloc_expr(ID_malloc); + malloc_expr.copy_to_operands(object_size); + malloc_expr.type()=pointer_typet(object_type); + malloc_expr.add_source_location()=location; + + // Adding a string expr in the map + refined_string_typet ref_type(length_type, data_type.subtype().subtype()); + string_exprt str(tmp_length, tmp_array, ref_type); + symbol_exprt cprover_string_sym=new_tmp_symbol( + "tmp_cprover_string", ref_type); + + std::list assigns; + assigns.emplace_back(lhs, malloc_expr); + assigns.emplace_back(tmp_length, rhs_length); + assigns.emplace_back(lhs_length, tmp_length); + assigns.emplace_back(tmp_array, rhs_data); + assigns.emplace_back(cprover_string_sym, str); + assigns.emplace_back(lhs_data, address_of_exprt(tmp_array)); + insert_assignments(goto_program, target, target->function, location, assigns); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_function + + Inputs: a position in a goto program, a function name, an expression lhs, + a function type, name, arguments, a location and a signature string + + Purpose: at the current position replace `lhs=s.some_function(x,...)` + by `lhs=function_name(s,x,...)`; + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + if(signature.length()>0) + { + if(signature.back()=='S') + { + code_typet ft=function_type; + ft.return_type()=jls_ptr; + typecast_exprt lhs2(lhs, jls_ptr); + + make_string_assign( + goto_program, + target, + lhs2, + ft, + function_name, + arguments, + location, + signature); + } + else + make_normal_assign( + goto_program, + target, + lhs, + function_type, + function_name, + arguments, + location, + signature); + } + else if(implements_java_char_sequence(function_type.return_type())) + make_string_assign( + goto_program, + target, + lhs, + function_type, + function_name, + arguments, + location, + signature); + else + make_normal_assign( + goto_program, + target, + lhs, + function_type, + function_name, + arguments, + location, + signature); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_string_function + + Inputs: a position in a goto program, a function name and two Boolean options + + Purpose: at the current position replace `lhs=s.some_function(x,...)` + by `lhs=function_name(s,x,...)`; + option `assign_first_arg` uses `s` instead of `lhs` in the resulting + expression, Warning : it assumes that `s` is string-like + option `skip_first_arg`, removes `s` from the arguments, ie `x` is + the first one; + arguments that are string (TODO: and char array) are replaced + by string_exprt + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature, + bool assign_first_arg, + bool skip_first_arg) +{ + code_function_callt &function_call=to_code_function_call(target->code); + code_typet function_type=to_code_type(function_call.function().type()); + code_typet new_type; + const source_locationt &loc=function_call.source_location(); + declare_function(function_name, function_type); + function_application_exprt rhs; + std::vector args; + if(assign_first_arg) + rhs.type()=function_call.arguments()[0].type(); + else + rhs.type()=function_type.return_type(); + rhs.add_source_location()=function_call.source_location(); + rhs.function()=symbol_exprt(function_name); + + std::size_t start_index=skip_first_arg?1:0; + for(std::size_t i=start_index; i tmp=function_name(x,...) + > s->data=tmp.data + > s->length=tmp.length + > r=s + +\*******************************************************************/ + +void string_refine_preprocesst::make_string_function_side_effect( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature) +{ + code_function_callt function_call=to_code_function_call(target->code); + source_locationt loc=function_call.source_location(); + std::list assignments; + exprt lhs=function_call.lhs(); + exprt s=function_call.arguments()[0]; + code_typet function_type=to_code_type(function_call.type()); + + function_type.return_type()=s.type(); + + if(lhs.is_not_nil()) + { + symbol_exprt tmp_string=new_tmp_symbol( + "tmp_string_side_effect", lhs.type()); + + make_string_assign( + goto_program, + target, + tmp_string, + function_type, + function_name, + function_call.arguments(), + loc, + signature); + dereference_exprt deref_lhs(s, s.type().subtype()); + typet data_type, length_type; + get_data_and_length_type_of_string(deref_lhs, data_type, length_type); + member_exprt lhs_data(deref_lhs, "data", data_type); + member_exprt lhs_length(deref_lhs, "length", length_type); + dereference_exprt deref_rhs(tmp_string, s.type().subtype()); + member_exprt rhs_data(deref_rhs, "data", data_type); + member_exprt rhs_length(deref_rhs, "length", length_type); + assignments.emplace_back(lhs_length, rhs_length); + assignments.emplace_back(lhs_data, rhs_data); + assignments.emplace_back(lhs, s); + target=goto_program.insert_after(target); + insert_assignments( + goto_program, target, target->function, loc, assignments); + } + else + { + make_string_function( + goto_program, target, function_name, signature, true, false); + } +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::build_function_application + + Inputs: a function name, a type, a location and a vector of arguments + + Outputs: a function application expression + + Purpose: declare a function and construct an function application expression + with the given function name, type, location and arguments + +\*******************************************************************/ + +function_application_exprt + string_refine_preprocesst::build_function_application( + const irep_idt &function_name, + const typet &type, + const source_locationt &location, + const exprt::operandst &arguments) +{ + declare_function(function_name, type); + function_application_exprt function_app(symbol_exprt(function_name), type); + function_app.add_source_location()=location; + for(const auto &arg : arguments) + function_app.arguments().push_back(arg); + + return function_app; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::make_to_char_array_function + + Inputs: a goto program and a position in that goto program + + Purpose: at the given position replace `return_tmp0=s.toCharArray()` with: + > return_tmp0 = malloc(array[char]); + > return_tmp0->data=&((s->data)[0]) + > return_tmp0->length=s->length + +\*******************************************************************/ + +void string_refine_preprocesst::make_to_char_array_function( + goto_programt &goto_program, goto_programt::targett &target) +{ + const code_function_callt &function_call=to_code_function_call(target->code); + source_locationt location=function_call.source_location(); + + assert(function_call.arguments().size()>=1); + const exprt &string_argument=function_call.arguments()[0]; + assert(is_java_string_pointer_type(string_argument.type())); + + typet deref_type=function_call.lhs().type().subtype(); + const exprt &lhs=function_call.lhs(); + dereference_exprt deref_lhs(lhs, deref_type); + + dereference_exprt deref(string_argument, string_argument.type().subtype()); + typet length_type, data_type; + get_data_and_length_type_of_string(deref, data_type, length_type); + std::list assignments; + + // lhs=malloc(array[char]) + typet object_type=ns.follow(deref_type); + exprt object_size=size_of_expr(object_type, ns); + + if(object_size.is_nil()) + debug() << "string_refine_preprocesst::make_to_char_array_function " + << "got nil object_size" << eom; + + side_effect_exprt malloc_expr(ID_malloc); + malloc_expr.copy_to_operands(object_size); + malloc_expr.type()=pointer_typet(object_type); + malloc_expr.add_source_location()=location; + assignments.emplace_back(lhs, malloc_expr); + + + // &((s->data)[0]) + exprt rhs_data=get_data(deref, data_type); + dereference_exprt rhs_array(rhs_data, data_type.subtype()); + exprt first_index=from_integer(0, java_int_type()); + index_exprt first_element(rhs_array, first_index, java_char_type()); + address_of_exprt rhs_pointer(first_element); + + // return_tmp0->data=&((s->data)[0]) + exprt lhs_data=get_data(deref_lhs, data_type); + assignments.emplace_back(lhs_data, rhs_pointer); + + // return_tmp0->length=s->length + exprt rhs_length=get_length(deref, length_type); + exprt lhs_length=get_length(deref_lhs, length_type); + assignments.emplace_back(lhs_length, rhs_length); + insert_assignments( + goto_program, target, target->function, location, assignments); +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::process_arguments + + Inputs: a goto program, a position, a list of expressions, a location and a + signature + + Outputs: a list of expressions + + Purpose: for each expression that is a string or that is at a position with + an 'S' character in the signature, we declare a new `cprover_string` + whose contents is deduced from the expression and replace the + expression by this cprover_string in the output list; + in the other case the expression is kept as is for the output list. + +\*******************************************************************/ + +exprt::operandst string_refine_preprocesst::process_arguments( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature) +{ + exprt::operandst new_arguments; + + for(std::size_t i=0; isecond; + else return ""; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::replace_string_calls + + Inputs: a function in a goto_program + + Purpose: goes through the instructions, replace function calls to string + function by equivalent instructions using functions defined + for the string solver, replace string literals by string + expressions of the type used by the string solver + +\*******************************************************************/ + +void string_refine_preprocesst::replace_string_calls( + goto_functionst::function_mapt::iterator f_it) +{ + goto_programt &goto_program=f_it->second.body; + + Forall_goto_program_instructions(target, goto_program) + { + if(target->is_function_call()) + { + code_function_callt &function_call=to_code_function_call(target->code); + + if(function_call.function().id()==ID_symbol) + { + const irep_idt &function_id= + to_symbol_expr(function_call.function()).get_identifier(); + std::string signature=function_signature(function_id); + auto it=string_functions.find(function_id); + if(it!=string_functions.end()) + make_string_function( + goto_program, target, it->second, signature, false, false); + + it=side_effect_functions.find(function_id); + if(it!=side_effect_functions.end()) + make_string_function_side_effect( + goto_program, target, it->second, signature); + + it=string_function_calls.find(function_id); + if(it!=string_function_calls.end()) + make_string_function_call( + goto_program, target, it->second, signature); + + if(function_id==irep_idt("java::java.lang.String.toCharArray:()[C")) + make_to_char_array_function(goto_program, target); + } + } + else + { + if(target->is_assign()) + { + // In assignments we replace string literals and C string functions + code_assignt assignment=to_code_assign(target->code); + + exprt new_rhs=assignment.rhs(); + code_assignt new_assignment(assignment.lhs(), new_rhs); + + exprt uncasted=new_rhs; + + if(uncasted.id()==ID_typecast) + uncasted=to_typecast_expr(uncasted).op0(); + + if(new_rhs.id()==ID_function_application) + { + function_application_exprt f=to_function_application_expr(new_rhs); + const exprt &name=f.function(); + assert(name.id()==ID_symbol); + const irep_idt &id=to_symbol_expr(name).get_identifier(); + auto it=c_string_functions.find(id); + if(it!=c_string_functions.end()) + { + declare_function(it->second, f.type()); + f.function()=symbol_exprt(it->second); + new_assignment=code_assignt(assignment.lhs(), f); + } + } + + new_assignment.add_source_location()=assignment.source_location(); + target->make_assignment(); + target->code=new_assignment; + } + } + } + return; +} + +/*******************************************************************\ + +Function: string_refine_preprocesst::initialize_string_function_table + + Purpose: fill maps with correspondance from java method names to cprover + functions + +\*******************************************************************/ + +void string_refine_preprocesst::initialize_string_function_table() +{ + string_functions["java::java.lang.String.codePointAt:(I)I"]= + ID_cprover_string_code_point_at_func; + string_functions["java::java.lang.String.codePointBefore:(I)I"]= + ID_cprover_string_code_point_before_func; + string_functions["java::java.lang.String.codePointCount:(II)I"]= + ID_cprover_string_code_point_count_func; + string_functions["java::java.lang.String.offsetByCodePoints:(II)I"]= + ID_cprover_string_offset_by_code_point_func; + string_functions["java::java.lang.String.hashCode:()I"]= + ID_cprover_string_hash_code_func; + string_functions["java::java.lang.String.indexOf:(I)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.indexOf:(II)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.indexOf:(Ljava/lang/String;)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.indexOf:(Ljava/lang/String;I)I"]= + ID_cprover_string_index_of_func; + string_functions["java::java.lang.String.lastIndexOf:(I)I"]= + ID_cprover_string_last_index_of_func; + string_functions["java::java.lang.String.lastIndexOf:(II)I"]= + ID_cprover_string_last_index_of_func; + string_functions + ["java::java.lang.String.lastIndexOf:(Ljava/lang/String;)I"]= + ID_cprover_string_last_index_of_func; + string_functions + ["java::java.lang.String.lastIndexOf:(Ljava/lang/String;I)I"]= + ID_cprover_string_last_index_of_func; + string_functions + ["java::java.lang.String.concat:(Ljava/lang/String;)Ljava/lang/String;"]= + ID_cprover_string_concat_func; + string_functions["java::java.lang.String.length:()I"]= + ID_cprover_string_length_func; + string_functions["java::java.lang.StringBuilder.length:()I"]= + ID_cprover_string_length_func; + string_functions["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]= + ID_cprover_string_equal_func; + string_functions + ["java::java.lang.String.equalsIgnoreCase:(Ljava/lang/String;)Z"]= + ID_cprover_string_equals_ignore_case_func; + string_functions["java::java.lang.String.startsWith:(Ljava/lang/String;)Z"]= + ID_cprover_string_startswith_func; + string_functions + ["java::java.lang.String.startsWith:(Ljava/lang/String;I)Z"]= + ID_cprover_string_startswith_func; + string_functions["java::java.lang.String.endsWith:(Ljava/lang/String;)Z"]= + ID_cprover_string_endswith_func; + string_functions["java::java.lang.String.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions["java::java.lang.String.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions["java::java.lang.String.substring:(I)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.StringBuilder.substring:(II)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.StringBuilder.substring:(I)Ljava/lang/String;"]= + ID_cprover_string_substring_func; + string_functions + ["java::java.lang.String.subSequence:(II)Ljava/lang/CharSequence;"]= + ID_cprover_string_substring_func; + string_functions["java::java.lang.String.trim:()Ljava/lang/String;"]= + ID_cprover_string_trim_func; + string_functions["java::java.lang.String.toLowerCase:()Ljava/lang/String;"]= + ID_cprover_string_to_lower_case_func; + string_functions["java::java.lang.String.toUpperCase:()Ljava/lang/String;"]= + ID_cprover_string_to_upper_case_func; + string_functions["java::java.lang.String.replace:(CC)Ljava/lang/String;"]= + ID_cprover_string_replace_func; + string_functions + ["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= + ID_cprover_string_contains_func; + string_functions["java::java.lang.String.compareTo:(Ljava/lang/String;)I"]= + ID_cprover_string_compare_to_func; + string_functions["java::java.lang.String.intern:()Ljava/lang/String;"]= + ID_cprover_string_intern_func; + string_functions["java::java.lang.String.isEmpty:()Z"]= + ID_cprover_string_is_empty_func; + string_functions["java::java.lang.String.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.StringBuilder.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions["java::java.lang.CharSequence.charAt:(I)C"]= + ID_cprover_string_char_at_func; + string_functions + ["java::java.lang.StringBuilder.toString:()Ljava/lang/String;"]= + ID_cprover_string_copy_func; + + string_functions["java::java.lang.String.valueOf:(F)Ljava/lang/String;"]= + ID_cprover_string_of_float_func; + string_functions["java::java.lang.Float.toString:(F)Ljava/lang/String;"]= + ID_cprover_string_of_float_func; + string_functions["java::java.lang.Integer.toString:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_func; + string_functions["java::java.lang.String.valueOf:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_func; + string_functions["java::java.lang.Integer.toHexString:(I)Ljava/lang/String;"]= + ID_cprover_string_of_int_hex_func; + string_functions["java::java.lang.String.valueOf:(L)Ljava/lang/String;"]= + ID_cprover_string_of_long_func; + string_functions["java::java.lang.String.valueOf:(D)Ljava/lang/String;"]= + ID_cprover_string_of_double_func; + string_functions["java::java.lang.String.valueOf:(Z)Ljava/lang/String;"]= + ID_cprover_string_of_bool_func; + string_functions["java::java.lang.String.valueOf:(C)Ljava/lang/String;"]= + ID_cprover_string_of_char_func; + string_functions["java::java.lang.Integer.parseInt:(Ljava/lang/String;)I"]= + ID_cprover_string_parse_int_func; + + side_effect_functions + ["java::java.lang.StringBuilder.append:(Ljava/lang/String;)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_func; + side_effect_functions["java::java.lang.StringBuilder.setCharAt:(IC)V"]= + ID_cprover_string_char_set_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(I)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_int_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(J)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_long_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(Z)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_bool_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(C)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_char_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(D)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_double_func; + side_effect_functions + ["java::java.lang.StringBuilder.append:(F)Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_float_func; + side_effect_functions + ["java::java.lang.StringBuilder.appendCodePoint:(I)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_code_point_func; + side_effect_functions + ["java::java.lang.StringBuilder.delete:(II)Ljava/lang/StringBuilder;"]= + ID_cprover_string_delete_func; + side_effect_functions + ["java::java.lang.StringBuilder.deleteCharAt:(I)Ljava/lang/StringBuilder;"]= + ID_cprover_string_delete_char_at_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(II)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_int_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IJ)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_long_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IC)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_char_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(IZ)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_bool_func; + side_effect_functions + ["java::java.lang.StringBuilder.setLength:(I)V"]= + ID_cprover_string_set_length_func; + + + + side_effect_functions + ["java::java.lang.StringBuilder.append:([C)" + "Ljava/lang/StringBuilder;"]= + ID_cprover_string_concat_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(I[CII)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_func; + side_effect_functions + ["java::java.lang.StringBuilder.insert:(I[C)Ljava/lang/StringBuilder;"]= + ID_cprover_string_insert_func; + // TODO clean irep ids from insert_char_array etc... + + string_function_calls + ["java::java.lang.String.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls + ["java::java.lang.String.:(Ljava/lang/StringBuilder;)V"]= + ID_cprover_string_copy_func; + string_function_calls + ["java::java.lang.StringBuilder.:(Ljava/lang/String;)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:()V"]= + ID_cprover_string_empty_string_func; + string_function_calls["java::java.lang.StringBuilder.:()V"]= + ID_cprover_string_empty_string_func; + + string_function_calls["java::java.lang.String.:([C)V"]= + ID_cprover_string_copy_func; + string_function_calls["java::java.lang.String.:([CII)V"]= + ID_cprover_string_copy_func; + + string_functions + ["java::java.lang.String.valueOf:([CII)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + string_functions + ["java::java.lang.String.valueOf:([C)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + string_functions + ["java::java.lang.String.copyValueOf:([CII)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + string_functions + ["java::java.lang.String.copyValueOf:([C)Ljava/lang/String;"]= + ID_cprover_string_copy_func; + + c_string_functions["__CPROVER_uninterpreted_string_literal_func"]= + ID_cprover_string_literal_func; + c_string_functions["__CPROVER_uninterpreted_string_char_at_func"]= + ID_cprover_string_char_at_func; + c_string_functions["__CPROVER_uninterpreted_string_equal_func"]= + ID_cprover_string_equal_func; + c_string_functions["__CPROVER_uninterpreted_string_concat_func"]= + ID_cprover_string_concat_func; + c_string_functions["__CPROVER_uninterpreted_string_length_func"]= + ID_cprover_string_length_func; + c_string_functions["__CPROVER_uninterpreted_string_substring_func"]= + ID_cprover_string_substring_func; + c_string_functions["__CPROVER_uninterpreted_string_is_prefix_func"]= + ID_cprover_string_is_prefix_func; + c_string_functions["__CPROVER_uninterpreted_string_is_suffix_func"]= + ID_cprover_string_is_suffix_func; + c_string_functions["__CPROVER_uninterpreted_string_contains_func"]= + ID_cprover_string_contains_func; + c_string_functions["__CPROVER_uninterpreted_string_index_of_func"]= + ID_cprover_string_index_of_func; + c_string_functions["__CPROVER_uninterpreted_string_last_index_of_func"]= + ID_cprover_string_last_index_of_func; + c_string_functions["__CPROVER_uninterpreted_string_char_set_func"]= + ID_cprover_string_char_set_func; + c_string_functions["__CPROVER_uninterpreted_string_copy_func"]= + ID_cprover_string_copy_func; + c_string_functions["__CPROVER_uninterpreted_string_parse_int_func"]= + ID_cprover_string_parse_int_func; + c_string_functions["__CPROVER_uninterpreted_string_of_int_func"]= + ID_cprover_string_of_int_func; + + signatures["java::java.lang.String.equals:(Ljava/lang/Object;)Z"]="SSZ"; + signatures["java::java.lang.String.contains:(Ljava/lang/CharSequence;)Z"]= + "SSZ"; + signatures["java::java.lang.StringBuilder.insert:(IZ)" + "Ljava/lang/StringBuilder;"]="SIZS"; + signatures["java::java.lang.StringBuilder.insert:(IJ)" + "Ljava/lang/StringBuilder;"]="SIJS"; + signatures["java::java.lang.StringBuilder.insert:(II)" + "Ljava/lang/StringBuilder;"]="SIIS"; + signatures["java::java.lang.StringBuilder.insert:(IC)" + "Ljava/lang/StringBuilder;"]="SICS"; + signatures["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]="SISS"; + signatures["java::java.lang.StringBuilder.insert:(ILjava/lang/String;)" + "Ljava/lang/StringBuilder;"]="SISS"; + signatures["java::java.lang.StringBuilder.insert:(I[C)" + "Ljava/lang/StringBuilder;"]="SI[S"; + signatures["java::java.lang.String.intern:()Ljava/lang/String;"]="SV"; +} + +/*******************************************************************\ + +Constructor: string_refine_preprocesst::string_refine_preprocesst + + Inputs: a symbol table, goto functions, a message handler + + Purpose: process the goto function by replacing calls to string functions + +\*******************************************************************/ + +string_refine_preprocesst::string_refine_preprocesst( + symbol_tablet &_symbol_table, + goto_functionst &_goto_functions, + message_handlert &_message_handler): + messaget(_message_handler), + ns(_symbol_table), + symbol_table(_symbol_table), + goto_functions(_goto_functions), + next_symbol_id(0), + jls_ptr(symbol_typet("java::java.lang.String")) +{ + initialize_string_function_table(); + Forall_goto_functions(it, goto_functions) + replace_string_calls(it); +} diff --git a/src/goto-programs/string_refine_preprocess.h b/src/goto-programs/string_refine_preprocess.h new file mode 100644 index 00000000000..065a86e968f --- /dev/null +++ b/src/goto-programs/string_refine_preprocess.h @@ -0,0 +1,198 @@ +/*******************************************************************\ + +Module: Preprocess a goto-programs so that calls to the java String + library are recognized by the PASS algorithm + +Author: Romain Brenguier + +Date: September 2016 + +\*******************************************************************/ + +#ifndef CPROVER_GOTO_PROGRAMS_STRING_REFINE_PREPROCESS_H +#define CPROVER_GOTO_PROGRAMS_STRING_REFINE_PREPROCESS_H + +#include +#include +#include + +class string_refine_preprocesst:public messaget +{ + public: + string_refine_preprocesst( + symbol_tablet &, goto_functionst &, message_handlert &); + + private: + namespacet ns; + symbol_tablet & symbol_table; + goto_functionst & goto_functions; + + typedef std::unordered_map id_mapt; + typedef std::unordered_map expr_mapt; + + // Map name of Java string functions to there equivalent in the solver + id_mapt side_effect_functions; + id_mapt string_functions; + id_mapt c_string_functions; + id_mapt string_function_calls; + + std::unordered_map signatures; + + // unique id for each newly created symbols + int next_symbol_id; + + void initialize_string_function_table(); + + static bool check_java_type(const typet &type, const std::string &tag); + + static bool is_java_string_pointer_type(const typet &type); + + static bool is_java_string_type(const typet &type); + + static bool is_java_string_builder_type(const typet &type); + + static bool is_java_string_builder_pointer_type(const typet &type); + + static bool is_java_char_sequence_type(const typet &type); + + static bool is_java_char_sequence_pointer_type(const typet &type); + + static bool is_java_char_array_type(const typet &type); + + static bool is_java_char_array_pointer_type(const typet &type); + + static bool implements_java_char_sequence(const typet &type) + { + return + is_java_char_sequence_pointer_type(type) || + is_java_string_builder_pointer_type(type) || + is_java_string_pointer_type(type); + } + + symbol_exprt new_tmp_symbol(const std::string &name, const typet &type); + + symbol_exprt new_symbol( + const std::string &prefix, const typet &type, bool static_lifetime=true); + + // get the data member of a java string + static exprt get_data(const exprt &string, const typet &data_type) + { + return member_exprt(string, "data", data_type); + } + + // get the length member of a java string + exprt get_length(const exprt &string, const typet &length_type) + { + return member_exprt(string, "length", length_type); + } + + // type of pointers to string + pointer_typet jls_ptr; + exprt replace_string(const exprt &in); + exprt replace_string_in_assign(const exprt &in); + + void insert_assignments( + goto_programt &goto_program, + goto_programt::targett &target, + irep_idt function, + source_locationt location, + const std::list &va); + + exprt replace_string_pointer(const exprt &in); + + // Replace string builders by expression of the mapping and make + // assignments for strings as string_exprt + exprt::operandst process_arguments( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature=""); + + // Signature of the named function if it is defined in the signature map, + // empty string otherwise + std::string function_signature(const irep_idt &function_id); + + void declare_function(irep_idt function_name, const typet &type); + + void get_data_and_length_type_of_string( + const exprt &expr, typet &data_type, typet &length_type); + + void get_data_and_length_type_of_char_array( + const exprt &expr, typet &data_type, typet &length_type); + + function_application_exprt build_function_application( + const irep_idt &function_name, + const typet &type, + const source_locationt &location, + const exprt::operandst &arguments); + + void make_normal_assign( + goto_programt &goto_program, + goto_programt::targett target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature=""); + + void make_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature); + + exprt make_cprover_string_assign( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &rhs, + const source_locationt &location); + + string_exprt make_cprover_char_array_assign( + goto_programt &goto_program, + goto_programt::targett &i_it, + const exprt &rhs, + const source_locationt &location); + + void make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature, + bool assign_first_arg=false, + bool skip_first_arg=false); + + void make_string_function( + goto_programt &goto_program, + goto_programt::targett &target, + const exprt &lhs, + const code_typet &function_type, + const irep_idt &function_name, + const exprt::operandst &arguments, + const source_locationt &location, + const std::string &signature); + + void make_string_function_call( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature); + + void make_string_function_side_effect( + goto_programt &goto_program, + goto_programt::targett &target, + const irep_idt &function_name, + const std::string &signature); + + void make_to_char_array_function( + goto_programt &goto_program, goto_programt::targett &); + + void replace_string_calls(goto_functionst::function_mapt::iterator f_it); +}; + +#endif diff --git a/src/java_bytecode/java_bytecode_convert_class.cpp b/src/java_bytecode/java_bytecode_convert_class.cpp index f21b0bb1ce2..7f52c6ef77b 100644 --- a/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/src/java_bytecode/java_bytecode_convert_class.cpp @@ -50,7 +50,16 @@ class java_bytecode_convert_classt:public messaget convert(parse_tree.parsed_class); else if(string_refinement_enabled && parse_tree.parsed_class.name=="java.lang.String") - add_string_type(); + add_string_type("java.lang.String"); + else if(string_refinement_enabled && + parse_tree.parsed_class.name=="java.lang.StringBuilder") + add_string_type("java.lang.StringBuilder"); + else if(string_refinement_enabled && + parse_tree.parsed_class.name=="java.lang.CharSequence") + add_string_type("java.lang.CharSequence"); + else if(string_refinement_enabled && + parse_tree.parsed_class.name=="java.lang.StringBuffer") + add_string_type("java.lang.StringBuffer"); else generate_class_stub(parse_tree.parsed_class.name); } @@ -72,7 +81,7 @@ class java_bytecode_convert_classt:public messaget void generate_class_stub(const irep_idt &class_name); void add_array_types(); - void add_string_type(); + void add_string_type(const irep_idt &class_name); }; /*******************************************************************\ @@ -406,15 +415,17 @@ bool java_bytecode_convert_class( Function: java_bytecode_convert_classt::add_string_type + Inputs: a name for the class such as "java.lang.String" + Purpose: Implements the java.lang.String type in the case that we provide an internal implementation. \*******************************************************************/ -void java_bytecode_convert_classt::add_string_type() +void java_bytecode_convert_classt::add_string_type(const irep_idt &class_name) { class_typet string_type; - string_type.set_tag("java.lang.String"); + string_type.set_tag(class_name); string_type.components().resize(3); string_type.components()[0].set_name("@java.lang.Object"); string_type.components()[0].set_pretty_name("@java.lang.Object"); @@ -432,8 +443,8 @@ void java_bytecode_convert_classt::add_string_type() string_type.add_base(symbol_typet("java::java.lang.Object")); symbolt string_symbol; - string_symbol.name="java::java.lang.String"; - string_symbol.base_name="java.lang.String"; + string_symbol.name="java::"+id2string(class_name); + string_symbol.base_name=id2string(class_name); string_symbol.type=string_type; string_symbol.is_type=true; @@ -445,8 +456,8 @@ void java_bytecode_convert_classt::add_string_type() symbolt string_equals_symbol; string_equals_symbol.name= "java::java.lang.String.equals:(Ljava/lang/Object;)Z"; - string_equals_symbol.base_name="java.lang.String.equals"; - string_equals_symbol.pretty_name="java.lang.String.equals"; + string_equals_symbol.base_name=id2string(class_name)+".equals"; + string_equals_symbol.pretty_name=id2string(class_name)+".equals"; string_equals_symbol.mode=ID_java; code_typet string_equals_type; diff --git a/src/solvers/Makefile b/src/solvers/Makefile index 95ea7650274..136db5765c1 100644 --- a/src/solvers/Makefile +++ b/src/solvers/Makefile @@ -118,6 +118,17 @@ SRC = $(CHAFF_SRC) $(BOOLEFORCE_SRC) $(MINISAT_SRC) $(MINISAT2_SRC) \ floatbv/float_utils.cpp floatbv/float_bv.cpp \ refinement/bv_refinement_loop.cpp refinement/refine_arithmetic.cpp \ refinement/refine_arrays.cpp \ + refinement/string_refinement.cpp \ + refinement/string_constraint_generator_code_points.cpp \ + refinement/string_constraint_generator_comparison.cpp \ + refinement/string_constraint_generator_concat.cpp \ + refinement/string_constraint_generator_constants.cpp \ + refinement/string_constraint_generator_indexof.cpp \ + refinement/string_constraint_generator_insert.cpp \ + refinement/string_constraint_generator_main.cpp \ + refinement/string_constraint_generator_testing.cpp \ + refinement/string_constraint_generator_transformation.cpp \ + refinement/string_constraint_generator_valueof.cpp \ miniBDD/miniBDD.cpp INCLUDES += -I .. \ diff --git a/src/solvers/refinement/refined_string_type.cpp b/src/solvers/refinement/refined_string_type.cpp deleted file mode 100644 index 012d30eb8de..00000000000 --- a/src/solvers/refinement/refined_string_type.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/********************************************************************\ - -Module: Type for string expressions used by the string solver. - These string expressions contain a field `length`, of type - `index_type`, a field `content` of type `content_type`. - This module also defines functions to recognise the C and java - string types. - -Author: Romain Brenguier, romain.brenguier@diffblue.com - -\*******************************************************************/ - -#include - -#include "refined_string_type.h" - -/*******************************************************************\ - -Constructor: refined_string_typet::refined_string_typet - - Inputs: type of characters - -\*******************************************************************/ - -refined_string_typet::refined_string_typet( - const typet &index_type, const typet &char_type) -{ - infinity_exprt infinite_index(index_type); - array_typet char_array(char_type, infinite_index); - components().emplace_back("length", index_type); - components().emplace_back("content", char_array); -} - -/*******************************************************************\ - -Function: refined_string_typet::is_c_string_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of C strings - -\*******************************************************************/ - -bool refined_string_typet::is_c_string_type(const typet &type) -{ - return - type.id()==ID_struct && - to_struct_type(type).get_tag()==CPROVER_PREFIX"string"; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_string_pointer_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java string pointers - -\*******************************************************************/ - -bool refined_string_typet::is_java_string_pointer_type(const typet &type) -{ - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - return is_java_string_type(subtype); - } - return false; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_string_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java string - -\*******************************************************************/ - -bool refined_string_typet::is_java_string_type(const typet &type) -{ - if(type.id()==ID_symbol) - { - irep_idt tag=to_symbol_type(type).get_identifier(); - return tag=="java::java.lang.String"; - } - else if(type.id()==ID_struct) - { - irep_idt tag=to_struct_type(type).get_tag(); - return tag=="java.lang.String"; - } - return false; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_string_builder_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java string builder - -\*******************************************************************/ - -bool refined_string_typet::is_java_string_builder_type(const typet &type) -{ - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - if(subtype.id()==ID_struct) - { - irep_idt tag=to_struct_type(subtype).get_tag(); - return tag=="java.lang.StringBuilder"; - } - } - return false; -} - -/*******************************************************************\ - -Function: refined_string_typet::is_java_char_sequence_type - - Inputs: a type - - Outputs: Boolean telling whether the type is that of java char sequence - -\*******************************************************************/ - -bool refined_string_typet::is_java_char_sequence_type(const typet &type) -{ - if(type.id()==ID_pointer) - { - const pointer_typet &pt=to_pointer_type(type); - const typet &subtype=pt.subtype(); - if(subtype.id()==ID_struct) - { - const irep_idt &tag=to_struct_type(subtype).get_tag(); - return tag=="java.lang.CharSequence"; - } - } - return false; -} diff --git a/src/solvers/refinement/string_constraint.h b/src/solvers/refinement/string_constraint.h index 61a6f3ebdd6..1bb460349b7 100644 --- a/src/solvers/refinement/string_constraint.h +++ b/src/solvers/refinement/string_constraint.h @@ -15,7 +15,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #include #include -#include +#include class string_constraintt: public exprt { @@ -48,7 +48,6 @@ class string_constraintt: public exprt return operands()[4]; } - private: string_constraintt(); diff --git a/src/solvers/refinement/string_constraint_generator.h b/src/solvers/refinement/string_constraint_generator.h index 2a56f09fddd..d8f3f17326e 100644 --- a/src/solvers/refinement/string_constraint_generator.h +++ b/src/solvers/refinement/string_constraint_generator.h @@ -14,7 +14,8 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #define CPROVER_SOLVERS_REFINEMENT_STRING_CONSTRAINT_GENERATOR_H #include -#include +#include +#include #include class string_constraint_generatort @@ -25,9 +26,17 @@ class string_constraint_generatort // to the axiom list. string_constraint_generatort(): - mode(ID_unknown) + mode(ID_unknown), + max_string_length(-1), + force_printable_characters(false) { } + // Constraints on the maximal length of strings + int max_string_length; + + // Should we add constraints on the characters + bool force_printable_characters; + void set_mode(irep_idt _mode) { // only C and java modes supported @@ -65,21 +74,22 @@ class string_constraint_generatort symbol_exprt fresh_univ_index(const irep_idt &prefix, const typet &type); symbol_exprt fresh_boolean(const irep_idt &prefix); string_exprt fresh_string(const refined_string_typet &type); + string_exprt get_string_expr(const exprt &expr); + string_exprt convert_java_string_to_string_exprt( + const exprt &underlying); + plus_exprt plus_exprt_with_overflow_check(const exprt &op1, const exprt &op2); - // We maintain a map from symbols to strings. - std::map symbol_to_string; + // Maps unresolved symbols to the string_exprt that was created for them + std::map unresolved_symbols; - string_exprt find_or_add_string_of_symbol(const symbol_exprt &sym); + // Set of strings that have been created by the generator + std::set created_strings; - void assign_to_symbol( - const symbol_exprt &sym, const string_exprt &expr) - { - symbol_to_string[sym.get_identifier()]=expr; - } + string_exprt find_or_add_string_of_symbol( + const symbol_exprt &sym, + const refined_string_typet &ref_type); - string_exprt add_axioms_for_string_expr(const exprt &expr); - void set_string_symbol_equal_to_expr( - const symbol_exprt &sym, const exprt &str); + string_exprt add_axioms_for_refined_string(const exprt &expr); exprt add_axioms_for_function_application( const function_application_exprt &expr); @@ -96,8 +106,11 @@ class string_constraint_generatort const std::size_t MAX_FLOAT_LENGTH=15; const std::size_t MAX_DOUBLE_LENGTH=30; + std::map function_application_cache; + static irep_idt extract_java_string(const symbol_exprt &s); + void add_default_axioms(const string_exprt &s); exprt axiom_for_is_positive_index(const exprt &x); // The following functions add axioms for the returned value @@ -117,6 +130,9 @@ class string_constraint_generatort // The specification is partial: the actual value is not actually computed // but we ensure that hash codes of equal strings are equal. exprt add_axioms_for_hash_code(const function_application_exprt &f); + // To each string on which hash_code was called we associate a symbol + // representing the return value of the hash_code function. + std::map hash_code_of_string; exprt add_axioms_for_is_empty(const function_application_exprt &f); exprt add_axioms_for_is_prefix( @@ -224,7 +240,9 @@ class string_constraint_generatort // the start for negative number string_exprt add_axioms_from_float(const function_application_exprt &f); string_exprt add_axioms_from_float( - const exprt &f, bool double_precision=false); + const exprt &f, + const refined_string_typet &ref_type, + bool double_precision); // Add axioms corresponding to the String.valueOf(D) java function // TODO: the specifications is only partial @@ -253,6 +271,7 @@ class string_constraint_generatort string_exprt add_axioms_for_code_point( const exprt &code_point, const refined_string_typet &ref_type); string_exprt add_axioms_for_java_char_array(const exprt &char_array); + exprt add_axioms_for_char_pointer(const function_application_exprt &fun); string_exprt add_axioms_for_if(const if_exprt &expr); exprt add_axioms_for_char_literal(const function_application_exprt &f); @@ -270,6 +289,8 @@ class string_constraint_generatort const function_application_exprt &f); exprt add_axioms_for_parse_int(const function_application_exprt &f); + exprt add_axioms_for_correct_number_format( + const string_exprt &str, std::size_t max_size=10); exprt add_axioms_for_to_char_array(const function_application_exprt &f); exprt add_axioms_for_compare_to(const function_application_exprt &f); @@ -278,6 +299,9 @@ class string_constraint_generatort // string pointers symbol_exprt add_axioms_for_intern(const function_application_exprt &f); + // Pool used for the intern method + std::map intern_of_string; + // Tells which language is used. C and Java are supported irep_idt mode; @@ -293,14 +317,8 @@ class string_constraint_generatort exprt int_of_hex_char(const exprt &chr) const; exprt is_high_surrogate(const exprt &chr) const; exprt is_low_surrogate(const exprt &chr) const; - static exprt character_equals_ignore_case( + exprt character_equals_ignore_case( exprt char1, exprt char2, exprt char_a, exprt char_A, exprt char_Z); - - // Pool used for the intern method - std::map pool; - - // Used to determine whether hashcode should be equal - std::map hash; }; #endif diff --git a/src/solvers/refinement/string_constraint_generator_code_points.cpp b/src/solvers/refinement/string_constraint_generator_code_points.cpp index 7c035a0d3e4..16763dfc97c 100644 --- a/src/solvers/refinement/string_constraint_generator_code_points.cpp +++ b/src/solvers/refinement/string_constraint_generator_code_points.cpp @@ -160,17 +160,18 @@ exprt string_constraint_generatort::add_axioms_for_code_point_at( { typet return_type=f.type(); assert(return_type.id()==ID_signedbv); - string_exprt str=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt str=get_string_expr(args(f, 2)[0]); const exprt &pos=args(f, 2)[1]; symbol_exprt result=fresh_symbol("char", return_type); exprt index1=from_integer(1, str.length().type()); const exprt &char1=str[pos]; - const exprt &char2=str[plus_exprt(pos, index1)]; + const exprt &char2=str[plus_exprt_with_overflow_check(pos, index1)]; exprt char1_as_int=typecast_exprt(char1, return_type); exprt char2_as_int=typecast_exprt(char2, return_type); exprt pair=pair_value(char1_as_int, char2_as_int, return_type); - exprt is_low=is_low_surrogate(str[plus_exprt(pos, index1)]); + exprt is_low=is_low_surrogate( + str[plus_exprt_with_overflow_check(pos, index1)]); exprt return_pair=and_exprt(is_high_surrogate(str[pos]), is_low); axioms.push_back(implies_exprt(return_pair, equal_exprt(result, pair))); @@ -199,7 +200,7 @@ exprt string_constraint_generatort::add_axioms_for_code_point_before( typet return_type=f.type(); assert(return_type.id()==ID_signedbv); symbol_exprt result=fresh_symbol("char", return_type); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); const exprt &char1= str[minus_exprt(args[1], from_integer(2, str.length().type()))]; @@ -234,7 +235,7 @@ Function: string_constraint_generatort::add_axioms_for_code_point_count exprt string_constraint_generatort::add_axioms_for_code_point_count( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const exprt &begin=args(f, 3)[1]; const exprt &end=args(f, 3)[2]; const typet &return_type=f.type(); @@ -265,14 +266,15 @@ Function: string_constraint_generatort::add_axioms_for_offset_by_code_point exprt string_constraint_generatort::add_axioms_for_offset_by_code_point( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const exprt &index=args(f, 3)[1]; const exprt &offset=args(f, 3)[2]; const typet &return_type=f.type(); symbol_exprt result=fresh_symbol("offset_by_code_point", return_type); - exprt minimum=plus_exprt(index, offset); - exprt maximum=plus_exprt(index, plus_exprt(offset, offset)); + exprt minimum=plus_exprt_with_overflow_check(index, offset); + exprt maximum=plus_exprt_with_overflow_check( + index, plus_exprt_with_overflow_check(offset, offset)); axioms.push_back(binary_relation_exprt(result, ID_le, maximum)); axioms.push_back(binary_relation_exprt(result, ID_ge, minimum)); diff --git a/src/solvers/refinement/string_constraint_generator_comparison.cpp b/src/solvers/refinement/string_constraint_generator_comparison.cpp index 321282ee9c1..a51e2abe3cd 100644 --- a/src/solvers/refinement/string_constraint_generator_comparison.cpp +++ b/src/solvers/refinement/string_constraint_generator_comparison.cpp @@ -18,7 +18,9 @@ Function: string_constraint_generatort::add_axioms_for_equals Outputs: a expression of Boolean type Purpose: add axioms stating that the result is true exactly when the strings - represented by the arguments are equal + represented by the arguments are equal. + the variable ending in `witness_unequal` is -1 if the length differs + or an index at which the strings are different \*******************************************************************/ @@ -29,8 +31,8 @@ exprt string_constraint_generatort::add_axioms_for_equals( symbol_exprt eq=fresh_boolean("equal"); typecast_exprt tc_eq(eq, f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); + string_exprt s1=get_string_expr(args(f, 2)[0]); + string_exprt s2=get_string_expr(args(f, 2)[1]); typet index_type=s1.length().type(); // We want to write: @@ -54,9 +56,10 @@ exprt string_constraint_generatort::add_axioms_for_equals( binary_relation_exprt(witness, ID_lt, s1.length()), binary_relation_exprt(witness, ID_ge, zero)); and_exprt witnessing(bound_witness, notequal_exprt(s1[witness], s2[witness])); - implies_exprt a3( - not_exprt(eq), - or_exprt(notequal_exprt(s1.length(), s2.length()), witnessing)); + and_exprt diff_length( + notequal_exprt(s1.length(), s2.length()), + equal_exprt(witness, from_integer(-1, index_type))); + implies_exprt a3(not_exprt(eq), or_exprt(diff_length, witnessing)); axioms.push_back(a3); return tc_eq; @@ -92,8 +95,13 @@ exprt string_constraint_generatort::character_equals_ignore_case( // p3 : (is_up2&&'a'-'A'+char2=char1) equal_exprt p1(char1, char2); minus_exprt diff=minus_exprt(char_a, char_A); - and_exprt p2(is_upper_case_1, equal_exprt(plus_exprt(diff, char1), char2)); - and_exprt p3(is_upper_case_2, equal_exprt(plus_exprt(diff, char2), char1)); + + // Overflow is not a problem here because is_upper_case conditions + // ensure that we are within a safe range. + and_exprt p2(is_upper_case_1, + equal_exprt(plus_exprt(diff, char1), char2)); + and_exprt p3(is_upper_case_2, + equal_exprt(plus_exprt(diff, char2), char1)); return or_exprt(or_exprt(p1, p2), p3); } @@ -116,8 +124,8 @@ exprt string_constraint_generatort::add_axioms_for_equals_ignore_case( symbol_exprt eq=fresh_boolean("equal_ignore_case"); typecast_exprt tc_eq(eq, f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); + string_exprt s1=get_string_expr(args(f, 2)[0]); + string_exprt s2=get_string_expr(args(f, 2)[1]); typet char_type=to_refined_string_type(s1.type()).get_char_type(); exprt char_a=constant_char('a', char_type); exprt char_A=constant_char('A', char_type); @@ -174,37 +182,35 @@ Function: string_constraint_generatort::add_axioms_for_hash_code exprt string_constraint_generatort::add_axioms_for_hash_code( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); typet return_type=f.type(); typet index_type=str.length().type(); - // initialisation of the missing pool variable - std::map::iterator it; - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) - if(hash.find(it->second)==hash.end()) - hash[it->second]=fresh_symbol("hash", return_type); + auto pair=hash_code_of_string.insert( + std::make_pair(str, fresh_symbol("hash", return_type))); + exprt hash=pair.first->second; // for each string s. either: // c1: hash(str)=hash(s) // c2: |str|!=|s| - // c3: (|str|==|s| &&exists i<|s|. s[i]!=str[i]) + // c3: (|str|==|s| && exists i<|s|. s[i]!=str[i]) // WARNING: the specification may be incomplete - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) + for(auto it : hash_code_of_string) { symbol_exprt i=fresh_exist_index("index_hash", index_type); - equal_exprt c1(hash[it->second], hash[str]); - not_exprt c2(equal_exprt(it->second.length(), str.length())); + equal_exprt c1(it.second, hash); + not_exprt c2(equal_exprt(it.first.length(), str.length())); and_exprt c3( - equal_exprt(it->second.length(), str.length()), + equal_exprt(it.first.length(), str.length()), and_exprt( - not_exprt(equal_exprt(str[i], it->second[i])), + not_exprt(equal_exprt(str[i], it.first[i])), and_exprt( str.axiom_for_is_strictly_longer_than(i), axiom_for_is_positive_index(i)))); axioms.push_back(or_exprt(c1, or_exprt(c2, c3))); } - return hash[str]; + return hash; } /*******************************************************************\ @@ -222,8 +228,8 @@ Function: string_constraint_generatort::add_axioms_for_compare_to exprt string_constraint_generatort::add_axioms_for_compare_to( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 2)[1]); + string_exprt s1=get_string_expr(args(f, 2)[0]); + string_exprt s2=get_string_expr(args(f, 2)[1]); const typet &return_type=f.type(); symbol_exprt res=fresh_symbol("compare_to", return_type); typet index_type=s1.length().type(); @@ -234,12 +240,12 @@ exprt string_constraint_generatort::add_axioms_for_compare_to( // a1 : res==0 => |s1|=|s2| // a2 : forall i<|s1|. s1[i]==s2[i] // a3 : exists x. - // res!=0 ==> x> 0 && - // ((|s1| <= |s2| &&x<|s1|) || (|s1| >= |s2| &&x<|s2|) - // &&res=s1[x]-s2[x] ) - // || cond2: - // (|s1|<|s2| &&x=|s1|) || (|s1| > |s2| &&x=|s2|) &&res=|s1|-|s2|) - // a4 : forall i s1[i]=s2[i] + // res!=0 ==> x > 0 + // && ((|s1| <= |s2| && x<|s1|) || (|s1| >= |s2| &&x<|s2|) + // && res=s1[x]-s2[x] ) + // || cond2: + // (|s1|<|s2| &&x=|s1|) || (|s1| > |s2| &&x=|s2|) &&res=|s1|-|s2|) + // a4 : forall i' s1[i]=s2[i] assert(return_type.id()==ID_signedbv); @@ -282,7 +288,9 @@ exprt string_constraint_generatort::add_axioms_for_compare_to( or_exprt(cond1, cond2))); axioms.push_back(a3); - string_constraintt a4(i, x, not_exprt(res_null), equal_exprt(s1[i], s2[i])); + symbol_exprt i2=fresh_univ_index("QA_compare_to", index_type); + string_constraintt a4( + i2, x, not_exprt(res_null), equal_exprt(s1[i2], s2[i2])); axioms.push_back(a4); return res; @@ -304,15 +312,15 @@ Function: string_constraint_generatort::add_axioms_for_intern symbol_exprt string_constraint_generatort::add_axioms_for_intern( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); + // For now we only enforce content equality and not pointer equality const typet &return_type=f.type(); + typet index_type=str.length().type(); - // initialisation of the missing pool variable - std::map::iterator it; - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) - if(pool.find(it->second)==pool.end()) - pool[it->second]=fresh_symbol("pool", return_type); + auto pair=intern_of_string.insert( + std::make_pair(str, fresh_symbol("pool", return_type))); + symbol_exprt intern=pair.first->second; // intern(str)=s_0 || s_1 || ... // for each string s. @@ -320,30 +328,30 @@ symbol_exprt string_constraint_generatort::add_axioms_for_intern( // || (|str|==|s| &&exists i<|s|. s[i]!=str[i]) exprt disj=false_exprt(); - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) + for(auto it : intern_of_string) disj=or_exprt( - disj, equal_exprt(pool[str], symbol_exprt(it->first, return_type))); + disj, equal_exprt(intern, it.second)); axioms.push_back(disj); // WARNING: the specification may be incomplete or incorrect - for(it=symbol_to_string.begin(); it!=symbol_to_string.end(); it++) - if(it->second!=str) + for(auto it : intern_of_string) + if(it.second!=str) { symbol_exprt i=fresh_exist_index("index_intern", index_type); axioms.push_back( or_exprt( - equal_exprt(pool[it->second], pool[str]), + equal_exprt(it.second, intern), or_exprt( - not_exprt(str.axiom_for_has_same_length_as(it->second)), + not_exprt(str.axiom_for_has_same_length_as(it.first)), and_exprt( - str.axiom_for_has_same_length_as(it->second), + str.axiom_for_has_same_length_as(it.first), and_exprt( - not_exprt(equal_exprt(str[i], it->second[i])), + not_exprt(equal_exprt(str[i], it.first[i])), and_exprt(str.axiom_for_is_strictly_longer_than(i), axiom_for_is_positive_index(i))))))); } - return pool[str]; + return intern; } diff --git a/src/solvers/refinement/string_constraint_generator_concat.cpp b/src/solvers/refinement/string_constraint_generator_concat.cpp index a7d9c4921c4..eb841cc5b04 100644 --- a/src/solvers/refinement/string_constraint_generator_concat.cpp +++ b/src/solvers/refinement/string_constraint_generator_concat.cpp @@ -35,8 +35,7 @@ string_exprt string_constraint_generatort::add_axioms_for_concat( // a4 : forall i<|s1|. res[i]=s1[i] // a5 : forall i<|s2|. res[i+|s1|]=s2[i] - exprt a1=res.axiom_for_has_length( - plus_exprt(s1.length(), s2.length())); + equal_exprt a1(res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length())); axioms.push_back(a1); axioms.push_back(s1.axiom_for_is_shorter_than(res)); axioms.push_back(s2.axiom_for_is_shorter_than(res)); @@ -73,8 +72,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat( const function_application_exprt::argumentst &args=f.arguments(); assert(args.size()==2); - string_exprt s1=add_axioms_for_string_expr(args[0]); - string_exprt s2=add_axioms_for_string_expr(args[1]); + string_exprt s1=get_string_expr(args[0]); + string_exprt s2=get_string_expr(args[1]); return add_axioms_for_concat(s1, s2); } @@ -95,7 +94,7 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_int( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_from_int( args(f, 2)[1], MAX_INTEGER_LENGTH, ref_type); return add_axioms_for_concat(s1, s2); @@ -118,7 +117,7 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_long( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); string_exprt s2=add_axioms_from_int(args(f, 2)[1], MAX_LONG_LENGTH, ref_type); return add_axioms_for_concat(s1, s2); } @@ -138,7 +137,7 @@ Function: string_constraint_generatort::add_axioms_for_concat_bool string_exprt string_constraint_generatort::add_axioms_for_concat_bool( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_from_bool(args(f, 2)[1], ref_type); return add_axioms_for_concat(s1, s2); @@ -159,7 +158,7 @@ Function: string_constraint_generatort::add_axioms_for_concat_char string_exprt string_constraint_generatort::add_axioms_for_concat_char( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_from_char(args(f, 2)[1], ref_type); return add_axioms_for_concat(s1, s2); @@ -180,9 +179,10 @@ Function: string_constraint_generatort::add_axioms_for_concat_double string_exprt string_constraint_generatort::add_axioms_for_concat_double( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_from_float( - args(f, 2)[1], MAX_DOUBLE_LENGTH); + string_exprt s1=get_string_expr(args(f, 2)[0]); + assert(refined_string_typet::is_refined_string_type(f.type())); + refined_string_typet ref_type=to_refined_string_type(f.type()); + string_exprt s2=add_axioms_from_float(args(f, 2)[1], ref_type, true); return add_axioms_for_concat(s1, s2); } @@ -201,8 +201,10 @@ Function: string_constraint_generatort::add_axioms_for_concat_float string_exprt string_constraint_generatort::add_axioms_for_concat_float( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s2=add_axioms_from_float(args(f, 2)[1], MAX_FLOAT_LENGTH); + string_exprt s1=get_string_expr(args(f, 2)[0]); + assert(refined_string_typet::is_refined_string_type(f.type())); + refined_string_typet ref_type=to_refined_string_type(f.type()); + string_exprt s2=add_axioms_from_float(args(f, 2)[1], ref_type, false); return add_axioms_for_concat(s1, s2); } @@ -222,7 +224,7 @@ Function: string_constraint_generatort::add_axioms_for_concat_code_point string_exprt string_constraint_generatort::add_axioms_for_concat_code_point( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_for_code_point(args(f, 2)[1], ref_type); return add_axioms_for_concat(s1, s2); diff --git a/src/solvers/refinement/string_constraint_generator_constants.cpp b/src/solvers/refinement/string_constraint_generator_constants.cpp index 90769747949..2905c6a5f21 100644 --- a/src/solvers/refinement/string_constraint_generator_constants.cpp +++ b/src/solvers/refinement/string_constraint_generator_constants.cpp @@ -93,9 +93,13 @@ string_exprt string_constraint_generatort::add_axioms_for_empty_string( const function_application_exprt &f) { assert(f.arguments().empty()); + assert(refined_string_typet::is_refined_string_type(f.type())); const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt res=fresh_string(ref_type); - axioms.push_back(res.axiom_for_has_length(0)); + exprt size=from_integer(0, ref_type.get_index_type()); + const array_typet &content_type=ref_type.get_content_type(); + array_of_exprt empty_array( + from_integer(0, ref_type.get_content_type().subtype()), content_type); + string_exprt res(size, empty_array, ref_type); return res; } @@ -132,7 +136,8 @@ string_exprt string_constraint_generatort::add_axioms_from_literal( else { // Java string constant - assert(refined_string_typet::is_unrefined_string_type(arg.type())); + assert(false); // TODO: Check if used. On the contrary, discard else. + assert(arg.id()==ID_symbol); const exprt &s=arg.op0(); // It seems the value of the string is lost, diff --git a/src/solvers/refinement/string_constraint_generator_indexof.cpp b/src/solvers/refinement/string_constraint_generator_indexof.cpp index 93db048458b..d799091a573 100644 --- a/src/solvers/refinement/string_constraint_generator_indexof.cpp +++ b/src/solvers/refinement/string_constraint_generator_indexof.cpp @@ -92,15 +92,16 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string( symbol_exprt contains=fresh_boolean("contains_substring"); // We add axioms: - // a1 : contains => |substring|>=offset>=from_index + // a1 : contains => |str|-|substring|>=offset>=from_index // a2 : !contains => offset=-1 - // a3 : forall 0 <= witness str[witness+offset]=substring[witness] + // a3 : forall 0<=witness<|substring|. + // contains => str[witness+offset]=substring[witness] implies_exprt a1( contains, and_exprt( - str.axiom_for_is_longer_than(plus_exprt(substring.length(), offset)), + str.axiom_for_is_longer_than(plus_exprt_with_overflow_check( + substring.length(), offset)), binary_relation_exprt(offset, ID_ge, from_index))); axioms.push_back(a1); @@ -138,7 +139,8 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of_string( implies_exprt a1( contains, and_exprt( - str.axiom_for_is_longer_than(plus_exprt(substring.length(), offset)), + str.axiom_for_is_longer_than( + plus_exprt_with_overflow_check(substring.length(), offset)), binary_relation_exprt(offset, ID_le, from_index))); axioms.push_back(a1); @@ -173,7 +175,7 @@ exprt string_constraint_generatort::add_axioms_for_index_of( const function_application_exprt &f) { const function_application_exprt::argumentst &args=f.arguments(); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); const exprt &c=args[1]; const refined_string_typet &ref_type=to_refined_string_type(str.type()); assert(f.type()==ref_type.get_index_type()); @@ -186,14 +188,17 @@ exprt string_constraint_generatort::add_axioms_for_index_of( else assert(false); - if(refined_string_typet::is_java_string_pointer_type(c.type())) + if(c.type().id()==ID_unsignedbv || c.type().id()==ID_signedbv) { - string_exprt sub=add_axioms_for_string_expr(c); - return add_axioms_for_index_of_string(str, sub, from_index); - } - else return add_axioms_for_index_of( str, typecast_exprt(c, ref_type.get_char_type()), from_index); + } + else + { + assert(refined_string_typet::is_refined_string_type(c.type())); + string_exprt sub=get_string_expr(c); + return add_axioms_for_index_of_string(str, sub, from_index); + } } exprt string_constraint_generatort::add_axioms_for_last_index_of( @@ -213,7 +218,7 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( exprt index1=from_integer(1, index_type); exprt minus1=from_integer(-1, index_type); - exprt from_index_plus_one=plus_exprt(from_index, index1); + exprt from_index_plus_one=plus_exprt_with_overflow_check(from_index, index1); and_exprt a1( binary_relation_exprt(index, ID_ge, minus1), binary_relation_exprt(index, ID_lt, from_index_plus_one)); @@ -267,7 +272,7 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( const function_application_exprt &f) { const function_application_exprt::argumentst &args=f.arguments(); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); exprt c=args[1]; const refined_string_typet &ref_type=to_refined_string_type(str.type()); exprt from_index; @@ -280,12 +285,14 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of( else assert(false); - if(refined_string_typet::is_java_string_pointer_type(c.type())) + if(c.type().id()==ID_unsignedbv || c.type().id()==ID_signedbv) { - string_exprt sub=add_axioms_for_string_expr(c); - return add_axioms_for_last_index_of_string(str, sub, from_index); - } - else return add_axioms_for_last_index_of( str, typecast_exprt(c, ref_type.get_char_type()), from_index); + } + else + { + string_exprt sub=get_string_expr(c); + return add_axioms_for_last_index_of_string(str, sub, from_index); + } } diff --git a/src/solvers/refinement/string_constraint_generator_insert.cpp b/src/solvers/refinement/string_constraint_generator_insert.cpp index 6a080a5dc6c..cd5f4376a93 100644 --- a/src/solvers/refinement/string_constraint_generator_insert.cpp +++ b/src/solvers/refinement/string_constraint_generator_insert.cpp @@ -48,8 +48,8 @@ Function: string_constraint_generatort::add_axioms_for_insert string_exprt string_constraint_generatort::add_axioms_for_insert( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); - string_exprt s2=add_axioms_for_string_expr(args(f, 3)[2]); + string_exprt s1=get_string_expr(args(f, 3)[0]); + string_exprt s2=get_string_expr(args(f, 3)[2]); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -70,7 +70,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_int( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); string_exprt s2=add_axioms_from_int( args(f, 3)[2], MAX_INTEGER_LENGTH, ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); @@ -93,7 +93,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_long( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); string_exprt s2=add_axioms_from_int(args(f, 3)[2], MAX_LONG_LENGTH, ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -115,7 +115,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_bool( const function_application_exprt &f) { const refined_string_typet &ref_type=to_refined_string_type(f.type()); - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); string_exprt s2=add_axioms_from_bool(args(f, 3)[2], ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -136,7 +136,7 @@ Function: string_constraint_generatort::add_axioms_for_insert_char string_exprt string_constraint_generatort::add_axioms_for_insert_char( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt s1=get_string_expr(args(f, 3)[0]); const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt s2=add_axioms_from_char(args(f, 3)[2], ref_type); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); @@ -158,8 +158,9 @@ Function: string_constraint_generatort::add_axioms_for_insert_double string_exprt string_constraint_generatort::add_axioms_for_insert_double( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); - string_exprt s2=add_axioms_from_float(args(f, 3)[2]); + string_exprt s1=get_string_expr(args(f, 3)[0]); + const refined_string_typet &ref_type=to_refined_string_type(s1.type()); + string_exprt s2=add_axioms_from_float(args(f, 3)[2], ref_type, true); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -179,8 +180,9 @@ Function: string_constraint_generatort::add_axioms_for_insert_float string_exprt string_constraint_generatort::add_axioms_for_insert_float( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 3)[0]); - string_exprt s2=add_axioms_from_float(args(f, 3)[2]); + string_exprt s1=get_string_expr(args(f, 3)[0]); + const refined_string_typet &ref_type=to_refined_string_type(s1.type()); + string_exprt s2=add_axioms_from_float(args(f, 3)[2], ref_type, false); return add_axioms_for_insert(s1, s2, args(f, 3)[1]); } @@ -216,7 +218,7 @@ string_exprt string_constraint_generatort::add_axioms_for_insert_char_array( offset=from_integer(0, count.type()); } - string_exprt str=add_axioms_for_string_expr(f.arguments()[0]); + string_exprt str=get_string_expr(f.arguments()[0]); const exprt &length=f.arguments()[2]; const exprt &data=f.arguments()[3]; string_exprt arr=add_axioms_from_char_array( diff --git a/src/solvers/refinement/string_constraint_generator_main.cpp b/src/solvers/refinement/string_constraint_generator_main.cpp index 5a269e5ad3b..1b94d05a462 100644 --- a/src/solvers/refinement/string_constraint_generator_main.cpp +++ b/src/solvers/refinement/string_constraint_generator_main.cpp @@ -16,6 +16,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com #include #include #include +#include unsigned string_constraint_generatort::next_symbol_id=1; @@ -122,6 +123,42 @@ symbol_exprt string_constraint_generatort::fresh_boolean( /*******************************************************************\ +Function: string_constraint_generatort::plus_exprt_with_overflow_check + + Inputs: + op1 - First term of the sum + op2 - Second term of the sum + + Outputs: A plus expression representing the sum of the arguments + + Purpose: Create a plus expression while adding extra constraints to + axioms in order to prevent overflows. + +\*******************************************************************/ +plus_exprt string_constraint_generatort::plus_exprt_with_overflow_check( + const exprt &op1, const exprt &op2) +{ + plus_exprt sum(plus_exprt(op1, op2)); + + exprt zero=from_integer(0, op1.type()); + + binary_relation_exprt neg1(op1, ID_lt, zero); + binary_relation_exprt neg2(op2, ID_lt, zero); + binary_relation_exprt neg_sum(sum, ID_lt, zero); + + // We prevent overflows by adding the following constraint: + // If the signs of the two operands are the same, then the sign of the sum + // should also be the same. + implies_exprt no_overflow(equal_exprt(neg1, neg2), + equal_exprt(neg1, neg_sum)); + + axioms.push_back(no_overflow); + + return sum; +} + +/*******************************************************************\ + Function: string_constraint_generatort::fresh_string Inputs: a type for string @@ -136,67 +173,157 @@ Function: string_constraint_generatort::fresh_string string_exprt string_constraint_generatort::fresh_string( const refined_string_typet &type) { - symbol_exprt length= - fresh_symbol("string_length", type.get_index_type()); + symbol_exprt length=fresh_symbol("string_length", type.get_index_type()); symbol_exprt content=fresh_symbol("string_content", type.get_content_type()); - return string_exprt(length, content, type); + string_exprt str(length, content, type); + created_strings.insert(str); + return str; +} + +/*******************************************************************\ + +Function: string_constraint_generatort::get_string_expr + + Inputs: an expression of refined string type + + Outputs: a string expression + + Purpose: casts an expression to a string expression, or fetches the + actual string_exprt in the case of a symbol. + +\*******************************************************************/ + +string_exprt string_constraint_generatort::get_string_expr(const exprt &expr) +{ + assert(refined_string_typet::is_refined_string_type(expr.type())); + + if(expr.id()==ID_symbol) + { + return find_or_add_string_of_symbol( + to_symbol_expr(expr), + to_refined_string_type(expr.type())); + } + else + { + return to_string_expr(expr); + } +} + +string_exprt string_constraint_generatort::convert_java_string_to_string_exprt( + const exprt &jls) +{ + assert(get_mode()==ID_java); + assert(jls.id()==ID_struct); + + exprt length(to_struct_expr(jls).op1()); + // TODO: Add assertion on the type. + // assert(length.type()==refined_string_typet::index_type()); + exprt java_content(to_struct_expr(jls).op2()); + if(java_content.id()==ID_address_of) + { + java_content=to_address_of_expr(java_content).object(); + } + else + { + java_content=dereference_exprt(java_content, java_content.type()); + } + + refined_string_typet type(java_int_type(), java_char_type()); + + return string_exprt(length, java_content, type); +} + +/*******************************************************************\ + +Function: string_constraint_generatort::add_default_constraints + + Inputs: + s - a string expression + + Outputs: a string expression that is linked to the argument through + axioms that are added to the list + + Purpose: adds standard axioms about the length of the string and + its content: + * its length should be positive + * it should not exceed max_string_length + * if force_printable_characters is true then all characters + should belong to the range of ASCII characters between ' ' and '~' + + +\*******************************************************************/ + +void string_constraint_generatort::add_default_axioms( + const string_exprt &s) +{ + s.axiom_for_is_longer_than(from_integer(0, s.length().type())); + if(max_string_length>=0) + axioms.push_back(s.axiom_for_is_shorter_than(max_string_length)); + + if(force_printable_characters) + { + symbol_exprt qvar=fresh_univ_index("printable", s.length().type()); + exprt chr=s[qvar]; + and_exprt printable( + binary_relation_exprt(chr, ID_ge, from_integer(' ', chr.type())), + binary_relation_exprt(chr, ID_le, from_integer('~', chr.type()))); + string_constraintt sc(qvar, s.length(), printable); + axioms.push_back(sc); + } } /*******************************************************************\ -Function: string_constraint_generatort::add_axioms_for_string_expr +Function: string_constraint_generatort::add_axioms_for_refined_string - Inputs: an expression of type string + Inputs: an expression of refined string type Outputs: a string expression that is linked to the argument through axioms that are added to the list - Purpose: obtain a refined string expression corresponding to string - variable of string function call + Purpose: obtain a refined string expression corresponding to a expression + of type string \*******************************************************************/ -string_exprt string_constraint_generatort::add_axioms_for_string_expr( - const exprt &unrefined_string) +string_exprt string_constraint_generatort::add_axioms_for_refined_string( + const exprt &string) { - string_exprt s; + assert(refined_string_typet::is_refined_string_type(string.type())); + refined_string_typet type=to_refined_string_type(string.type()); - if(unrefined_string.id()==ID_function_application) + // Function applications should have been removed before + assert(string.id()!=ID_function_application); + + if(string.id()==ID_symbol) { - exprt res=add_axioms_for_function_application( - to_function_application_expr(unrefined_string)); - s=to_string_expr(res); + const symbol_exprt &sym=to_symbol_expr(string); + string_exprt s=find_or_add_string_of_symbol(sym, type); + add_default_axioms(s); + return s; } - else if(unrefined_string.id()==ID_symbol) - s=find_or_add_string_of_symbol(to_symbol_expr(unrefined_string)); - else if(unrefined_string.id()==ID_address_of) + else if(string.id()==ID_nondet_symbol) { - assert(unrefined_string.op0().id()==ID_symbol); - s=find_or_add_string_of_symbol(to_symbol_expr(unrefined_string.op0())); + string_exprt s=fresh_string(type); + add_default_axioms(s); + return s; } - else if(unrefined_string.id()==ID_if) - s=add_axioms_for_if(to_if_expr(unrefined_string)); - else if(unrefined_string.id()==ID_nondet_symbol || - unrefined_string.id()==ID_struct) + else if(string.id()==ID_if) { - // TODO: for now we ignore non deterministic symbols and struct + return add_axioms_for_if(to_if_expr(string)); } - else if(unrefined_string.id()==ID_typecast) + else if(string.id()==ID_struct) { - exprt arg=to_typecast_expr(unrefined_string).op(); - exprt res=add_axioms_for_string_expr(arg); - s=to_string_expr(res); + const string_exprt &s=to_string_expr(string); + add_default_axioms(s); + return s; } else { - throw "add_axioms_for_string_expr:\n"+unrefined_string.pretty()+ + throw "add_axioms_for_refined_string:\n"+string.pretty()+ "\nwhich is not a function application, "+ - "a symbol or an if expression"; + "a symbol, a struct or an if expression"; } - - axioms.push_back( - s.axiom_for_is_longer_than(from_integer(0, s.length().type()))); - return s; } /*******************************************************************\ @@ -215,11 +342,11 @@ string_exprt string_constraint_generatort::add_axioms_for_if( const if_exprt &expr) { assert( - refined_string_typet::is_unrefined_string_type(expr.true_case().type())); - string_exprt t=add_axioms_for_string_expr(expr.true_case()); + refined_string_typet::is_refined_string_type(expr.true_case().type())); + string_exprt t=get_string_expr(expr.true_case()); assert( - refined_string_typet::is_unrefined_string_type(expr.false_case().type())); - string_exprt f=add_axioms_for_string_expr(expr.false_case()); + refined_string_typet::is_refined_string_type(expr.false_case().type())); + string_exprt f=get_string_expr(expr.false_case()); const refined_string_typet &ref_type=to_refined_string_type(t.type()); const typet &index_type=ref_type.get_index_type(); string_exprt res=fresh_string(ref_type); @@ -246,7 +373,7 @@ Function: string_constraint_generatort::find_or_add_string_of_symbol Outputs: a string expression - Purpose: if a symbol represent a string is present in the symbol_to_string + Purpose: if a symbol representing a string is present in the symbol_to_string table, returns the corresponding string, if the symbol is not yet present, creates a new string with the correct type depending on whether the mode is java or c, adds it to the table and returns it. @@ -254,12 +381,11 @@ Function: string_constraint_generatort::find_or_add_string_of_symbol \*******************************************************************/ string_exprt string_constraint_generatort::find_or_add_string_of_symbol( - const symbol_exprt &sym) + const symbol_exprt &sym, const refined_string_typet &ref_type) { irep_idt id=sym.get_identifier(); - const refined_string_typet &ref_type=to_refined_string_type(sym.type()); string_exprt str=fresh_string(ref_type); - auto entry=symbol_to_string.insert(std::make_pair(id, str)); + auto entry=unresolved_symbols.insert(std::make_pair(id, str)); return entry.first->second; } @@ -286,125 +412,180 @@ exprt string_constraint_generatort::add_axioms_for_function_application( const irep_idt &id=is_ssa_expr(name)?to_ssa_expr(name).get_object_name(): to_symbol_expr(name).get_identifier(); + std::string str_id(id.c_str()); + + size_t pos=str_id.find("func_length"); + if(pos!=std::string::npos) + { + function_application_exprt new_expr(expr); + // TODO: This part needs some improvement. + // Stripping the symbol name is not a very robust process. + new_expr.function() = symbol_exprt(str_id.substr(0, pos+4)); + assert(get_mode()==ID_java); + new_expr.type() = refined_string_typet(java_int_type(), java_char_type()); + + auto res_it=function_application_cache.insert(std::make_pair(new_expr, + nil_exprt())); + if(res_it.second) + { + string_exprt res=to_string_expr( + add_axioms_for_function_application(new_expr)); + res_it.first->second=res; + return res.length(); + } + else + return to_string_expr(res_it.first->second).length(); + } + + pos = str_id.find("func_data"); + if(pos!=std::string::npos) + { + function_application_exprt new_expr(expr); + new_expr.function() = symbol_exprt(str_id.substr(0, pos+4)); + new_expr.type() = refined_string_typet(java_int_type(), java_char_type()); + + auto res_it=function_application_cache.insert(std::make_pair(new_expr, + nil_exprt())); + if(res_it.second) + { + string_exprt res=to_string_expr( + add_axioms_for_function_application(new_expr)); + res_it.first->second=res; + return res.content(); + } + else + return to_string_expr(res_it.first->second).content(); + } + // TODO: improve efficiency of this test by either ordering test by frequency // or using a map + auto res_it=function_application_cache.find(expr); + if(res_it!=function_application_cache.end() && res_it->second!=nil_exprt()) + return res_it->second; + + exprt res; + if(id==ID_cprover_char_literal_func) - return add_axioms_for_char_literal(expr); + res=add_axioms_for_char_literal(expr); else if(id==ID_cprover_string_length_func) - return add_axioms_for_length(expr); + res=add_axioms_for_length(expr); else if(id==ID_cprover_string_equal_func) - return add_axioms_for_equals(expr); + res=add_axioms_for_equals(expr); else if(id==ID_cprover_string_equals_ignore_case_func) - return add_axioms_for_equals_ignore_case(expr); + res=add_axioms_for_equals_ignore_case(expr); else if(id==ID_cprover_string_is_empty_func) - return add_axioms_for_is_empty(expr); + res=add_axioms_for_is_empty(expr); else if(id==ID_cprover_string_char_at_func) - return add_axioms_for_char_at(expr); + res=add_axioms_for_char_at(expr); else if(id==ID_cprover_string_is_prefix_func) - return add_axioms_for_is_prefix(expr); + res=add_axioms_for_is_prefix(expr); else if(id==ID_cprover_string_is_suffix_func) - return add_axioms_for_is_suffix(expr); + res=add_axioms_for_is_suffix(expr); else if(id==ID_cprover_string_startswith_func) - return add_axioms_for_is_prefix(expr, true); + res=add_axioms_for_is_prefix(expr, true); else if(id==ID_cprover_string_endswith_func) - return add_axioms_for_is_suffix(expr, true); + res=add_axioms_for_is_suffix(expr, true); else if(id==ID_cprover_string_contains_func) - return add_axioms_for_contains(expr); + res=add_axioms_for_contains(expr); else if(id==ID_cprover_string_hash_code_func) - return add_axioms_for_hash_code(expr); + res=add_axioms_for_hash_code(expr); else if(id==ID_cprover_string_index_of_func) - return add_axioms_for_index_of(expr); + res=add_axioms_for_index_of(expr); else if(id==ID_cprover_string_last_index_of_func) - return add_axioms_for_last_index_of(expr); + res=add_axioms_for_last_index_of(expr); else if(id==ID_cprover_string_parse_int_func) - return add_axioms_for_parse_int(expr); + res=add_axioms_for_parse_int(expr); else if(id==ID_cprover_string_to_char_array_func) - return add_axioms_for_to_char_array(expr); + res=add_axioms_for_to_char_array(expr); else if(id==ID_cprover_string_code_point_at_func) - return add_axioms_for_code_point_at(expr); + res=add_axioms_for_code_point_at(expr); else if(id==ID_cprover_string_code_point_before_func) - return add_axioms_for_code_point_before(expr); + res=add_axioms_for_code_point_before(expr); else if(id==ID_cprover_string_code_point_count_func) - return add_axioms_for_code_point_count(expr); + res=add_axioms_for_code_point_count(expr); else if(id==ID_cprover_string_offset_by_code_point_func) - return add_axioms_for_offset_by_code_point(expr); + res=add_axioms_for_offset_by_code_point(expr); else if(id==ID_cprover_string_compare_to_func) - return add_axioms_for_compare_to(expr); + res=add_axioms_for_compare_to(expr); else if(id==ID_cprover_string_literal_func) - return add_axioms_from_literal(expr); + res=add_axioms_from_literal(expr); else if(id==ID_cprover_string_concat_func) - return add_axioms_for_concat(expr); + res=add_axioms_for_concat(expr); else if(id==ID_cprover_string_concat_int_func) - return add_axioms_for_concat_int(expr); + res=add_axioms_for_concat_int(expr); else if(id==ID_cprover_string_concat_long_func) - return add_axioms_for_concat_long(expr); + res=add_axioms_for_concat_long(expr); else if(id==ID_cprover_string_concat_bool_func) - return add_axioms_for_concat_bool(expr); + res=add_axioms_for_concat_bool(expr); else if(id==ID_cprover_string_concat_char_func) - return add_axioms_for_concat_char(expr); + res=add_axioms_for_concat_char(expr); else if(id==ID_cprover_string_concat_double_func) - return add_axioms_for_concat_double(expr); + res=add_axioms_for_concat_double(expr); else if(id==ID_cprover_string_concat_float_func) - return add_axioms_for_concat_float(expr); + res=add_axioms_for_concat_float(expr); else if(id==ID_cprover_string_concat_code_point_func) - return add_axioms_for_concat_code_point(expr); + res=add_axioms_for_concat_code_point(expr); else if(id==ID_cprover_string_insert_func) - return add_axioms_for_insert(expr); + res=add_axioms_for_insert(expr); else if(id==ID_cprover_string_insert_int_func) - return add_axioms_for_insert_int(expr); + res=add_axioms_for_insert_int(expr); else if(id==ID_cprover_string_insert_long_func) - return add_axioms_for_insert_long(expr); + res=add_axioms_for_insert_long(expr); else if(id==ID_cprover_string_insert_bool_func) - return add_axioms_for_insert_bool(expr); + res=add_axioms_for_insert_bool(expr); else if(id==ID_cprover_string_insert_char_func) - return add_axioms_for_insert_char(expr); + res=add_axioms_for_insert_char(expr); else if(id==ID_cprover_string_insert_double_func) - return add_axioms_for_insert_double(expr); + res=add_axioms_for_insert_double(expr); else if(id==ID_cprover_string_insert_float_func) - return add_axioms_for_insert_float(expr); + res=add_axioms_for_insert_float(expr); +#if 0 else if(id==ID_cprover_string_insert_char_array_func) - return add_axioms_for_insert_char_array(expr); + res=add_axioms_for_insert_char_array(expr); +#endif else if(id==ID_cprover_string_substring_func) - return add_axioms_for_substring(expr); + res=add_axioms_for_substring(expr); else if(id==ID_cprover_string_trim_func) - return add_axioms_for_trim(expr); + res=add_axioms_for_trim(expr); else if(id==ID_cprover_string_to_lower_case_func) - return add_axioms_for_to_lower_case(expr); + res=add_axioms_for_to_lower_case(expr); else if(id==ID_cprover_string_to_upper_case_func) - return add_axioms_for_to_upper_case(expr); + res=add_axioms_for_to_upper_case(expr); else if(id==ID_cprover_string_char_set_func) - return add_axioms_for_char_set(expr); + res=add_axioms_for_char_set(expr); else if(id==ID_cprover_string_value_of_func) - return add_axioms_for_value_of(expr); + res=add_axioms_for_value_of(expr); else if(id==ID_cprover_string_empty_string_func) - return add_axioms_for_empty_string(expr); + res=add_axioms_for_empty_string(expr); else if(id==ID_cprover_string_copy_func) - return add_axioms_for_copy(expr); + res=add_axioms_for_copy(expr); else if(id==ID_cprover_string_of_int_func) - return add_axioms_from_int(expr); + res=add_axioms_from_int(expr); else if(id==ID_cprover_string_of_int_hex_func) - return add_axioms_from_int_hex(expr); + res=add_axioms_from_int_hex(expr); else if(id==ID_cprover_string_of_float_func) - return add_axioms_from_float(expr); + res=add_axioms_from_float(expr); else if(id==ID_cprover_string_of_double_func) - return add_axioms_from_double(expr); + res=add_axioms_from_double(expr); else if(id==ID_cprover_string_of_long_func) - return add_axioms_from_long(expr); + res=add_axioms_from_long(expr); else if(id==ID_cprover_string_of_bool_func) - return add_axioms_from_bool(expr); + res=add_axioms_from_bool(expr); else if(id==ID_cprover_string_of_char_func) - return add_axioms_from_char(expr); - else if(id==ID_cprover_string_of_char_array_func) - return add_axioms_from_char_array(expr); + res=add_axioms_from_char(expr); else if(id==ID_cprover_string_set_length_func) - return add_axioms_for_set_length(expr); + res=add_axioms_for_set_length(expr); else if(id==ID_cprover_string_delete_func) - return add_axioms_for_delete(expr); + res=add_axioms_for_delete(expr); else if(id==ID_cprover_string_delete_char_at_func) - return add_axioms_for_delete_char_at(expr); + res=add_axioms_for_delete_char_at(expr); else if(id==ID_cprover_string_replace_func) - return add_axioms_for_replace(expr); + res=add_axioms_for_replace(expr); + else if(id==ID_cprover_string_intern_func) + res=add_axioms_for_intern(expr); + else if(id==ID_cprover_string_array_of_char_pointer_func) + res=add_axioms_for_char_pointer(expr); else { std::string msg( @@ -412,13 +593,16 @@ exprt string_constraint_generatort::add_axioms_for_function_application( msg+=id2string(id); throw msg; } + function_application_cache[expr]=res; + return res; } /*******************************************************************\ Function: string_constraint_generatort::add_axioms_for_copy - Inputs: function application with one argument, which is a string + Inputs: function application with one argument, which is a string, + or three arguments: string, integer offset and count Outputs: a new string expression @@ -430,20 +614,20 @@ Function: string_constraint_generatort::add_axioms_for_copy string_exprt string_constraint_generatort::add_axioms_for_copy( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 1)[0]); - const refined_string_typet &ref_type=to_refined_string_type(s1.type()); - string_exprt res=fresh_string(ref_type); - - // We add axioms: - // a1 : |res|=|s1| - // a2 : forall i<|s1|. s1[i]=res[i] - - axioms.push_back(res.axiom_for_has_same_length_as(s1)); - - symbol_exprt idx=fresh_univ_index("QA_index_copy", ref_type.get_index_type()); - string_constraintt a2(idx, s1.length(), equal_exprt(s1[idx], res[idx])); - axioms.push_back(a2); - return res; + const auto &args=f.arguments(); + if(args.size()==1) + { + string_exprt s1=get_string_expr(args[0]); + return s1; + } + else + { + assert(args.size()==3); + string_exprt s1=get_string_expr(args[0]); + exprt offset=args[1]; + exprt count=args[2]; + return add_axioms_for_substring(s1, offset, plus_exprt(offset, count)); + } } /*******************************************************************\ @@ -473,6 +657,28 @@ string_exprt string_constraint_generatort::add_axioms_for_java_char_array( /*******************************************************************\ +Function: string_constraint_generatort::add_axioms_for_char_pointer + + Inputs: an expression of type char + + Outputs: an array expression + + Purpose: for an expression of the form `array[0]` returns `array` + +\*******************************************************************/ + +exprt string_constraint_generatort::add_axioms_for_char_pointer( + const function_application_exprt &fun) +{ + exprt char_pointer=args(fun, 1)[0]; + if(char_pointer.id()==ID_index) + return char_pointer.op0(); + // TODO: we do not know what to do in the other cases + assert(false); +} + +/*******************************************************************\ + Function: string_constraint_generatort::add_axioms_for_length Inputs: function application with one string argument @@ -486,7 +692,7 @@ Function: string_constraint_generatort::add_axioms_for_length exprt string_constraint_generatort::add_axioms_for_length( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); return str.length(); } @@ -511,6 +717,7 @@ string_exprt string_constraint_generatort::add_axioms_from_char_array( const exprt &offset, const exprt &count) { + assert(false); // deprecated, we should use add_axioms_for_substring instead const typet &char_type=to_array_type(data.type()).subtype(); const typet &index_type=length.type(); refined_string_typet ref_type(index_type, char_type); @@ -523,7 +730,7 @@ string_exprt string_constraint_generatort::add_axioms_from_char_array( symbol_exprt qvar=fresh_univ_index("QA_string_of_char_array", index_type); exprt char_in_tab=data; assert(char_in_tab.id()==ID_index); - char_in_tab.op1()=plus_exprt(qvar, offset); + char_in_tab.op1()=plus_exprt_with_overflow_check(qvar, offset); string_constraintt a1(qvar, count, equal_exprt(str[qvar], char_in_tab)); axioms.push_back(a1); @@ -549,6 +756,7 @@ Function: string_constraint_generatort::add_axioms_from_char_array string_exprt string_constraint_generatort::add_axioms_from_char_array( const function_application_exprt &f) { + assert(false); // deprecated, we should use add_axioms_for_substring instead exprt offset; exprt count; if(f.arguments().size()==4) @@ -638,7 +846,7 @@ Function: string_constraint_generatort::add_axioms_for_char_at exprt string_constraint_generatort::add_axioms_for_char_at( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt str=get_string_expr(args(f, 2)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); symbol_exprt char_sym=fresh_symbol("char", ref_type.get_char_type()); axioms.push_back(equal_exprt(char_sym, str[args(f, 2)[1]])); @@ -660,26 +868,6 @@ Function: string_constraint_generatort::add_axioms_for_to_char_array exprt string_constraint_generatort::add_axioms_for_to_char_array( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); return str.content(); } - -/*******************************************************************\ - -Function: string_constraint_generatort::set_string_symbol_equal_to_expr - - Inputs: a symbol and a string - - Purpose: add a correspondence to make sure the symbol points to the - same string as the second argument - -\*******************************************************************/ - -void string_constraint_generatort::set_string_symbol_equal_to_expr( - const symbol_exprt &sym, const exprt &str) -{ - if(str.id()==ID_symbol) - assign_to_symbol(sym, find_or_add_string_of_symbol(to_symbol_expr(str))); - else - assign_to_symbol(sym, add_axioms_for_string_expr(str)); -} diff --git a/src/solvers/refinement/string_constraint_generator_testing.cpp b/src/solvers/refinement/string_constraint_generator_testing.cpp index 8b1c7bca9d4..2a08b021070 100644 --- a/src/solvers/refinement/string_constraint_generator_testing.cpp +++ b/src/solvers/refinement/string_constraint_generator_testing.cpp @@ -31,15 +31,15 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( // We add axioms: // a1 : isprefix => |str| >= |prefix|+offset - // a2 : forall 0<=qvar - // s0[witness+offset]=s2[witness] - // a3 : !isprefix => |str| < |prefix|+offset - // || (|str| >= |prefix|+offset &&0<=witness<|prefix| - // &&str[witness+ofsset]!=prefix[witness]) + // a2 : forall 0<=qvar<|prefix|. isprefix => s0[witness+offset]=s2[witness] + // a3 : !isprefix => + // |str|<|prefix|+offset || + // (0<=witness<|prefix| && str[witness+offset]!=prefix[witness]) implies_exprt a1( isprefix, - str.axiom_for_is_longer_than(plus_exprt(prefix.length(), offset))); + str.axiom_for_is_longer_than(plus_exprt_with_overflow_check( + prefix.length(), offset))); axioms.push_back(a1); symbol_exprt qvar=fresh_univ_index("QA_isprefix", index_type); @@ -47,7 +47,8 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( qvar, prefix.length(), isprefix, - equal_exprt(str[plus_exprt(qvar, offset)], prefix[qvar])); + equal_exprt(str[plus_exprt_with_overflow_check(qvar, offset)], + prefix[qvar])); axioms.push_back(a2); symbol_exprt witness=fresh_exist_index("witness_not_isprefix", index_type); @@ -55,14 +56,13 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( axiom_for_is_positive_index(witness), and_exprt( prefix.axiom_for_is_strictly_longer_than(witness), - notequal_exprt(str[plus_exprt(witness, offset)], prefix[witness]))); + notequal_exprt(str[plus_exprt_with_overflow_check(witness, offset)], + prefix[witness]))); or_exprt s0_notpref_s1( not_exprt( - str.axiom_for_is_longer_than(plus_exprt(prefix.length(), offset))), - and_exprt( - witness_diff, str.axiom_for_is_longer_than( - plus_exprt(prefix.length(), offset)))); + plus_exprt_with_overflow_check(prefix.length(), offset))), + witness_diff); implies_exprt a3(not_exprt(isprefix), s0_notpref_s1); axioms.push_back(a3); @@ -88,8 +88,8 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix( { const function_application_exprt::argumentst &args=f.arguments(); assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); - string_exprt s0=add_axioms_for_string_expr(args[swap_arguments?1:0]); - string_exprt s1=add_axioms_for_string_expr(args[swap_arguments?0:1]); + string_exprt s0=get_string_expr(args[swap_arguments?1:0]); + string_exprt s1=get_string_expr(args[swap_arguments?0:1]); exprt offset; if(args.size()==2) offset=from_integer(0, s0.length().type()); @@ -121,7 +121,7 @@ exprt string_constraint_generatort::add_axioms_for_is_empty( // a2 : s0 => is_empty symbol_exprt is_empty=fresh_boolean("is_empty"); - string_exprt s0=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt s0=get_string_expr(args(f, 1)[0]); axioms.push_back(implies_exprt(is_empty, s0.axiom_for_has_length(0))); axioms.push_back(implies_exprt(s0.axiom_for_has_length(0), is_empty)); return typecast_exprt(is_empty, f.type()); @@ -150,8 +150,8 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix( symbol_exprt issuffix=fresh_boolean("issuffix"); typecast_exprt tc_issuffix(issuffix, f.type()); - string_exprt s0=add_axioms_for_string_expr(args[swap_arguments?1:0]); - string_exprt s1=add_axioms_for_string_expr(args[swap_arguments?0:1]); + string_exprt s0=get_string_expr(args[swap_arguments?1:0]); + string_exprt s1=get_string_expr(args[swap_arguments?0:1]); const typet &index_type=s0.length().type(); // We add axioms: @@ -159,7 +159,7 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix( // a2 : forall witness s1[witness]=s0[witness + s0.length-s1.length] // a3 : !issuffix => - // s1.length > s0.length + // (s1.length > s0.length && witness=-1) // || (s1.length > witness>=0 // &&s1[witness]!=s0[witness + s0.length-s1.length] @@ -177,7 +177,8 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix( exprt shifted=plus_exprt( witness, minus_exprt(s1.length(), s0.length())); or_exprt constr3( - s0.axiom_for_is_strictly_longer_than(s1), + and_exprt(s0.axiom_for_is_strictly_longer_than(s1), + equal_exprt(witness, from_integer(-1, index_type))), and_exprt( notequal_exprt(s0[witness], s1[shifted]), and_exprt( @@ -207,9 +208,10 @@ exprt string_constraint_generatort::add_axioms_for_contains( assert(f.type()==bool_typet() || f.type().id()==ID_c_bool); symbol_exprt contains=fresh_boolean("contains"); typecast_exprt tc_contains(contains, f.type()); - string_exprt s0=add_axioms_for_string_expr(args(f, 2)[0]); - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[1]); - const typet &index_type=s0.type(); + string_exprt s0=get_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[1]); + const refined_string_typet ref_type=to_refined_string_type(s0.type()); + const typet &index_type=ref_type.get_index_type(); // We add axioms: // a1 : contains => s0.length >= s1.length diff --git a/src/solvers/refinement/string_constraint_generator_transformation.cpp b/src/solvers/refinement/string_constraint_generator_transformation.cpp index 83735e0d5b5..f27fe5d4317 100644 --- a/src/solvers/refinement/string_constraint_generator_transformation.cpp +++ b/src/solvers/refinement/string_constraint_generator_transformation.cpp @@ -29,7 +29,7 @@ Function: string_constraint_generatort::add_axioms_for_set_length string_exprt string_constraint_generatort::add_axioms_for_set_length( const function_application_exprt &f) { - string_exprt s1=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt s1=get_string_expr(args(f, 2)[0]); exprt k=args(f, 2)[1]; const refined_string_typet &ref_type=to_refined_string_type(s1.type()); string_exprt res=fresh_string(ref_type); @@ -76,7 +76,7 @@ string_exprt string_constraint_generatort::add_axioms_for_substring( { const function_application_exprt::argumentst &args=f.arguments(); assert(args.size()>=2); - string_exprt str=add_axioms_for_string_expr(args[0]); + string_exprt str=get_string_expr(args[0]); exprt i(args[1]); exprt j; if(args.size()==3) @@ -110,7 +110,6 @@ string_exprt string_constraint_generatort::add_axioms_for_substring( { const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &index_type=ref_type.get_index_type(); - symbol_exprt idx=fresh_exist_index("index_substring", index_type); assert(start.type()==index_type); assert(end.type()==index_type); string_exprt res=fresh_string(ref_type); @@ -133,8 +132,11 @@ string_exprt string_constraint_generatort::add_axioms_for_substring( // Warning: check what to do if the string is not long enough axioms.push_back(str.axiom_for_is_longer_than(end)); - string_constraintt a4( - idx, res.length(), equal_exprt(res[idx], str[plus_exprt(start, idx)])); + symbol_exprt idx=fresh_univ_index("QA_index_substring", index_type); + string_constraintt a4(idx, + res.length(), + equal_exprt(res[idx], + str[plus_exprt_with_overflow_check(start, idx)])); axioms.push_back(a4); return res; } @@ -154,7 +156,7 @@ Function: string_constraint_generatort::add_axioms_for_trim string_exprt string_constraint_generatort::add_axioms_for_trim( const function_application_exprt &expr) { - string_exprt str=add_axioms_for_string_expr(args(expr, 1)[0]); + string_exprt str=get_string_expr(args(expr, 1)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &index_type=ref_type.get_index_type(); string_exprt res=fresh_string(ref_type); @@ -173,7 +175,8 @@ string_exprt string_constraint_generatort::add_axioms_for_trim( // a8 : forall n<|s1|, s[idx+n]=s1[n] // a9 : (s[m]>' ' &&s[m+|s1|-1]>' ') || m=|s| - exprt a1=str.axiom_for_is_longer_than(plus_exprt(idx, res.length())); + exprt a1=str.axiom_for_is_longer_than( + plus_exprt_with_overflow_check(idx, res.length())); axioms.push_back(a1); binary_relation_exprt a2(idx, ID_ge, from_integer(0, index_type)); @@ -195,7 +198,8 @@ string_exprt string_constraint_generatort::add_axioms_for_trim( axioms.push_back(a6); symbol_exprt n2=fresh_univ_index("QA_index_trim2", index_type); - minus_exprt bound(str.length(), plus_exprt(idx, res.length())); + minus_exprt bound(str.length(), plus_exprt_with_overflow_check(idx, + res.length())); binary_relation_exprt eqn2( str[plus_exprt(idx, plus_exprt(res.length(), n2))], ID_le, @@ -210,7 +214,8 @@ string_exprt string_constraint_generatort::add_axioms_for_trim( axioms.push_back(a8); minus_exprt index_before( - plus_exprt(idx, res.length()), from_integer(1, index_type)); + plus_exprt_with_overflow_check(idx, res.length()), + from_integer(1, index_type)); binary_relation_exprt no_space_before(str[index_before], ID_gt, space_char); or_exprt a9( equal_exprt(idx, str.length()), @@ -236,7 +241,7 @@ Function: string_constraint_generatort::add_axioms_for_to_lower_case string_exprt string_constraint_generatort::add_axioms_for_to_lower_case( const function_application_exprt &expr) { - string_exprt str=add_axioms_for_string_expr(args(expr, 1)[0]); + string_exprt str=get_string_expr(args(expr, 1)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &char_type=ref_type.get_char_type(); const typet &index_type=ref_type.get_index_type(); @@ -289,7 +294,7 @@ Function: string_constraint_generatort::add_axioms_for_to_upper_case string_exprt string_constraint_generatort::add_axioms_for_to_upper_case( const function_application_exprt &expr) { - string_exprt str=add_axioms_for_string_expr(args(expr, 1)[0]); + string_exprt str=get_string_expr(args(expr, 1)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const typet &char_type=ref_type.get_char_type(); const typet &index_type=ref_type.get_index_type(); @@ -345,7 +350,7 @@ Function: string_constraint_generatort::add_axioms_for_char_set string_exprt string_constraint_generatort::add_axioms_for_char_set( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); string_exprt res=fresh_string(ref_type); with_exprt sarrnew(str.content(), args(f, 3)[1], args(f, 3)[2]); @@ -378,7 +383,7 @@ Function: string_constraint_generatort::add_axioms_for_replace string_exprt string_constraint_generatort::add_axioms_for_replace( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); const refined_string_typet &ref_type=to_refined_string_type(str.type()); const exprt &old_char=args(f, 3)[1]; const exprt &new_char=args(f, 3)[2]; @@ -421,10 +426,12 @@ Function: string_constraint_generatort::add_axioms_for_delete_char_at string_exprt string_constraint_generatort::add_axioms_for_delete_char_at( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 2)[0]); + string_exprt str=get_string_expr(args(f, 2)[0]); exprt index_one=from_integer(1, str.length().type()); return add_axioms_for_delete( - str, args(f, 2)[1], plus_exprt(args(f, 2)[1], index_one)); + str, + args(f, 2)[1], + plus_exprt_with_overflow_check(args(f, 2)[1], index_one)); } /*******************************************************************\ @@ -468,6 +475,6 @@ Function: string_constraint_generatort::add_axioms_for_delete string_exprt string_constraint_generatort::add_axioms_for_delete( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 3)[0]); + string_exprt str=get_string_expr(args(f, 3)[0]); return add_axioms_for_delete(str, args(f, 3)[1], args(f, 3)[2]); } diff --git a/src/solvers/refinement/string_constraint_generator_valueof.cpp b/src/solvers/refinement/string_constraint_generator_valueof.cpp index d1030e5e085..10fe490259a 100644 --- a/src/solvers/refinement/string_constraint_generator_valueof.cpp +++ b/src/solvers/refinement/string_constraint_generator_valueof.cpp @@ -63,7 +63,8 @@ Function: string_constraint_generatort::add_axioms_from_float string_exprt string_constraint_generatort::add_axioms_from_float( const function_application_exprt &f) { - return add_axioms_from_float(args(f, 1)[0], false); + const refined_string_typet &ref_type=to_refined_string_type(f.type()); + return add_axioms_from_float(args(f, 1)[0], ref_type, false); } /*******************************************************************\ @@ -81,7 +82,8 @@ Function: string_constraint_generatort::add_axioms_from_double string_exprt string_constraint_generatort::add_axioms_from_double( const function_application_exprt &f) { - return add_axioms_from_float(args(f, 1)[0], true); + const refined_string_typet &ref_type=to_refined_string_type(f.type()); + return add_axioms_from_float(args(f, 1)[0], ref_type, true); } /*******************************************************************\ @@ -99,13 +101,12 @@ Function: string_constraint_generatort::add_axioms_from_float \*******************************************************************/ string_exprt string_constraint_generatort::add_axioms_from_float( - const exprt &f, bool double_precision) + const exprt &f, const refined_string_typet &ref_type, bool double_precision) { - const refined_string_typet &ref_type=to_refined_string_type(f.type()); + string_exprt res=fresh_string(ref_type); const typet &index_type=ref_type.get_index_type(); const typet &char_type=ref_type.get_char_type(); - string_exprt res=fresh_string(ref_type); - const exprt &index24=from_integer(24, ref_type.get_index_type()); + const exprt &index24=from_integer(24, index_type); axioms.push_back(res.axiom_for_is_shorter_than(index24)); string_exprt magnitude=fresh_string(ref_type); @@ -323,13 +324,22 @@ string_exprt string_constraint_generatort::add_axioms_from_int( axioms.push_back(a1); exprt chr=res[0]; - exprt starts_with_minus=equal_exprt(chr, minus_char); - exprt starts_with_digit=and_exprt( + equal_exprt starts_with_minus(chr, minus_char); + and_exprt starts_with_digit( binary_relation_exprt(chr, ID_ge, zero_char), binary_relation_exprt(chr, ID_le, nine_char)); or_exprt a2(starts_with_digit, starts_with_minus); axioms.push_back(a2); + // These are constraints to detect number that requiere the maximum number + // of digits + exprt smallest_with_max_digits= + from_integer(smallest_by_digit(max_size-1), type); + binary_relation_exprt big_negative( + i, ID_le, unary_minus_exprt(smallest_with_max_digits)); + binary_relation_exprt big_positive(i, ID_ge, smallest_with_max_digits); + or_exprt requieres_max_digits(big_negative, big_positive); + for(size_t size=1; size<=max_size; size++) { // For each possible size, we add axioms: @@ -387,13 +397,18 @@ string_exprt string_constraint_generatort::add_axioms_from_int( axioms.push_back(a6); } - // we have to be careful when exceeding the maximal size of integers + // when the size is close to the maximum, either the number is very big + // or it is negative + if(size==max_size-1) + { + implies_exprt a7(premise, or_exprt(requieres_max_digits, + starts_with_minus)); + axioms.push_back(a7); + } + // when we reach the maximal size the number is very big in the negative if(size==max_size) { - exprt smallest_with_10_digits=from_integer( - smallest_by_digit(max_size), type); - binary_relation_exprt big(i, ID_ge, smallest_with_10_digits); - implies_exprt a7(premise, big); + implies_exprt a7(premise, and_exprt(starts_with_minus, big_negative)); axioms.push_back(a7); } } @@ -597,6 +612,60 @@ string_exprt string_constraint_generatort::add_axioms_for_value_of( /*******************************************************************\ +Function: string_constraint_generatort::add_axioms_for_correct_number_format + + Inputs: function application with one string expression + + Outputs: an boolean expression + + Purpose: add axioms making the return value true if the given string is + a correct number + +\*******************************************************************/ + +exprt string_constraint_generatort::add_axioms_for_correct_number_format( + const string_exprt &str, std::size_t max_size) +{ + symbol_exprt correct=fresh_boolean("correct_number_format"); + const refined_string_typet &ref_type=to_refined_string_type(str.type()); + const typet &char_type=ref_type.get_char_type(); + const typet &index_type=ref_type.get_index_type(); + exprt zero_char=constant_char('0', char_type); + exprt nine_char=constant_char('9', char_type); + exprt minus_char=constant_char('-', char_type); + exprt plus_char=constant_char('+', char_type); + + exprt chr=str[0]; + equal_exprt starts_with_minus(chr, minus_char); + equal_exprt starts_with_plus(chr, plus_char); + and_exprt starts_with_digit( + binary_relation_exprt(chr, ID_ge, zero_char), + binary_relation_exprt(chr, ID_le, nine_char)); + + or_exprt correct_first( + or_exprt(starts_with_minus, starts_with_plus), starts_with_digit); + exprt has_first=str.axiom_for_is_longer_than(from_integer(1, index_type)); + implies_exprt a1(correct, and_exprt(has_first, correct_first)); + axioms.push_back(a1); + + exprt not_too_long=str.axiom_for_is_shorter_than(max_size); + axioms.push_back(not_too_long); + + symbol_exprt qvar=fresh_univ_index("number_format", index_type); + + and_exprt is_digit( + binary_relation_exprt(str[qvar], ID_ge, zero_char), + binary_relation_exprt(str[qvar], ID_le, nine_char)); + + string_constraintt a2( + qvar, from_integer(1, index_type), str.length(), correct, is_digit); + + axioms.push_back(a2); + return correct; +} + +/*******************************************************************\ + Function: string_constraint_generatort::add_axioms_for_parse_int Inputs: function application with one string expression @@ -610,7 +679,7 @@ Function: string_constraint_generatort::add_axioms_for_parse_int exprt string_constraint_generatort::add_axioms_for_parse_int( const function_application_exprt &f) { - string_exprt str=add_axioms_for_string_expr(args(f, 1)[0]); + string_exprt str=get_string_expr(args(f, 1)[0]); const typet &type=f.type(); symbol_exprt i=fresh_symbol("parsed_int", type); const refined_string_typet &ref_type=to_refined_string_type(str.type()); @@ -626,6 +695,10 @@ exprt string_constraint_generatort::add_axioms_for_parse_int( exprt starts_with_plus=equal_exprt(chr, plus_char); exprt starts_with_digit=binary_relation_exprt(chr, ID_ge, zero_char); + // TODO: we should throw an exception when this does not hold: + exprt correct=add_axioms_for_correct_number_format(str); + axioms.push_back(correct); + for(unsigned size=1; size<=10; size++) { exprt sum=from_integer(0, type); diff --git a/src/solvers/refinement/string_refinement.cpp b/src/solvers/refinement/string_refinement.cpp index 16b89bc43c8..164bb32c012 100644 --- a/src/solvers/refinement/string_refinement.cpp +++ b/src/solvers/refinement/string_refinement.cpp @@ -11,18 +11,40 @@ Author: Alberto Griggio, alberto.griggio@gmail.com \*******************************************************************/ #include +#include #include #include #include +#include +#include #include #include #include +#include + +/*******************************************************************\ + +Constructor: string_refinementt + + Inputs: a namespace, a decision procedure, a bound on the number + of refinements and a boolean flag `concretize_result` + + Purpose: refinement_bound is a bound on the number of refinement allowed. + if `concretize_result` is set to true, at the end of the decision + procedure, the solver try to find a concrete value for each + character + +\*******************************************************************/ string_refinementt::string_refinementt( - const namespacet &_ns, propt &_prop, unsigned refinement_bound): + const namespacet &_ns, + propt &_prop, + unsigned refinement_bound): supert(_ns, _prop), use_counter_example(false), - initial_loop_bound(refinement_bound) + do_concretizing(false), + initial_loop_bound(refinement_bound), + non_empty_string(false) { } /*******************************************************************\ @@ -44,6 +66,52 @@ void string_refinementt::set_mode() /*******************************************************************\ +Function: string_refinementt::set_max_string_length + + Inputs: + i - maximum length which is allowed for strings. + negative number means no limit + + Purpose: Add constraints on the size of strings used in the + program. + +\*******************************************************************/ + +void string_refinementt::set_max_string_length(int i) +{ + generator.max_string_length=i; +} + +/*******************************************************************\ + +Function: string_refinementt::set_max_string_length + + Purpose: Add constraints on the size of nondet character arrays + to ensure they have length at least 1 + +\*******************************************************************/ + +void string_refinementt::enforce_non_empty_string() +{ + non_empty_string=true; +} + +/*******************************************************************\ + +Function: string_refinementt::enforce_printable_characters + + Purpose: Add constraints on characters used in the program + to ensure they are printable + +\*******************************************************************/ + +void string_refinementt::enforce_printable_characters() +{ + generator.force_printable_characters=true; +} + +/*******************************************************************\ + Function: string_refinementt::display_index_set Purpose: display the current index set, for debugging @@ -52,15 +120,27 @@ Function: string_refinementt::display_index_set void string_refinementt::display_index_set() { + std::size_t count=0; + std::size_t count_current=0; for(const auto &i : index_set) { const exprt &s=i.first; - debug() << "IS(" << from_expr(s) << ")=={"; + debug() << "IS(" << from_expr(s) << ")=={" << eom; for(auto j : i.second) - debug() << from_expr(j) << "; "; + { + if(current_index_set[i.first].find(j)!=current_index_set[i.first].end()) + { + count_current++; + debug() << "**"; + } + debug() << " " << from_expr(j) << ";" << eom; + count++; + } debug() << "}" << eom; } + debug() << count << " elements in index set (" << count_current + << " newly added)" << eom; } /*******************************************************************\ @@ -100,152 +180,350 @@ void string_refinementt::add_instantiations() /*******************************************************************\ -Function: string_refinementt::convert_rest - - Inputs: an expression +Function: string_refinementt::add_symbol_to_symbol_map() - Outputs: a literal + Inputs: a symbol and the expression to map it to - Purpose: if the expression is a function application, we convert it - using our own convert_function_application method + Purpose: keeps a map of symbols to expressions, such as none of the + mapped values exist as a key \*******************************************************************/ -literalt string_refinementt::convert_rest(const exprt &expr) +void string_refinementt::add_symbol_to_symbol_map +(const exprt &lhs, const exprt &rhs) { - if(expr.id()==ID_function_application) + assert(lhs.id()==ID_symbol); + + // We insert the mapped value of the rhs, if it exists. + auto it=symbol_resolve.find(rhs); + const exprt &new_rhs=it!=symbol_resolve.end()?it->second:rhs; + + symbol_resolve[lhs]=new_rhs; + reverse_symbol_resolve[new_rhs].push_back(lhs); + + std::list symbols_to_update_with_new_rhs(reverse_symbol_resolve[rhs]); + for(exprt item : symbols_to_update_with_new_rhs) { - // can occur in __CPROVER_assume - bvt bv=convert_function_application(to_function_application_expr(expr)); - assert(bv.size()==1); - return bv[0]; + symbol_resolve[item]=new_rhs; + reverse_symbol_resolve[new_rhs].push_back(item); } - else +} + +/*******************************************************************\ + +Function: string_refinementt::set_char_array_equality() + + Inputs: the rhs and lhs of an equality over character arrays + + Purpose: add axioms if the rhs is a character array + +\*******************************************************************/ + +void string_refinementt::set_char_array_equality( + const exprt &lhs, const exprt &rhs) +{ + assert(lhs.id()==ID_symbol); + + if(rhs.id()==ID_array && rhs.type().id()==ID_array) { - return supert::convert_rest(expr); + const typet &index_type=to_array_type(rhs.type()).size().type(); + for(size_t i=0, ilim=rhs.operands().size(); i!=ilim; ++i) + { + // Introduce axioms to map symbolic rhs to its char array. + index_exprt arraycell(rhs, from_integer(i, index_type)); + equal_exprt arrayeq(arraycell, rhs.operands()[i]); + add_lemma(arrayeq, false); +#if 0 + generator.axioms.push_back(arrayeq); +#endif + } } + // At least for Java (as it is currently pre-processed), we need not consider + // other cases, because all character arrays find themselves on the rhs of an + // equality. Note that this might not be the case for other languages. } /*******************************************************************\ -Function: string_refinementt::convert_symbol +Function: string_refinementt::substitute_function_applications() - Inputs: an expression + Inputs: an expression containing function applications - Outputs: a bitvector + Outputs: an epression containing no function application - Purpose: if the expression as string type, look up for the string in the - list of string symbols that we maintain, and convert it; - otherwise use the method of the parent class + Purpose: remove functions applications and create the necessary + axioms \*******************************************************************/ -bvt string_refinementt::convert_symbol(const exprt &expr) +exprt string_refinementt::substitute_function_applications(exprt expr) { - const typet &type=expr.type(); - const irep_idt &identifier=expr.get(ID_identifier); - assert(!identifier.empty()); + for(size_t i=0; iMAX_CONCRETE_STRING_SIZE? + MAX_CONCRETE_STRING_SIZE:concretize_limit; + exprt content_expr=str.content(); + for(size_t i=0; i &pair : non_string_axioms) + { + replace_expr(symbol_resolve, pair.first); + debug() << "super::set_to " << from_expr(pair.first) << eom; + supert::set_to(pair.first, pair.second); + } + + for(exprt &axiom : generator.axioms) + { + replace_expr(symbol_resolve, axiom); if(axiom.id()==ID_string_constraint) { string_constraintt c=to_string_constraint(axiom); @@ -282,6 +571,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() { add_lemma(axiom); } + } initial_index_set(universal_axioms); update_index_set(cur); @@ -302,6 +592,7 @@ decision_proceduret::resultt string_refinementt::dec_solve() else { debug() << "check_SAT: the model is correct" << eom; + concretize_lengths(); return D_SATISFIABLE; } @@ -318,7 +609,13 @@ decision_proceduret::resultt string_refinementt::dec_solve() if(current_index_set.empty()) { debug() << "current index set is empty" << eom; - return D_SATISFIABLE; + if(do_concretizing) + { + concretize_results(); + do_concretizing=false; + } + else + return D_SATISFIABLE; } display_index_set(); @@ -367,178 +664,459 @@ bvt string_refinementt::convert_bool_bv(const exprt &boole, const exprt &orig) Function: string_refinementt::add_lemma - Inputs: a lemma + Inputs: a lemma and Boolean value stating whether the lemma should + be added to the index set. Purpose: add the given lemma to the solver \*******************************************************************/ -void string_refinementt::add_lemma(const exprt &lemma, bool add_to_index_set) +void string_refinementt::add_lemma( + const exprt &lemma, bool _simplify, bool add_to_index_set) { if(!seen_instances.insert(lemma).second) return; - if(lemma.is_true()) + if(add_to_index_set) + cur.push_back(lemma); + + exprt simple_lemma=lemma; + if(_simplify) + simplify(simple_lemma, ns); + + if(simple_lemma.is_true()) { +#if 0 debug() << "string_refinementt::add_lemma : tautology" << eom; +#endif return; } - debug() << "adding lemma " << from_expr(lemma) << eom; + debug() << "adding lemma " << from_expr(simple_lemma) << eom; - prop.l_set_to_true(convert(lemma)); - if(add_to_index_set) - cur.push_back(lemma); + prop.l_set_to_true(convert(simple_lemma)); } /*******************************************************************\ -Function: string_refinementt::string_of_array +Function: string_refinementt::get_array - Inputs: a constant array expression and a integer expression + Inputs: an expression representing an array and an expression + representing an integer - Outputs: a string + Outputs: an array expression or an array_of_exprt - Purpose: convert the content of a string to a more readable representation. - This should only be used for debbuging. + Purpose: get a model of an array and put it in a certain form. + If the size cannot be obtained or if it is too big, return an + empty array. \*******************************************************************/ -std::string string_refinementt::string_of_array( - const exprt &arr, const exprt &size) const +exprt string_refinementt::get_array(const exprt &arr, const exprt &size) const { - if(size.id()!=ID_constant) - return "string of unknown size"; + exprt arr_val=get_array(arr); + exprt size_val=supert::get(size); + size_val=simplify_expr(size_val, ns); + typet char_type=arr.type().subtype(); + typet index_type=size.type(); + array_typet empty_ret_type(char_type, from_integer(0, index_type)); + array_of_exprt empty_ret(from_integer(0, char_type), empty_ret_type); + + if(size_val.id()!=ID_constant) + { +#if 0 + debug() << "(sr::get_array) string of unknown size: " + << from_expr(size_val) << eom; +#endif + return empty_ret; + } + unsigned n; - if(to_unsigned_integer(to_constant_expr(size), n)) - n=0; + if(to_unsigned_integer(to_constant_expr(size_val), n)) + { +#if 0 + debug() << "(sr::get_array) size is not valid" << eom; +#endif + return empty_ret; + } + + array_typet ret_type(char_type, from_integer(n, index_type)); + array_exprt ret(ret_type); if(n>MAX_CONCRETE_STRING_SIZE) - return "very long string"; + { +#if 0 + debug() << "(sr::get_array) long string (size=" << n << ")" << eom; +#endif + return empty_ret; + } + if(n==0) - return "\"\""; + { +#if 0 + debug() << "(sr::get_array) empty string" << eom; +#endif + return empty_ret; + } - std::ostringstream buf; - buf << "\""; - exprt val=get(arr); + std::vector concrete_array(n); - if(val.id()=="array-list") + if(arr_val.id()=="array-list") { - for(size_t i=0; i(c); + exprt value=arr_val.operands()[i*2+1]; + to_unsigned_integer(to_constant_expr(value), concrete_array[idx]); } } } } + else if(arr_val.id()==ID_array) + { + for(size_t i=0; i=32) + result << (unsigned char) c; + else + { + result << "\\u" << std::hex << std::setw(4) << std::setfill('0') + << (unsigned int) c; + } + } + + return result.str(); +} + +/*******************************************************************\ - for(size_t i=0; i violated; @@ -547,21 +1125,28 @@ bool string_refinementt::check_axioms() for(size_t i=0; i &m, bool negated) const + std::map &m, const typet &type, bool negated) const { exprt sum=nil_exprt(); mp_integer constants=0; typet index_type; if(m.empty()) - return nil_exprt(); + return from_integer(0, type); else index_type=m.begin()->first.type(); @@ -723,12 +1307,20 @@ exprt string_refinementt::sum_over_map( default: if(second>1) { - for(int i=0; isecond; i--) + if(sum.is_nil()) + sum=unary_minus_exprt(t); + else + sum=minus_exprt(sum, t); + for(int i=-1; i>second; i--) sum=minus_exprt(sum, t); } } @@ -755,7 +1347,7 @@ Function: string_refinementt::simplify_sum exprt string_refinementt::simplify_sum(const exprt &f) const { std::map map=map_representation_of_sum(f); - return sum_over_map(map); + return sum_over_map(map, f.type()); } /*******************************************************************\ @@ -800,7 +1392,7 @@ exprt string_refinementt::compute_inverse_function( } elems.erase(it); - return sum_over_map(elems, neg); + return sum_over_map(elems, f.type(), neg); } @@ -830,7 +1422,7 @@ Function: find_qvar Outputs: a Boolean - Purpose: looks for the symbol and return true if it is found + Purpose: look for the symbol and return true if it is found \*******************************************************************/ @@ -885,6 +1477,26 @@ Function: string_refinementt::initial_index_set and the upper bound minus one \*******************************************************************/ +void string_refinementt::add_to_index_set(const exprt &s, exprt i) +{ + simplify(i, ns); + if(i.id()==ID_constant) + { + mp_integer mpi; + to_integer(i, mpi); + if(mpi<0) + { + debug() << "add_to_index_set : ignoring negative number " << mpi << eom; + return; + } + } + if(index_set[s].insert(i).second) + { + debug() << "adding to index set of " << from_expr(s) + << ": " << from_expr(i) << eom; + current_index_set[s].insert(i); + } +} void string_refinementt::initial_index_set(const string_constraintt &axiom) { @@ -906,8 +1518,7 @@ void string_refinementt::initial_index_set(const string_constraintt &axiom) // if cur is of the form s[i] and no quantified variable appears in i if(!has_quant_var) { - current_index_set[s].insert(i); - index_set[s].insert(i); + add_to_index_set(s, i); } else { @@ -917,8 +1528,7 @@ void string_refinementt::initial_index_set(const string_constraintt &axiom) axiom.upper_bound(), from_integer(1, axiom.upper_bound().type())); replace_expr(qvar, kminus1, e); - current_index_set[s].insert(e); - index_set[s].insert(e); + add_to_index_set(s, e); } } else @@ -952,12 +1562,7 @@ void string_refinementt::update_index_set(const exprt &formula) const exprt &i=cur.op1(); assert(s.type().id()==ID_array); exprt simplified=simplify_sum(i); - if(index_set[s].insert(simplified).second) - { - debug() << "adding to index set of " << from_expr(s) - << ": " << from_expr(simplified) << eom; - current_index_set[s].insert(simplified); - } + add_to_index_set(s, simplified); } else { @@ -1014,19 +1619,18 @@ exprt find_index(const exprt &expr, const exprt &str) catch (exprt i) { return i; } } - /*******************************************************************\ Function: string_refinementt::instantiate - Inputs: an universaly quantified formula `axiom`, an array of char + Inputs: a universally quantified formula `axiom`, an array of char variable `str`, and an index expression `val`. - Outputs: substitute `qvar` the universaly quantified variable of `axiom`, by + Outputs: substitute `qvar` the universally quantified variable of `axiom`, by an index `val`, in `axiom`, so that the index used for `str` equals `val`. For instance, if `axiom` corresponds to - $\forall q. s[q+x]='a' && t[q]='b'$, `instantiate(axom,s,v)` would return - an expression for $s[v]='a' && t[v-x]='b'$. + $\forall q. s[q+x]='a' && t[q]='b'$, `instantiate(axom,s,v)` + would return an expression for $s[v]='a' && t[v-x]='b'$. \*******************************************************************/ @@ -1051,6 +1655,17 @@ exprt string_refinementt::instantiate( return implies_exprt(bounds, instance); } +/*******************************************************************\ + +Function: string_refinementt::instantiate_not_contains + + Inputs: a quantified formula representing `not_contains`, and a + list to which to add the created lemmas to + + Purpose: instantiate a quantified formula representing `not_contains` + by substituting the quantifiers and generating axioms + +\*******************************************************************/ void string_refinementt::instantiate_not_contains( const string_not_contains_constraintt &axiom, std::list &new_lemmas) @@ -1102,3 +1717,76 @@ void string_refinementt::instantiate_not_contains( new_lemmas.push_back(witness_bounds); } } + +/*******************************************************************\ + +Function: string_refinementt::substitute_array_lists() + + Inputs: an expression containing array-list expressions + + Outputs: an epression containing no array-list + + Purpose: replace array-lists by 'with' expressions + +\*******************************************************************/ + +exprt string_refinementt::substitute_array_lists(exprt expr) const +{ + for(size_t i=0; i=2); + typet &char_type=expr.operands()[1].type(); + array_typet arr_type(char_type, infinity_exprt(char_type)); + array_of_exprt new_arr(from_integer(0, char_type), + arr_type); + + with_exprt ret_expr(new_arr, + expr.operands()[0], + expr.operands()[1]); + + for(size_t i=2; isecond); + } + + ecopy=supert::get(ecopy); + + return substitute_array_lists(ecopy); +} diff --git a/src/solvers/refinement/string_refinement.h b/src/solvers/refinement/string_refinement.h index be0cd332bc3..6688401f40c 100644 --- a/src/solvers/refinement/string_refinement.h +++ b/src/solvers/refinement/string_refinement.h @@ -2,7 +2,7 @@ Module: String support via creating string constraints and progressively instantiating the universal constraints as needed. - The procedure is described in the PASS paper at HVC'13: + The procedure is described in the PASS paper at HVC'13: "PASS: String Solving with Parameterized Array and Interval Automaton" by Guodong Li and Indradeep Ghosh @@ -14,6 +14,7 @@ Author: Alberto Griggio, alberto.griggio@gmail.com #define CPROVER_SOLVERS_REFINEMENT_STRING_REFINEMENT_H #include +#include #include #include @@ -27,30 +28,37 @@ Author: Alberto Griggio, alberto.griggio@gmail.com class string_refinementt: public bv_refinementt { public: - // refinement_bound is a bound on the number of refinement allowed string_refinementt( - const namespacet &_ns, propt &_prop, unsigned refinement_bound); + const namespacet &_ns, + propt &_prop, + unsigned refinement_bound); void set_mode(); // Should we use counter examples at each iteration? bool use_counter_example; - virtual std::string decision_procedure_text() const + // Should we concretize strings when the solver finished + bool do_concretizing; + + void set_max_string_length(int i); + void enforce_non_empty_string(); + void enforce_printable_characters(); + + virtual std::string decision_procedure_text() const override { return "string refinement loop with "+prop.solver_text(); } static exprt is_positive(const exprt &x); + exprt get(const exprt &expr) const override; + protected: typedef std::set expr_sett; + typedef std::list exprt_listt; - virtual bvt convert_symbol(const exprt &expr); - virtual bvt convert_function_application( - const function_application_exprt &expr); - - decision_proceduret::resultt dec_solve(); + decision_proceduret::resultt dec_solve() override; bvt convert_bool_bv(const exprt &boole, const exprt &orig); @@ -60,8 +68,14 @@ class string_refinementt: public bv_refinementt unsigned initial_loop_bound; + // Is the current model correct + bool concrete_model; + string_constraint_generatort generator; + bool non_empty_string; + expr_sett nondet_arrays; + // Simple constraints that have been given to the solver expr_sett seen_instances; @@ -76,23 +90,44 @@ class string_refinementt: public bv_refinementt // Warning: this is indexed by array_expressions and not string expressions std::map current_index_set; std::map index_set; + replace_mapt symbol_resolve; + std::map reverse_symbol_resolve; + std::list> non_string_axioms; - void display_index_set(); + // Valuation in the current model of the symbols that have been created + // by the solver + replace_mapt current_model; - void add_lemma(const exprt &lemma, bool add_to_index_set=true); + void add_equivalence(const irep_idt & lhs, const exprt & rhs); - bool boolbv_set_equality_to_true(const equal_exprt &expr); + void display_index_set(); - literalt convert_rest(const exprt &expr); + void add_lemma(const exprt &lemma, + bool simplify=true, + bool add_to_index_set=true); - void add_instantiations(); + exprt substitute_function_applications(exprt expr); + typet substitute_java_string_types(typet type); + exprt substitute_java_strings(exprt expr); + exprt substitute_array_with_expr(exprt &expr, exprt &index) const; + exprt substitute_array_access(exprt &expr) const; + void add_symbol_to_symbol_map(const exprt &lhs, const exprt &rhs); + bool is_char_array(const typet &type) const; + bool add_axioms_for_string_assigns(const exprt &lhs, const exprt &rhs); + void set_to(const exprt &expr, bool value) override; + void add_instantiations(); + void add_negation_of_constraint_to_solver( + const string_constraintt &axiom, supert &solver); + void fill_model(); bool check_axioms(); + void set_char_array_equality(const exprt &lhs, const exprt &rhs); void update_index_set(const exprt &formula); void update_index_set(const std::vector &cur); void initial_index_set(const string_constraintt &axiom); void initial_index_set(const std::vector &string_axioms); + void add_to_index_set(const exprt &s, exprt i); exprt instantiate( const string_constraintt &axiom, const exprt &str, const exprt &val); @@ -101,17 +136,28 @@ class string_refinementt: public bv_refinementt const string_not_contains_constraintt &axiom, std::list &new_lemmas); + exprt substitute_array_lists(exprt) const; + exprt compute_inverse_function( const exprt &qvar, const exprt &val, const exprt &f); std::map map_representation_of_sum(const exprt &f) const; - exprt sum_over_map(std::map &m, bool negated=false) const; + exprt sum_over_map( + std::map &m, const typet &type, bool negated=false) const; exprt simplify_sum(const exprt &f) const; - exprt get_array(const exprt &arr, const exprt &size); + void concretize_string(const exprt &expr); + void concretize_results(); + void concretize_lengths(); + + // Length of char arrays found during concretization + std::map found_length; + + exprt get_array(const exprt &arr, const exprt &size) const; + exprt get_array(const exprt &arr) const; - std::string string_of_array(const exprt &arr, const exprt &size) const; + std::string string_of_array(const array_exprt &arr); }; #endif diff --git a/src/util/Makefile b/src/util/Makefile index fefabaed3af..0bfb2539af4 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -23,7 +23,9 @@ SRC = arith_tools.cpp base_type.cpp cmdline.cpp config.cpp symbol_table.cpp \ memory_info.cpp pipe_stream.cpp irep_hash.cpp endianness_map.cpp \ ssa_expr.cpp json_irep.cpp json_expr.cpp \ fresh_symbol.cpp \ - string_utils.cpp + string_utils.cpp \ + refined_string_type.cpp \ + #Empty last line INCLUDES= -I .. diff --git a/src/util/irep_ids.txt b/src/util/irep_ids.txt index 066a5f831cc..470a0f01c78 100644 --- a/src/util/irep_ids.txt +++ b/src/util/irep_ids.txt @@ -743,6 +743,7 @@ string_constraint string_not_contains_constraint cprover_char_literal_func cprover_string_literal_func +cprover_string_array_of_char_pointer_func cprover_string_char_at_func cprover_string_char_set_func cprover_string_code_point_at_func diff --git a/src/util/refined_string_type.cpp b/src/util/refined_string_type.cpp new file mode 100644 index 00000000000..0625149cf83 --- /dev/null +++ b/src/util/refined_string_type.cpp @@ -0,0 +1,51 @@ +/********************************************************************\ + +Module: Type for string expressions used by the string solver. + These string expressions contain a field `length`, of type + `index_type`, a field `content` of type `content_type`. + This module also defines functions to recognise the C and java + string types. + +Author: Romain Brenguier, romain.brenguier@diffblue.com + +\*******************************************************************/ + +#include + +#include "refined_string_type.h" + +/*******************************************************************\ + +Constructor: refined_string_typet::refined_string_typet + + Inputs: type of characters + +\*******************************************************************/ + +refined_string_typet::refined_string_typet( + const typet &index_type, const typet &char_type) +{ + infinity_exprt infinite_index(index_type); + array_typet char_array(char_type, infinite_index); + components().emplace_back("length", index_type); + components().emplace_back("content", char_array); + set_tag(CPROVER_PREFIX"refined_string_type"); +} + +/*******************************************************************\ + +Function: refined_string_typet::is_refined_string_type + + Inputs: a type + + Outputs: Boolean telling whether the input is a refined string type + +\*******************************************************************/ + +bool refined_string_typet::is_refined_string_type(const typet &type) +{ + return + type.id()==ID_struct && + to_struct_type(type).get_tag()==CPROVER_PREFIX"refined_string_type"; +} + diff --git a/src/solvers/refinement/refined_string_type.h b/src/util/refined_string_type.h similarity index 55% rename from src/solvers/refinement/refined_string_type.h rename to src/util/refined_string_type.h index 3ecc0ac3a9f..a0cb7500e7f 100644 --- a/src/solvers/refinement/refined_string_type.h +++ b/src/util/refined_string_type.h @@ -10,8 +10,8 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com \*******************************************************************/ -#ifndef CPROVER_SOLVERS_REFINEMENT_REFINED_STRING_TYPE_H -#define CPROVER_SOLVERS_REFINEMENT_REFINED_STRING_TYPE_H +#ifndef CPROVER_UTIL_REFINED_STRING_TYPE_H +#define CPROVER_UTIL_REFINED_STRING_TYPE_H #include #include @@ -33,41 +33,16 @@ class refined_string_typet: public struct_typet const typet &get_char_type() const { - assert(components().size()==2); - return components()[0].type(); + return get_content_type().subtype(); } const typet &get_index_type() const { - return get_content_type().size().type(); - } - - // For C the unrefined string type is __CPROVER_string, for java it is a - // pointer to a struct with tag java.lang.String - - static bool is_c_string_type(const typet &type); - - static bool is_java_string_pointer_type(const typet &type); - - static bool is_java_string_type(const typet &type); - - static bool is_java_string_builder_type(const typet &type); - - static bool is_java_char_sequence_type(const typet &type); - - static bool is_unrefined_string_type(const typet &type) - { - return ( - is_c_string_type(type) || - is_java_string_pointer_type(type) || - is_java_string_builder_type(type) || - is_java_char_sequence_type(type)); + assert(components().size()==2); + return components()[0].type(); } - static bool is_unrefined_string(const exprt &expr) - { - return (is_unrefined_string_type(expr.type())); - } + static bool is_refined_string_type(const typet &type); constant_exprt index_of_int(int i) const { @@ -75,9 +50,10 @@ class refined_string_typet: public struct_typet } }; -const refined_string_typet &to_refined_string_type(const typet &type) +extern inline const refined_string_typet &to_refined_string_type( + const typet &type) { - assert(type.id()==ID_struct); + assert(refined_string_typet::is_refined_string_type(type)); return static_cast(type); } diff --git a/src/util/std_expr.h b/src/util/std_expr.h index a2f78ab25e8..7debf8d7e62 100644 --- a/src/util/std_expr.h +++ b/src/util/std_expr.h @@ -3450,6 +3450,19 @@ class function_application_exprt:public exprt operands().resize(2); } + explicit function_application_exprt(const typet &_type): + exprt(ID_function_application, _type) + { + operands().resize(2); + } + + function_application_exprt( + const symbol_exprt &_function, const typet &_type): + function_application_exprt(_type) + { + function()=_function; + } + exprt &function() { return op0();