@@ -119,6 +119,8 @@ 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
123
+ rinner_classes_attribute (classt &parsed_class, const u4 &attribute_length);
122
124
void rclass_attribute (classt &parsed_class);
123
125
void rRuntimeAnnotation_attribute (annotationst &);
124
126
void rRuntimeAnnotation (annotationt &);
@@ -1576,6 +1578,68 @@ void java_bytecode_parsert::relement_value_pair(
1576
1578
}
1577
1579
}
1578
1580
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
+
1579
1643
void java_bytecode_parsert::rclass_attribute (classt &parsed_class)
1580
1644
{
1581
1645
u2 attribute_name_index=read_u2 ();
@@ -1642,52 +1706,8 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1642
1706
}
1643
1707
else if (attribute_name == " InnerClasses" )
1644
1708
{
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);
1691
1711
}
1692
1712
else
1693
1713
skip_bytes (attribute_length);
0 commit comments