Skip to content

Commit 1930aef

Browse files
Refactors parsing of inner classes attribute.
1 parent b28562b commit 1930aef

File tree

1 file changed

+66
-46
lines changed

1 file changed

+66
-46
lines changed

jbmc/src/java_bytecode/java_bytecode_parser.cpp

+66-46
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,68 @@ 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 bytes of the InnerClasses attribute for the current parsed class,
1585+
/// which contains any array of information about 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+
u2 number_of_classes = read_u2();
1597+
u4 number_of_bytes_to_be_read = number_of_classes * 8 + 2;
1598+
INVARIANT(
1599+
number_of_bytes_to_be_read == attribute_length,
1600+
"The number of bytes to be read for the InnerClasses attribute does not "
1601+
"match the attribute length.");
1602+
1603+
const auto pool_entry_lambda = [this](u2 index) -> pool_entryt & {
1604+
return pool_entry(index);
1605+
};
1606+
const auto remove_separator_char = [](std::string str, char ch) {
1607+
str.erase(std::remove(str.begin(), str.end(), ch), str.end());
1608+
return str;
1609+
};
1610+
1611+
for(int i = 0; i < number_of_classes; i++)
1612+
{
1613+
u2 inner_class_info_index = read_u2();
1614+
UNUSED u2 outer_class_info_index = read_u2();
1615+
UNUSED u2 inner_name_index = read_u2();
1616+
u2 inner_class_access_flags = read_u2();
1617+
1618+
if(inner_class_info_index == 0)
1619+
continue;
1620+
1621+
std::string inner_class_info_name =
1622+
class_infot(pool_entry(inner_class_info_index))
1623+
.get_name(pool_entry_lambda);
1624+
bool is_private = inner_class_access_flags & ACC_PRIVATE;
1625+
bool is_public = inner_class_access_flags & ACC_PUBLIC;
1626+
bool is_protected = inner_class_access_flags & ACC_PROTECTED;
1627+
1628+
// If the original parsed class name matches the inner class name,
1629+
// the parsed class is an inner class, so overwrite the parsed class'
1630+
// access information and mark it as an inner class
1631+
parsed_class.is_inner_class =
1632+
remove_separator_char(id2string(parsed_class.name), '.') ==
1633+
remove_separator_char(inner_class_info_name, '/');
1634+
if(parsed_class.is_inner_class)
1635+
{
1636+
parsed_class.is_private = is_private;
1637+
parsed_class.is_protected = is_protected;
1638+
parsed_class.is_public = is_public;
1639+
}
1640+
}
1641+
}
1642+
15791643
void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
15801644
{
15811645
u2 attribute_name_index=read_u2();
@@ -1642,52 +1706,8 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
16421706
}
16431707
else if(attribute_name == "InnerClasses")
16441708
{
1645-
u2 number_of_classes = read_u2();
1646-
u4 number_of_bytes_to_be_read = number_of_classes * 8 + 2;
1647-
INVARIANT(
1648-
number_of_bytes_to_be_read == attribute_length,
1649-
"The number of bytes to be read for the InnerClasses attribute does not "
1650-
"match the attribute length.");
1651-
1652-
const std::function<pool_entryt &(u2)> pool_entry_lambda =
1653-
[this](u2 index) -> pool_entryt & { return pool_entry(index); };
1654-
std::function<std::string(std::string, char)> remove_separator_char =
1655-
[](std::string str, char ch) {
1656-
str.erase(std::remove(str.begin(), str.end(), ch), str.end());
1657-
return str;
1658-
};
1659-
1660-
for(int i = 0; i < number_of_classes; i++)
1661-
{
1662-
u2 inner_class_info_index = read_u2();
1663-
UNUSED u2 outer_class_info_index = read_u2();
1664-
UNUSED u2 inner_name_index = read_u2();
1665-
u2 inner_class_access_flags = read_u2();
1666-
1667-
if(inner_class_info_index != 0)
1668-
{
1669-
std::string inner_class_info_name =
1670-
class_infot(pool_entry(inner_class_info_index))
1671-
.get_name(pool_entry_lambda);
1672-
bool is_private = inner_class_access_flags & ACC_PRIVATE;
1673-
bool is_public = inner_class_access_flags & ACC_PUBLIC;
1674-
bool is_protected = inner_class_access_flags & ACC_PROTECTED;
1675-
1676-
// If the original parsed class name matches the inner class name
1677-
// the parsed class is an inner class, so overwrite the parsed class'
1678-
// access information and mark it as an inner class
1679-
bool is_inner_class =
1680-
remove_separator_char(id2string(parsed_class.name), '.') ==
1681-
remove_separator_char(inner_class_info_name, '/');
1682-
if(is_inner_class)
1683-
{
1684-
parsed_class.is_inner_class = is_inner_class;
1685-
parsed_class.is_private = is_private;
1686-
parsed_class.is_protected = is_protected;
1687-
parsed_class.is_public = is_public;
1688-
}
1689-
}
1690-
}
1709+
java_bytecode_parsert::rinner_classes_attribute(
1710+
parsed_class, attribute_length);
16911711
}
16921712
else
16931713
skip_bytes(attribute_length);

0 commit comments

Comments
 (0)