forked from diffblue/cbmc
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tolerate stub static fields defined on non-stub types
Normally this situation (a reference to static field A.x, when neither A nor any of its ancestors either define a field x or are opaque stubs) would be an error, probably indicating a class version mismatch, but at present some of our library models intentionally exploit this behaviour to obtain a nondet- initialised field. Therefore for the time being we tolerate the situation, initialising such fields in __CPROVER_initialize, as we cannot attach a synthetic clinit method to a non-stub type.
- Loading branch information
Showing
6 changed files
with
76 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ Author: Chris Smowton, [email protected] | |
|
||
#include "java_static_initializers.h" | ||
#include "java_object_factory.h" | ||
#include "java_utils.h" | ||
#include <goto-programs/class_hierarchy.h> | ||
#include <util/std_types.h> | ||
#include <util/std_expr.h> | ||
|
@@ -266,8 +267,20 @@ void stub_global_initializer_factoryt::create_stub_global_initializer_symbols( | |
// Populate map from class id -> stub globals: | ||
for(const irep_idt &stub_global : stub_globals_set) | ||
{ | ||
const symbolt &global_symbol = symbol_table.lookup_ref(stub_global); | ||
if(global_symbol.value.is_nil()) | ||
{ | ||
// This symbol is already nondet-initialised during __CPROVER_initialize | ||
// (generated in java_static_lifetime_init). In future this will only | ||
// be the case for primitive-typed fields, but for now reference-typed | ||
// fields can also be treated this way in the exceptional case that they | ||
// belong to a non-stub class. Skip the field, as it does not need a | ||
// synthetic static initializer. | ||
continue; | ||
} | ||
|
||
const irep_idt class_id = | ||
symbol_table.lookup_ref(stub_global).type.get(ID_C_class); | ||
global_symbol.type.get(ID_C_class); | ||
INVARIANT( | ||
!class_id.empty(), | ||
"static field should be annotated with its defining class"); | ||
|
@@ -283,6 +296,9 @@ void stub_global_initializer_factoryt::create_stub_global_initializer_symbols( | |
{ | ||
const irep_idt static_init_name = clinit_function_name(it->first); | ||
|
||
INVARIANT( | ||
symbol_table.lookup_ref(it->first).type.get_bool(ID_incomplete_class), | ||
"only incomplete classes should be given synthetic static initialisers"); | ||
INVARIANT( | ||
!symbol_table.has_symbol(static_init_name), | ||
"a class cannot be both incomplete, and so have stub static fields, and " | ||
|
@@ -315,20 +331,6 @@ void stub_global_initializer_factoryt::create_stub_global_initializer_symbols( | |
} | ||
} | ||
|
||
/// Check if a symbol is a well-known non-null global | ||
/// \param symbolid: symbol id to check | ||
/// \return true if this static field is known never to be null | ||
static bool is_non_null_library_global(const irep_idt &symbolid) | ||
{ | ||
static const std::unordered_set<irep_idt, irep_id_hash> non_null_globals = | ||
{ | ||
"java::java.lang.System.out", | ||
"java::java.lang.System.err", | ||
"java::java.lang.System.in" | ||
}; | ||
return non_null_globals.count(symbolid); | ||
} | ||
|
||
/// Create the body of a synthetic static initializer (clinit method), | ||
/// which initialise stub globals in the same manner as | ||
/// java_static_lifetime_init, only delayed until first reference by virtue of | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ Author: Daniel Kroening, [email protected] | |
#include <util/string_utils.h> | ||
|
||
#include <set> | ||
#include <unordered_set> | ||
|
||
bool java_is_array_type(const typet &type) | ||
{ | ||
|
@@ -413,3 +414,17 @@ resolve_inherited_componentt::inherited_componentt get_inherited_component( | |
return resolve_inherited_componentt::inherited_componentt(); | ||
} | ||
} | ||
|
||
/// Check if a symbol is a well-known non-null global | ||
/// \param symbolid: symbol id to check | ||
/// \return true if this static field is known never to be null | ||
bool is_non_null_library_global(const irep_idt &symbolid) | ||
{ | ||
static const std::unordered_set<irep_idt, irep_id_hash> non_null_globals = | ||
{ | ||
"java::java.lang.System.out", | ||
"java::java.lang.System.err", | ||
"java::java.lang.System.in" | ||
}; | ||
return non_null_globals.count(symbolid); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters