Skip to content

Commit 2a8fb02

Browse files
fixup! Updates parser with reviewer comments
1 parent 191e1b7 commit 2a8fb02

File tree

1 file changed

+61
-46
lines changed

1 file changed

+61
-46
lines changed

jbmc/src/java_bytecode/java_bytecode_parser.cpp

+61-46
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ 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 rinner_classes_attribute(classt &parsed_class, const u4 &attribute_length);
122123
void rclass_attribute(classt &parsed_class);
123124
void rRuntimeAnnotation_attribute(annotationst &);
124125
void rRuntimeAnnotation(annotationt &);
@@ -1576,6 +1577,65 @@ void java_bytecode_parsert::relement_value_pair(
15761577
}
15771578
}
15781579

1580+
/// Corresponds to the element_value structure
1581+
/// Described in Java 8 specification 4.7.6
1582+
/// https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6
1583+
/// Parses the bytes of the InnerClasses attribute for the current parsed class,
1584+
/// which contains any array of information about inner classes. We are
1585+
/// interested in getting information only for inner classes, which is
1586+
/// determined by checking if the parsed class matches any of the inner classes
1587+
/// in its inner class array. If the parsed class is not an inner class, then it
1588+
/// is ignored. When a parsed class is an inner class, the accessibility
1589+
/// information for the parsed class is overwritten, and the parsed class is
1590+
/// marked as an inner class.
1591+
void java_bytecode_parsert::rinner_classes_attribute(classt &parsed_class, const u4 &attribute_length)
1592+
{
1593+
u2 number_of_classes = read_u2();
1594+
u4 number_of_bytes_to_be_read = number_of_classes * 8 + 2;
1595+
INVARIANT(
1596+
number_of_bytes_to_be_read == attribute_length,
1597+
"The number of bytes to be read for the InnerClasses attribute does not "
1598+
"match the attribute length.");
1599+
1600+
const auto pool_entry_lambda =
1601+
[this](u2 index) -> pool_entryt & { return pool_entry(index); };
1602+
const auto remove_separator_char =
1603+
[](std::string str, char ch) {
1604+
str.erase(std::remove(str.begin(), str.end(), ch), str.end());
1605+
return str;
1606+
};
1607+
1608+
for(int i = 0; i < number_of_classes; i++)
1609+
{
1610+
u2 inner_class_info_index = read_u2();
1611+
UNUSED u2 outer_class_info_index = read_u2();
1612+
UNUSED u2 inner_name_index = read_u2();
1613+
u2 inner_class_access_flags = read_u2();
1614+
1615+
if(inner_class_info_index == 0) continue;
1616+
1617+
std::string inner_class_info_name =
1618+
class_infot(pool_entry(inner_class_info_index))
1619+
.get_name(pool_entry_lambda);
1620+
bool is_private = inner_class_access_flags & ACC_PRIVATE;
1621+
bool is_public = inner_class_access_flags & ACC_PUBLIC;
1622+
bool is_protected = inner_class_access_flags & ACC_PROTECTED;
1623+
1624+
// If the original parsed class name matches the inner class name,
1625+
// the parsed class is an inner class, so overwrite the parsed class'
1626+
// access information and mark it as an inner class
1627+
parsed_class.is_inner_class =
1628+
remove_separator_char(id2string(parsed_class.name), '.') ==
1629+
remove_separator_char(inner_class_info_name, '/');
1630+
if(parsed_class.is_inner_class)
1631+
{
1632+
parsed_class.is_private = is_private;
1633+
parsed_class.is_protected = is_protected;
1634+
parsed_class.is_public = is_public;
1635+
}
1636+
}
1637+
}
1638+
15791639
void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
15801640
{
15811641
u2 attribute_name_index=read_u2();
@@ -1642,52 +1702,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
16421702
}
16431703
else if(attribute_name == "InnerClasses")
16441704
{
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-
}
1705+
java_bytecode_parsert::rinner_classes_attribute(parsed_class, attribute_length);
16911706
}
16921707
else
16931708
skip_bytes(attribute_length);

0 commit comments

Comments
 (0)