Skip to content

Commit d6783d8

Browse files
committed
Java method converter: look for inherited static fields
Previously it assumed that static field references were resolved in the bytecode (e.g. that a reference to A.somefield meant that A defines somefield). However in fact they can be inherited, and especially now that stub fields can be created on parent classes they are likely to appear there. As such the "get/putstatic" instructions now search the class hierarchy for the field they actually refer to.
1 parent 32cc538 commit d6783d8

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,7 +1996,9 @@ codet java_bytecode_convert_methodt::convert_instructions(
19961996
const auto &field_name=arg0.get_string(ID_component_name);
19971997
const bool is_assertions_disabled_field=
19981998
field_name.find("$assertionsDisabled")!=std::string::npos;
1999-
symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name);
1999+
2000+
symbol_expr.set_identifier(
2001+
get_static_field(arg0.get_string(ID_class), field_name));
20002002

20012003
INVARIANT(
20022004
symbol_table.has_symbol(symbol_expr.get_identifier()),
@@ -2025,6 +2027,9 @@ codet java_bytecode_convert_methodt::convert_instructions(
20252027
}
20262028
results[0]=java_bytecode_promotion(symbol_expr);
20272029

2030+
// Note this initialiser call deliberately inits the class used to make
2031+
// the reference, which may be a child of the class that actually defines
2032+
// the field.
20282033
codet clinit_call=get_clinit_call(arg0.get_string(ID_class));
20292034
if(clinit_call.get_statement()!=ID_skip)
20302035
c=clinit_call;
@@ -2052,7 +2057,8 @@ codet java_bytecode_convert_methodt::convert_instructions(
20522057
assert(op.size()==1 && results.empty());
20532058
symbol_exprt symbol_expr(arg0.type());
20542059
const auto &field_name=arg0.get_string(ID_component_name);
2055-
symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name);
2060+
symbol_expr.set_identifier(
2061+
get_static_field(arg0.get_string(ID_class), field_name));
20562062

20572063
INVARIANT(
20582064
symbol_table.has_symbol(symbol_expr.get_identifier()),
@@ -2067,6 +2073,9 @@ codet java_bytecode_convert_methodt::convert_instructions(
20672073
code_blockt block;
20682074
block.add_source_location()=i_it->source_location;
20692075

2076+
// Note this initialiser call deliberately inits the class used to make
2077+
// the reference, which may be a child of the class that actually defines
2078+
// the field.
20702079
codet clinit_call=get_clinit_call(arg0.get_string(ID_class));
20712080
if(clinit_call.get_statement()!=ID_skip)
20722081
block.move_to_operands(clinit_call);
@@ -2822,6 +2831,30 @@ bool java_bytecode_convert_methodt::is_method_inherited(
28222831
return inherited_method.is_valid();
28232832
}
28242833

2834+
/// Get static field identifier referred to by `class_identifier.component_name`
2835+
/// Note this may be inherited from either a parent or an interface.
2836+
/// \param class_identifier: class used to refer to the field
2837+
/// \param component_name: component (static field) name
2838+
/// \return identifier of the actual concrete field referred to
2839+
irep_idt java_bytecode_convert_methodt::get_static_field(
2840+
const irep_idt &class_identifier,
2841+
const irep_idt &component_name) const
2842+
{
2843+
resolve_inherited_componentt::inherited_componentt inherited_method =
2844+
get_inherited_component(
2845+
class_identifier,
2846+
component_name,
2847+
symbol_table.lookup_ref(current_method).type.get(ID_C_class),
2848+
symbol_table,
2849+
class_hierarchy,
2850+
true);
2851+
2852+
INVARIANT(
2853+
inherited_method.is_valid(), "static field should be in symbol table");
2854+
2855+
return inherited_method.get_full_component_identifier();
2856+
}
2857+
28252858
/// create temporary variables if a write instruction can have undesired side-
28262859
/// effects
28272860
void java_bytecode_convert_methodt::save_stack_entries(

src/java_bytecode/java_bytecode_convert_method_class.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ class java_bytecode_convert_methodt:public messaget
257257
const irep_idt &classname,
258258
const irep_idt &methodid) const;
259259

260+
irep_idt get_static_field(
261+
const irep_idt &class_identifier, const irep_idt &component_name) const;
262+
260263
enum class bytecode_write_typet { VARIABLE, ARRAY_REF, STATIC_FIELD, FIELD};
261264
void save_stack_entries(
262265
const std::string &,

0 commit comments

Comments
 (0)