@@ -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,77 @@ 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 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
+
1579
1652
void java_bytecode_parsert::rclass_attribute (classt &parsed_class)
1580
1653
{
1581
1654
u2 attribute_name_index=read_u2 ();
@@ -1640,6 +1713,11 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1640
1713
parsed_class.attribute_bootstrapmethods_read = true ;
1641
1714
read_bootstrapmethods_entry (parsed_class);
1642
1715
}
1716
+ else if (attribute_name == " InnerClasses" )
1717
+ {
1718
+ java_bytecode_parsert::rinner_classes_attribute (
1719
+ parsed_class, attribute_length);
1720
+ }
1643
1721
else
1644
1722
skip_bytes (attribute_length);
1645
1723
}
0 commit comments