Skip to content

Commit 24b3f75

Browse files
Merge pull request #1618 from romainbrenguier/bugfix/string-equals#TG1619
Fix problem with String.equals not checking the argument is a String TG-1619
2 parents 02e7b4a + 0dd029d commit 24b3f75

File tree

5 files changed

+67
-6
lines changed

5 files changed

+67
-6
lines changed
871 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
public class Test {
2+
public static void check(int i, String s) {
3+
String t = "Hello World";
4+
Integer x = new Integer(2);
5+
if (i==0)
6+
assert("Hello World".equals(t));
7+
else if (i==1)
8+
assert(! "Hello World".equals(s));
9+
else if (i==2)
10+
assert(! "Hello World".equals(x));
11+
else if (i==3)
12+
assert("Hello World".equals(x));
13+
else if (i==4)
14+
assert(! s.equals(x));
15+
else if (i==5)
16+
assert(s.equals(x));
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
Test.class
3+
--refine-strings --string-max-length 1000 --function Test.check
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
assertion at file Test.java line 6 .* SUCCESS
7+
assertion at file Test.java line 8 .* FAILURE
8+
assertion at file Test.java line 10 .* SUCCESS
9+
assertion at file Test.java line 12 .* FAILURE
10+
assertion at file Test.java line 14 .* SUCCESS
11+
assertion at file Test.java line 16 .* FAILURE
12+
--

src/java_bytecode/java_object_factory.cpp

+13-3
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,19 @@ codet initialize_nondet_string_struct(
571571

572572
// `obj` is `*expr`
573573
const struct_typet &struct_type = to_struct_type(ns.follow(obj.type()));
574-
const irep_idt &class_id = "java::" + id2string(struct_type.get_tag());
575-
576-
// @clsid = String and @lock = false:
574+
// @clsid = java::java.lang.String or similar.
575+
// We allow type StringBuffer and StringBuilder to be initialized
576+
// in the same way has String, because they have the same structure and
577+
// are treated in the same way by CBMC.
578+
// Note that CharSequence cannot be used as classid because it's abstract,
579+
// so it is replaced by String.
580+
// \todo allow StringBuffer and StringBuilder as classid for Charsequence
581+
const irep_idt &class_id =
582+
struct_type.get_tag() == "java.lang.CharSequence"
583+
? "java::java.lang.String"
584+
: "java::" + id2string(struct_type.get_tag());
585+
586+
// @lock = false:
577587
const symbol_typet jlo_symbol("java::java.lang.Object");
578588
const struct_typet &jlo_type = to_struct_type(ns.follow(jlo_symbol));
579589
struct_exprt jlo_init(jlo_symbol);

src/java_bytecode/java_string_library_preprocess.cpp

+24-3
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,6 @@ codet java_string_library_preprocesst::make_equals_function_code(
913913
const source_locationt &loc,
914914
symbol_table_baset &symbol_table)
915915
{
916-
// TODO: Code should return false if Object is not String.
917916
code_blockt code;
918917
exprt::operandst ops;
919918
for(const auto &p : type.parameters())
@@ -923,8 +922,30 @@ codet java_string_library_preprocesst::make_equals_function_code(
923922
}
924923
exprt::operandst args=process_equals_function_operands(
925924
ops, loc, symbol_table, code);
926-
code.add(code_return_function_application(
927-
ID_cprover_string_equal_func, args, type.return_type(), symbol_table));
925+
926+
member_exprt class_identifier(
927+
checked_dereference(ops[1], ops[1].type().subtype()),
928+
"@class_identifier",
929+
string_typet());
930+
931+
// Check the object argument is a String.
932+
equal_exprt arg_is_string(
933+
class_identifier, constant_exprt("java::java.lang.String", string_typet()));
934+
935+
// Check content equality
936+
const symbolt string_equals_sym = get_fresh_aux_symbol(
937+
java_boolean_type(), "string_equals", "str_eq", loc, ID_java, symbol_table);
938+
const symbol_exprt string_equals = string_equals_sym.symbol_expr();
939+
code.add(code_declt(string_equals));
940+
code.add(code_assignt(
941+
string_equals,
942+
make_function_application(
943+
ID_cprover_string_equal_func, args, type.return_type(), symbol_table)));
944+
945+
code.add(code_returnt(if_exprt(
946+
arg_is_string,
947+
string_equals,
948+
from_integer(false, java_boolean_type()))));
928949
return code;
929950
}
930951

0 commit comments

Comments
 (0)