Skip to content

Commit 819c683

Browse files
author
Thomas Kiley
authored
Merge pull request #2493 from jeannielynnmoulton/jeannie/InnerClasses
[TG-3694] Parse and store inner class information
2 parents 6e554d9 + 5350133 commit 819c683

32 files changed

+476
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ void java_bytecode_convert_classt::convert(
276276
class_type.set(ID_interface, c.is_interface);
277277
class_type.set(ID_synthetic, c.is_synthetic);
278278
class_type.set_final(c.is_final);
279+
class_type.set_is_inner_class(c.is_inner_class);
279280
if(c.is_enum)
280281
{
281282
if(max_array_length != 0 && c.enum_elements > max_array_length)

jbmc/src/java_bytecode/java_bytecode_parse_tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ class java_bytecode_parse_treet
217217
bool is_interface = false;
218218
bool is_synthetic = false;
219219
bool is_annotation = false;
220+
bool is_inner_class = false;
220221
bool attribute_bootstrapmethods_read = false;
221222
size_t enum_elements=0;
222223

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ class java_bytecode_parsert:public parsert
119119
void rfields(classt &parsed_class);
120120
void rmethods(classt &parsed_class);
121121
void rmethod(classt &parsed_class);
122+
void
123+
rinner_classes_attribute(classt &parsed_class, const u4 &attribute_length);
122124
void rclass_attribute(classt &parsed_class);
123125
void rRuntimeAnnotation_attribute(annotationst &);
124126
void rRuntimeAnnotation(annotationt &);
@@ -1576,6 +1578,77 @@ void java_bytecode_parsert::relement_value_pair(
15761578
}
15771579
}
15781580

1581+
/// Corresponds to the element_value structure
1582+
/// Described in Java 8 specification 4.7.6
1583+
/// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6
1584+
/// Parses the InnerClasses attribute for the current parsed class,
1585+
/// which contains an array of information about its inner classes. We are
1586+
/// interested in getting information only for inner classes, which is
1587+
/// determined by checking if the parsed class matches any of the inner classes
1588+
/// in its inner class array. If the parsed class is not an inner class, then it
1589+
/// is ignored. When a parsed class is an inner class, the accessibility
1590+
/// information for the parsed class is overwritten, and the parsed class is
1591+
/// marked as an inner class.
1592+
void java_bytecode_parsert::rinner_classes_attribute(
1593+
classt &parsed_class,
1594+
const u4 &attribute_length)
1595+
{
1596+
std::string name = parsed_class.name.c_str();
1597+
u2 number_of_classes = read_u2();
1598+
u4 number_of_bytes_to_be_read = number_of_classes * 8 + 2;
1599+
INVARIANT(
1600+
number_of_bytes_to_be_read == attribute_length,
1601+
"The number of bytes to be read for the InnerClasses attribute does not "
1602+
"match the attribute length.");
1603+
1604+
const auto pool_entry_lambda = [this](u2 index) -> pool_entryt & {
1605+
return pool_entry(index);
1606+
};
1607+
const auto remove_separator_char = [](std::string str, char ch) {
1608+
str.erase(std::remove(str.begin(), str.end(), ch), str.end());
1609+
return str;
1610+
};
1611+
1612+
for(int i = 0; i < number_of_classes; i++)
1613+
{
1614+
u2 inner_class_info_index = read_u2();
1615+
u2 outer_class_info_index = read_u2();
1616+
UNUSED u2 inner_name_index = read_u2();
1617+
u2 inner_class_access_flags = read_u2();
1618+
1619+
std::string inner_class_info_name =
1620+
class_infot(pool_entry(inner_class_info_index))
1621+
.get_name(pool_entry_lambda);
1622+
bool is_private = (inner_class_access_flags & ACC_PRIVATE) != 0;
1623+
bool is_public = (inner_class_access_flags & ACC_PUBLIC) != 0;
1624+
bool is_protected = (inner_class_access_flags & ACC_PROTECTED) != 0;
1625+
1626+
// If the original parsed class name matches the inner class name,
1627+
// the parsed class is an inner class, so overwrite the parsed class'
1628+
// access information and mark it as an inner class.
1629+
bool is_inner_class = remove_separator_char(id2string(parsed_class.name), '.') ==
1630+
remove_separator_char(inner_class_info_name, '/');
1631+
if(is_inner_class)
1632+
parsed_class.is_inner_class = is_inner_class;
1633+
if(!is_inner_class)
1634+
continue;
1635+
// Note that if outer_class_info_index == 0, the inner class is an anonymous
1636+
// or local class, and is treated as private.
1637+
if(outer_class_info_index == 0)
1638+
{
1639+
parsed_class.is_private = true;
1640+
parsed_class.is_protected = false;
1641+
parsed_class.is_public = false;
1642+
}
1643+
else
1644+
{
1645+
parsed_class.is_private = is_private;
1646+
parsed_class.is_protected = is_protected;
1647+
parsed_class.is_public = is_public;
1648+
}
1649+
}
1650+
}
1651+
15791652
void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
15801653
{
15811654
u2 attribute_name_index=read_u2();
@@ -1640,6 +1713,11 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
16401713
parsed_class.attribute_bootstrapmethods_read = true;
16411714
read_bootstrapmethods_entry(parsed_class);
16421715
}
1716+
else if(attribute_name == "InnerClasses")
1717+
{
1718+
java_bytecode_parsert::rinner_classes_attribute(
1719+
parsed_class, attribute_length);
1720+
}
16431721
else
16441722
skip_bytes(attribute_length);
16451723
}

jbmc/src/java_bytecode/java_types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ class java_class_typet:public class_typet
111111
return set(ID_access, access);
112112
}
113113

114+
const bool get_is_inner_class() const
115+
{
116+
return get_bool(ID_is_inner_class);
117+
}
118+
119+
void set_is_inner_class(const bool &is_inner_class)
120+
{
121+
return set(ID_is_inner_class, is_inner_class);
122+
}
123+
114124
bool get_final()
115125
{
116126
return get_bool(ID_final);

jbmc/unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SRC += java_bytecode/goto-programs/class_hierarchy_output.cpp \
1212
java_bytecode/java_bytecode_convert_class/convert_java_annotations.cpp \
1313
java_bytecode/java_bytecode_convert_method/convert_invoke_dynamic.cpp \
1414
java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp \
15+
java_bytecode/java_bytecode_parser/parse_java_attributes.cpp \
1516
java_bytecode/java_object_factory/gen_nondet_string_init.cpp \
1617
java_bytecode/java_bytecode_parse_lambdas/java_bytecode_parse_lambda_method_table.cpp \
1718
java_bytecode/java_bytecode_parse_lambdas/java_bytecode_convert_class_lambda_method_handles.cpp \
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)