Skip to content

Commit d9694d5

Browse files
author
svorenova
authored
Merge pull request diffblue#4439 from svorenova/opaque-fields-final
[TG-6381] Set opaque fields as final
2 parents d583164 + 1c4444a commit d9694d5

File tree

7 files changed

+66
-0
lines changed

7 files changed

+66
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ bool java_bytecode_languaget::parse(
297297
/// without realising that is in fact the same field, inherited from that
298298
/// ancestor. This can lead to incorrect results when opaque types are cast
299299
/// to other opaque types and their fields do not alias as intended.
300+
/// We set opaque fields as final to avoid assuming they can be overridden.
300301
/// \param parse_tree: class parse tree
301302
/// \param symbol_table: global symbol table
302303
static void infer_opaque_type_fields(
@@ -335,6 +336,7 @@ static void infer_opaque_type_fields(
335336
components.emplace_back(component_name, fieldref.type());
336337
components.back().set_base_name(component_name);
337338
components.back().set_pretty_name(component_name);
339+
components.back().set_is_final(true);
338340
break;
339341
}
340342
else
@@ -501,6 +503,8 @@ static void create_stub_global_symbol(
501503
// whereas a more restricted visbility would encourage separating them.
502504
// Neither is correct, as without the class file we can't know the truth.
503505
new_symbol.type.set(ID_C_access, ID_public);
506+
// We set the field as final to avoid assuming they can be overridden.
507+
new_symbol.type.set(ID_C_constant, true);
504508
new_symbol.pretty_name = new_symbol.name;
505509
new_symbol.mode = ID_java;
506510
new_symbol.is_type = false;

jbmc/unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SRC += java_bytecode/ci_lazy_methods/lazy_load_lambdas.cpp \
2020
java_bytecode/java_bytecode_convert_method/convert_invoke_dynamic.cpp \
2121
java_bytecode/java_bytecode_convert_method/convert_method.cpp \
2222
java_bytecode/java_bytecode_instrument/virtual_call_null_checks.cpp \
23+
java_bytecode/java_bytecode_language/language.cpp \
2324
java_bytecode/java_bytecode_parse_generics/parse_bounded_generic_inner_classes.cpp \
2425
java_bytecode/java_bytecode_parse_generics/parse_derived_generic_class.cpp \
2526
java_bytecode/java_bytecode_parse_generics/parse_functions_with_generics.cpp \
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public class ClassUsingOpaqueField {
2+
public static int opaqueFieldMethod() {
3+
OpaqueClass o = new OpaqueClass();
4+
return OpaqueClass.field1 + o.field2;
5+
}
6+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// .class file must be deleted
2+
public class OpaqueClass {
3+
public static int field1 = 1;
4+
public int field2;
5+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for java_bytecode_language.
4+
5+
Author: Diffblue Limited.
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/use_catch.h>
10+
11+
#include <util/symbol_table.h>
12+
13+
#include <java-testing-utils/load_java_class.h>
14+
#include <java-testing-utils/require_type.h>
15+
16+
SCENARIO(
17+
"java_bytecode_language_opaque_field",
18+
"[core][java_bytecode][java_bytecode_language]")
19+
{
20+
GIVEN("A class that accesses opaque fields")
21+
{
22+
const symbol_tablet symbol_table = load_java_class(
23+
"ClassUsingOpaqueField", "./java_bytecode/java_bytecode_language");
24+
std::string opaque_class_prefix = "java::OpaqueClass";
25+
26+
WHEN("When parsing opaque class with fields")
27+
{
28+
THEN("Static field field1 is marked as final")
29+
{
30+
const symbolt &opaque_field_symbol =
31+
symbol_table.lookup_ref(opaque_class_prefix + ".field1");
32+
REQUIRE(opaque_field_symbol.type.get_bool(ID_C_constant));
33+
}
34+
35+
THEN("Non-static field field2 is marked final")
36+
{
37+
const symbolt &opaque_class_symbol =
38+
symbol_table.lookup_ref(opaque_class_prefix);
39+
const struct_typet &opaque_class_struct =
40+
to_struct_type(opaque_class_symbol.type);
41+
const struct_union_typet::componentt &field =
42+
require_type::require_component(opaque_class_struct, "field2");
43+
REQUIRE(field.get_is_final());
44+
}
45+
}
46+
}
47+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
java-testing-utils
2+
testing-utils
3+
util

0 commit comments

Comments
 (0)