Skip to content

Commit f005427

Browse files
committed
Fix global variable initialisation
External globals (static fields in Java) should have been annotated with the static_lifetime attribute and consequently initialised with either null, or an actual instance of the right type. Instead they were given nondet pointers which could lead to odd results, such as apparently being neither null nor pointing to something of the expected type. This restores proper initialisation, and excludes global void* fields (currently only the #exception_value special returns match this definition)
1 parent 65835c2 commit f005427

File tree

5 files changed

+71
-25
lines changed

5 files changed

+71
-25
lines changed
569 Bytes
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
test.class
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class A
2+
{
3+
public static A external_global;
4+
public int i;
5+
};
6+
7+
public class test
8+
{
9+
public static void main()
10+
{
11+
if(A.external_global == null)
12+
return;
13+
A local = A.external_global;
14+
assert(local instanceof A);
15+
}
16+
}

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,6 +2014,10 @@ codet java_bytecode_convert_methodt::convert_instructions(
20142014
const bool is_assertions_disabled_field=
20152015
field_name.find("$assertionsDisabled")!=std::string::npos;
20162016
symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name);
2017+
2018+
// If external, create a symbol table entry for this static field:
2019+
check_static_field_stub(symbol_expr, field_name);
2020+
20172021
if(lazy_methods)
20182022
{
20192023
if(arg0.type().id()==ID_symbol)
@@ -2056,6 +2060,10 @@ codet java_bytecode_convert_methodt::convert_instructions(
20562060
symbol_exprt symbol_expr(arg0.type());
20572061
const auto &field_name=arg0.get_string(ID_component_name);
20582062
symbol_expr.set_identifier(arg0.get_string(ID_class)+"."+field_name);
2063+
2064+
// If external, create a symbol table entry for this static field:
2065+
check_static_field_stub(symbol_expr, field_name);
2066+
20592067
if(lazy_methods && arg0.type().id()==ID_symbol)
20602068
{
20612069
lazy_methods->add_needed_class(

src/java_bytecode/java_object_factory.cpp

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,8 @@ void java_object_factoryt::gen_nondet_pointer_init(
473473
alloc_type,
474474
update_in_placet::NO_UPDATE_IN_PLACE);
475475

476+
auto set_null_inst=get_null_assignment(expr, pointer_type);
477+
476478
// Determine whether the pointer can be null.
477479
// In particular the array field of a String should not be null.
478480
bool not_null=
@@ -483,7 +485,18 @@ void java_object_factoryt::gen_nondet_pointer_init(
483485
class_identifier=="java.lang.CharSequence") &&
484486
subtype.id()==ID_array);
485487

486-
if(not_null)
488+
// Alternatively, if this is a void* we *must* initialise with null:
489+
// (This can currently happen for some cases of #exception_value)
490+
bool must_be_null=
491+
subtype==empty_typet();
492+
493+
if(must_be_null)
494+
{
495+
// Add the following code to assignments:
496+
// <expr> = nullptr;
497+
new_object_assignments.add(set_null_inst);
498+
}
499+
else if(not_null)
487500
{
488501
// Add the following code to assignments:
489502
// <expr> = <aoe>;
@@ -500,8 +513,6 @@ void java_object_factoryt::gen_nondet_pointer_init(
500513
// <code from recursive call to gen_nondet_init() with
501514
// tmp$<temporary_counter>>
502515
// }
503-
auto set_null_inst=get_null_assignment(expr, pointer_type);
504-
505516
code_ifthenelset null_check;
506517
null_check.cond()=side_effect_expr_nondett(bool_typet());
507518
null_check.then_case()=set_null_inst;
@@ -900,6 +911,29 @@ void java_object_factoryt::gen_nondet_array_init(
900911
assignments.move_to_operands(init_done_label);
901912
}
902913

914+
/// Add code_declt instructions to `init_code` for every non-static symbol
915+
/// in `symbols_created`
916+
/// \param symbols_created: list of symbols
917+
/// \param loc: source location for new code_declt instances
918+
/// \param [out] init_code: gets code_declt for each symbol
919+
static void declare_created_symbols(
920+
const std::vector<const symbolt *> &symbols_created,
921+
const source_locationt &loc,
922+
code_blockt &init_code)
923+
{
924+
// Add the following code to init_code for each symbol that's been created:
925+
// <type> <identifier>;
926+
for(const symbolt * const symbol_ptr : symbols_created)
927+
{
928+
if(!symbol_ptr->is_static_lifetime)
929+
{
930+
code_declt decl(symbol_ptr->symbol_expr());
931+
decl.add_source_location()=loc;
932+
init_code.add(decl);
933+
}
934+
}
935+
}
936+
903937
/// Similar to `gen_nondet_init`, but returns an object expression
904938
/// rather than assigning to one.
905939
/// \param type: type of new object to create
@@ -960,17 +994,7 @@ exprt object_factory(
960994
typet(),
961995
update_in_placet::NO_UPDATE_IN_PLACE);
962996

963-
// Add the following code to init_code for each symbol that's been created:
964-
// <type> <identifier>;
965-
for(const symbolt * const symbol_ptr : symbols_created)
966-
{
967-
if(!symbol_ptr->is_static_lifetime)
968-
{
969-
code_declt decl(symbol_ptr->symbol_expr());
970-
decl.add_source_location()=loc;
971-
init_code.add(decl);
972-
}
973-
}
997+
declare_created_symbols(symbols_created, loc, init_code);
974998

975999
init_code.append(assignments);
9761000
return object;
@@ -1026,17 +1050,7 @@ void gen_nondet_init(
10261050
typet(),
10271051
update_in_place);
10281052

1029-
// Add the following code to init_code for each symbol that's been created:
1030-
// <type> <identifier>;
1031-
for(const symbolt * const symbol_ptr : symbols_created)
1032-
{
1033-
if(!symbol_ptr->is_static_lifetime)
1034-
{
1035-
code_declt decl(symbol_ptr->symbol_expr());
1036-
decl.add_source_location()=loc;
1037-
init_code.add(decl);
1038-
}
1039-
}
1053+
declare_created_symbols(symbols_created, loc, init_code);
10401054

10411055
init_code.append(assignments);
10421056
}

0 commit comments

Comments
 (0)