@@ -119,6 +119,7 @@ class java_bytecode_parsert:public parsert
119
119
void rfields (classt &parsed_class);
120
120
void rmethods (classt &parsed_class);
121
121
void rmethod (classt &parsed_class);
122
+ void rinner_classes_attribute (classt &parsed_class, const u4 &attribute_length);
122
123
void rclass_attribute (classt &parsed_class);
123
124
void rRuntimeAnnotation_attribute (annotationst &);
124
125
void rRuntimeAnnotation (annotationt &);
@@ -1576,6 +1577,65 @@ void java_bytecode_parsert::relement_value_pair(
1576
1577
}
1577
1578
}
1578
1579
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
+
1579
1639
void java_bytecode_parsert::rclass_attribute (classt &parsed_class)
1580
1640
{
1581
1641
u2 attribute_name_index=read_u2 ();
@@ -1642,52 +1702,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1642
1702
}
1643
1703
else if (attribute_name == " InnerClasses" )
1644
1704
{
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);
1691
1706
}
1692
1707
else
1693
1708
skip_bytes (attribute_length);
0 commit comments