@@ -136,6 +136,7 @@ class java_bytecode_parsert:public parsert
136
136
void parse_local_variable_type_table (methodt &method);
137
137
optionalt<lambda_method_handlet>
138
138
parse_method_handle (const class method_handle_infot &entry);
139
+ void read_bootstrapmethods_entry (classt &);
139
140
140
141
void skip_bytes (std::size_t bytes)
141
142
{
@@ -1595,117 +1596,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1595
1596
1596
1597
// mark as read in parsed class
1597
1598
parsed_class.attribute_bootstrapmethods_read = true ;
1598
- u2 num_bootstrap_methods = read_u2 ();
1599
- for (size_t i = 0 ; i < num_bootstrap_methods; i++)
1600
- {
1601
- u2 bootstrap_methodhandle_ref = read_u2 ();
1602
- const pool_entryt &entry = pool_entry (bootstrap_methodhandle_ref);
1603
-
1604
- method_handle_infot method_handle{entry};
1605
-
1606
- u2 num_bootstrap_arguments = read_u2 ();
1607
- debug () << " INFO: parse BootstrapMethod handle "
1608
- << num_bootstrap_arguments << " #args" << eom;
1609
-
1610
- // try parsing bootstrap method handle
1611
- if (num_bootstrap_arguments >= 3 )
1612
- {
1613
- // each entry contains a MethodHandle structure
1614
- // u2 tag
1615
- // u2 reference kind which must be in the range from 1 to 9
1616
- // u2 reference index into the constant pool
1617
- //
1618
- // reference kinds use the following
1619
- // 1 to 4 must point to a CONSTANT_Fieldref structure
1620
- // 5 or 8 must point to a CONSTANT_Methodref structure
1621
- // 6 or 7 must point to a CONSTANT_Methodref or
1622
- // CONSTANT_InterfaceMethodref structure, if the class file version
1623
- // number is 52.0 or above, to a CONSTANT_Methodref only in the case
1624
- // of less than 52.0
1625
- // 9 must point to a CONSTANT_InterfaceMethodref structure
1626
-
1627
- // the index must point to a CONSTANT_String
1628
- // CONSTANT_Class
1629
- // CONSTANT_Integer
1630
- // CONSTANT_Long
1631
- // CONSTANT_Float
1632
- // CONSTANT_Double
1633
- // CONSTANT_MethodHandle
1634
- // CONSTANT_MethodType
1635
-
1636
- // We read the three arguments here to see whether they correspond to
1637
- // our hypotheses for this being a lambda function entry.
1638
-
1639
- u2 argument_index1 = read_u2 ();
1640
- u2 argument_index2 = read_u2 ();
1641
- u2 argument_index3 = read_u2 ();
1642
-
1643
- // The additional arguments for the altmetafactory call are skipped,
1644
- // as they are currently not used. We verify though that they are of
1645
- // CONSTANT_Integer type, cases where this does not hold will be
1646
- // analyzed further.
1647
- bool recognized = true ;
1648
- for (size_t i = 3 ; i < num_bootstrap_arguments; i++)
1649
- {
1650
- u2 skipped_argument = read_u2 ();
1651
- recognized |= pool_entry (skipped_argument).tag == CONSTANT_Integer;
1652
- }
1653
- if (!recognized)
1654
- {
1655
- debug () << " format of BootstrapMethods entry not recognized" << eom;
1656
- return ;
1657
- }
1658
-
1659
- const pool_entryt &interface_type_argument =
1660
- pool_entry (argument_index1);
1661
- const pool_entryt &method_handle_argument =
1662
- pool_entry (argument_index2);
1663
- const pool_entryt &method_type_argument = pool_entry (argument_index3);
1664
-
1665
- if (
1666
- !(interface_type_argument.tag == CONSTANT_MethodType &&
1667
- method_handle_argument.tag == CONSTANT_MethodHandle &&
1668
- method_type_argument.tag == CONSTANT_MethodType))
1669
- return ;
1670
-
1671
- debug () << " INFO: parse lambda handle" << eom;
1672
- optionalt<lambda_method_handlet> lambda_method_handle =
1673
- parse_method_handle (method_handle_infot{method_handle_argument});
1674
-
1675
- if (
1676
- lambda_method_handle.has_value () &&
1677
- lambda_method_handle->handle_type !=
1678
- method_handle_typet::LAMBDA_METHOD_HANDLE)
1679
- {
1680
- error () << " ERROR: could not parse lambda function method handle"
1681
- << eom;
1682
- }
1683
- else
1684
- {
1685
- lambda_method_handle->interface_type =
1686
- pool_entry (interface_type_argument.ref1 ).s ;
1687
- lambda_method_handle->method_type =
1688
- pool_entry (method_type_argument.ref1 ).s ;
1689
- debug () << " lambda function reference "
1690
- << id2string (lambda_method_handle->lambda_method_name )
1691
- << " in class \" " << parsed_class.name << " \" "
1692
- << " \n interface type is "
1693
- << id2string (pool_entry (interface_type_argument.ref1 ).s )
1694
- << " \n method type is "
1695
- << id2string (pool_entry (method_type_argument.ref1 ).s )
1696
- << eom;
1697
- parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1698
- *lambda_method_handle;
1699
- }
1700
- }
1701
- else
1702
- {
1703
- // skip bytes to align for next entry
1704
- for (size_t i = 0 ; i < num_bootstrap_arguments; i++)
1705
- read_u2 ();
1706
- error () << " ERROR: num_bootstrap_arguments must be at least 3" << eom;
1707
- }
1708
- }
1599
+ read_bootstrapmethods_entry (parsed_class);
1709
1600
}
1710
1601
else
1711
1602
skip_bytes (attribute_length);
@@ -1879,3 +1770,119 @@ java_bytecode_parsert::parse_method_handle(const method_handle_infot &entry)
1879
1770
1880
1771
return {};
1881
1772
}
1773
+
1774
+ // / Read all entries of the `BootstrapMethods` attribute of a class file.
1775
+ // / \param parsed_class: the class representation of the class file that is
1776
+ // / currently parsed
1777
+ void java_bytecode_parsert::read_bootstrapmethods_entry (
1778
+ classt &parsed_class)
1779
+ {
1780
+ u2 num_bootstrap_methods = read_u2 ();
1781
+ for (size_t i = 0 ; i < num_bootstrap_methods; i++)
1782
+ {
1783
+ u2 bootstrap_methodhandle_ref = read_u2 ();
1784
+ const pool_entryt &entry = pool_entry (bootstrap_methodhandle_ref);
1785
+
1786
+ method_handle_infot method_handle{entry};
1787
+
1788
+ u2 num_bootstrap_arguments = read_u2 ();
1789
+ debug () << " INFO: parse BootstrapMethod handle "
1790
+ << num_bootstrap_arguments << " #args" << eom;
1791
+
1792
+ // try parsing bootstrap method handle
1793
+ if (num_bootstrap_arguments >= 3 )
1794
+ {
1795
+ // each entry contains a MethodHandle structure
1796
+ // u2 tag
1797
+ // u2 reference kind which must be in the range from 1 to 9
1798
+ // u2 reference index into the constant pool
1799
+ //
1800
+ // reference kinds use the following
1801
+ // 1 to 4 must point to a CONSTANT_Fieldref structure
1802
+ // 5 or 8 must point to a CONSTANT_Methodref structure
1803
+ // 6 or 7 must point to a CONSTANT_Methodref or
1804
+ // CONSTANT_InterfaceMethodref structure, if the class file version
1805
+ // number is 52.0 or above, to a CONSTANT_Methodref only in the case
1806
+ // of less than 52.0
1807
+ // 9 must point to a CONSTANT_InterfaceMethodref structure
1808
+
1809
+ // the index must point to a CONSTANT_String
1810
+ // CONSTANT_Class
1811
+ // CONSTANT_Integer
1812
+ // CONSTANT_Long
1813
+ // CONSTANT_Float
1814
+ // CONSTANT_Double
1815
+ // CONSTANT_MethodHandle
1816
+ // CONSTANT_MethodType
1817
+
1818
+ // We read the three arguments here to see whether they correspond to
1819
+ // our hypotheses for this being a lambda function entry.
1820
+
1821
+ u2 argument_index1 = read_u2 ();
1822
+ u2 argument_index2 = read_u2 ();
1823
+ u2 argument_index3 = read_u2 ();
1824
+
1825
+ // The additional arguments for the altmetafactory call are skipped,
1826
+ // as they are currently not used. We verify though that they are of
1827
+ // CONSTANT_Integer type, cases where this does not hold will be
1828
+ // analyzed further.
1829
+ bool recognized = true ;
1830
+ for (size_t i = 3 ; i < num_bootstrap_arguments; i++)
1831
+ {
1832
+ u2 skipped_argument = read_u2 ();
1833
+ recognized &= pool_entry (skipped_argument).tag == CONSTANT_Integer;
1834
+ }
1835
+ if (!recognized)
1836
+ {
1837
+ debug () << " format of BootstrapMethods entry not recognized" << eom;
1838
+ return ;
1839
+ }
1840
+
1841
+ const pool_entryt &interface_type_argument = pool_entry (argument_index1);
1842
+ const pool_entryt &method_handle_argument = pool_entry (argument_index2);
1843
+ const pool_entryt &method_type_argument = pool_entry (argument_index3);
1844
+
1845
+ if (
1846
+ !(interface_type_argument.tag == CONSTANT_MethodType &&
1847
+ method_handle_argument.tag == CONSTANT_MethodHandle &&
1848
+ method_type_argument.tag == CONSTANT_MethodType))
1849
+ return ;
1850
+
1851
+ debug () << " INFO: parse lambda handle" << eom;
1852
+ optionalt<lambda_method_handlet> lambda_method_handle =
1853
+ parse_method_handle (method_handle_infot{method_handle_argument});
1854
+
1855
+ if (
1856
+ lambda_method_handle.has_value () &&
1857
+ lambda_method_handle->handle_type !=
1858
+ method_handle_typet::LAMBDA_METHOD_HANDLE)
1859
+ {
1860
+ error () << " ERROR: could not parse lambda function method handle"
1861
+ << eom;
1862
+ }
1863
+ else
1864
+ {
1865
+ lambda_method_handle->interface_type =
1866
+ pool_entry (interface_type_argument.ref1 ).s ;
1867
+ lambda_method_handle->method_type =
1868
+ pool_entry (method_type_argument.ref1 ).s ;
1869
+ debug () << " lambda function reference "
1870
+ << id2string (lambda_method_handle->lambda_method_name )
1871
+ << " in class \" " << parsed_class.name << " \" "
1872
+ << " \n interface type is "
1873
+ << id2string (pool_entry (interface_type_argument.ref1 ).s )
1874
+ << " \n method type is "
1875
+ << id2string (pool_entry (method_type_argument.ref1 ).s ) << eom;
1876
+ parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1877
+ *lambda_method_handle;
1878
+ }
1879
+ }
1880
+ else
1881
+ {
1882
+ // skip bytes to align for next entry
1883
+ for (size_t i = 0 ; i < num_bootstrap_arguments; i++)
1884
+ read_u2 ();
1885
+ error () << " ERROR: num_bootstrap_arguments must be at least 3" << eom;
1886
+ }
1887
+ }
1888
+ }
0 commit comments