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