@@ -52,8 +52,6 @@ class java_bytecode_parsert:public parsert
52
52
method_handle_typet;
53
53
typedef java_bytecode_parse_treet::classt::lambda_method_handlet
54
54
lambda_method_handlet;
55
- typedef java_bytecode_parse_treet::classt::lambda_method_handle_mapt
56
- lambda_method_handle_mapt;
57
55
typedef java_bytecode_parse_treet::classt::u2_valuest u2_valuest;
58
56
59
57
java_bytecode_parse_treet parse_tree;
@@ -186,6 +184,11 @@ class java_bytecode_parsert:public parsert
186
184
{
187
185
return read_bytes (8 );
188
186
}
187
+
188
+ void store_unknown_method_handle (
189
+ classt &parsed_class,
190
+ size_t bootstrap_method_index,
191
+ u2_valuest u2_values) const ;
189
192
};
190
193
191
194
#define CONSTANT_Class 7
@@ -1803,7 +1806,9 @@ java_bytecode_parsert::parse_method_handle(const method_handle_infot &entry)
1803
1806
void java_bytecode_parsert::read_bootstrapmethods_entry (classt &parsed_class)
1804
1807
{
1805
1808
u2 num_bootstrap_methods = read_u2 ();
1806
- for (size_t i = 0 ; i < num_bootstrap_methods; i++)
1809
+ for (size_t bootstrap_method_index = 0 ;
1810
+ bootstrap_method_index < num_bootstrap_methods;
1811
+ ++bootstrap_method_index)
1807
1812
{
1808
1813
u2 bootstrap_methodhandle_ref = read_u2 ();
1809
1814
const pool_entryt &entry = pool_entry (bootstrap_methodhandle_ref);
@@ -1820,122 +1825,133 @@ void java_bytecode_parsert::read_bootstrapmethods_entry(classt &parsed_class)
1820
1825
u2_values[i] = read_u2 ();
1821
1826
1822
1827
// try parsing bootstrap method handle
1823
- if (num_bootstrap_arguments >= 3 )
1828
+ // each entry contains a MethodHandle structure
1829
+ // u2 tag
1830
+ // u2 reference kind which must be in the range from 1 to 9
1831
+ // u2 reference index into the constant pool
1832
+ //
1833
+ // reference kinds use the following
1834
+ // 1 to 4 must point to a CONSTANT_Fieldref structure
1835
+ // 5 or 8 must point to a CONSTANT_Methodref structure
1836
+ // 6 or 7 must point to a CONSTANT_Methodref or
1837
+ // CONSTANT_InterfaceMethodref structure, if the class file version
1838
+ // number is 52.0 or above, to a CONSTANT_Methodref only in the case
1839
+ // of less than 52.0
1840
+ // 9 must point to a CONSTANT_InterfaceMethodref structure
1841
+
1842
+ // the index must point to a CONSTANT_String
1843
+ // CONSTANT_Class
1844
+ // CONSTANT_Integer
1845
+ // CONSTANT_Long
1846
+ // CONSTANT_Float
1847
+ // CONSTANT_Double
1848
+ // CONSTANT_MethodHandle
1849
+ // CONSTANT_MethodType
1850
+
1851
+ // We read the three arguments here to see whether they correspond to
1852
+ // our hypotheses for this being a lambda function entry.
1853
+
1854
+ // Need at least 3 arguments, the interface type, the method hanlde
1855
+ // and the method_type, otherwise it doesn't look like a call that we
1856
+ // understand
1857
+ if (num_bootstrap_arguments < 3 )
1824
1858
{
1825
- // each entry contains a MethodHandle structure
1826
- // u2 tag
1827
- // u2 reference kind which must be in the range from 1 to 9
1828
- // u2 reference index into the constant pool
1829
- //
1830
- // reference kinds use the following
1831
- // 1 to 4 must point to a CONSTANT_Fieldref structure
1832
- // 5 or 8 must point to a CONSTANT_Methodref structure
1833
- // 6 or 7 must point to a CONSTANT_Methodref or
1834
- // CONSTANT_InterfaceMethodref structure, if the class file version
1835
- // number is 52.0 or above, to a CONSTANT_Methodref only in the case
1836
- // of less than 52.0
1837
- // 9 must point to a CONSTANT_InterfaceMethodref structure
1838
-
1839
- // the index must point to a CONSTANT_String
1840
- // CONSTANT_Class
1841
- // CONSTANT_Integer
1842
- // CONSTANT_Long
1843
- // CONSTANT_Float
1844
- // CONSTANT_Double
1845
- // CONSTANT_MethodHandle
1846
- // CONSTANT_MethodType
1847
-
1848
- // We read the three arguments here to see whether they correspond to
1849
- // our hypotheses for this being a lambda function entry.
1850
-
1851
- u2 argument_index1 = u2_values[0 ];
1852
- u2 argument_index2 = u2_values[1 ];
1853
- u2 argument_index3 = u2_values[2 ];
1854
-
1855
- // The additional arguments for the altmetafactory call are skipped,
1856
- // as they are currently not used. We verify though that they are of
1857
- // CONSTANT_Integer type, cases where this does not hold will be
1858
- // analyzed further.
1859
- bool recognized = true ;
1860
- for (size_t i = 3 ; i < num_bootstrap_arguments; i++)
1861
- {
1862
- u2 skipped_argument = u2_values[i];
1863
- recognized &= pool_entry (skipped_argument).tag == CONSTANT_Integer;
1864
- }
1865
- if (!recognized)
1866
- {
1867
- debug () << " format of BootstrapMethods entry not recognized" << eom;
1868
- lambda_method_handlet lambda_method_handle;
1869
- lambda_method_handle.handle_type = method_handle_typet::UNKNOWN_HANDLE;
1870
- lambda_method_handle.u2_values = std::move (u2_values);
1871
- parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1872
- lambda_method_handle;
1873
- return ;
1874
- }
1875
- const pool_entryt &interface_type_argument = pool_entry (argument_index1);
1876
- const pool_entryt &method_handle_argument = pool_entry (argument_index2);
1877
- const pool_entryt &method_type_argument = pool_entry (argument_index3);
1878
-
1879
- if (
1880
- !(interface_type_argument.tag == CONSTANT_MethodType &&
1881
- method_handle_argument.tag == CONSTANT_MethodHandle &&
1882
- method_type_argument.tag == CONSTANT_MethodType))
1883
- {
1884
- lambda_method_handlet lambda_method_handle;
1885
- lambda_method_handle.handle_type = method_handle_typet::UNKNOWN_HANDLE;
1886
- lambda_method_handle.u2_values = std::move (u2_values);
1887
- parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1888
- lambda_method_handle;
1889
- return ;
1890
- }
1859
+ store_unknown_method_handle (
1860
+ parsed_class, bootstrap_method_index, std::move (u2_values));
1861
+ debug ()
1862
+ << " format of BootstrapMethods entry not recognized: too few arguments"
1863
+ << eom;
1864
+ continue ;
1865
+ }
1891
1866
1892
- debug () << " INFO: parse lambda handle " << eom ;
1893
- optionalt<lambda_method_handlet> lambda_method_handle =
1894
- parse_method_handle (method_handle_infot{method_handle_argument}) ;
1867
+ u2 interface_type_index = u2_values[ 0 ] ;
1868
+ u2 method_handle_index = u2_values[ 1 ];
1869
+ u2 method_type_index = u2_values[ 2 ] ;
1895
1870
1896
- if (!lambda_method_handle.has_value ())
1897
- {
1898
- lambda_method_handlet lambda_method_handle;
1899
- lambda_method_handle.handle_type = method_handle_typet::UNKNOWN_HANDLE;
1900
- lambda_method_handle.u2_values = std::move (u2_values);
1901
- parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1902
- lambda_method_handle;
1903
- return ;
1904
- }
1905
- else if (
1906
- lambda_method_handle->handle_type !=
1907
- method_handle_typet::LAMBDA_METHOD_HANDLE)
1908
- {
1909
- lambda_method_handle->u2_values = std::move (u2_values);
1910
- error () << " ERROR: could not parse lambda function method handle"
1911
- << eom;
1912
- }
1913
- else
1914
- {
1915
- lambda_method_handle->interface_type =
1916
- pool_entry (interface_type_argument.ref1 ).s ;
1917
- lambda_method_handle->method_type =
1918
- pool_entry (method_type_argument.ref1 ).s ;
1919
- lambda_method_handle->u2_values = std::move (u2_values);
1920
- debug () << " lambda function reference "
1921
- << id2string (lambda_method_handle->lambda_method_name )
1922
- << " in class \" " << parsed_class.name << " \" "
1923
- << " \n interface type is "
1924
- << id2string (pool_entry (interface_type_argument.ref1 ).s )
1925
- << " \n method type is "
1926
- << id2string (pool_entry (method_type_argument.ref1 ).s ) << eom;
1927
- }
1928
- parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1929
- *lambda_method_handle;
1871
+ // The additional arguments for the altmetafactory call are skipped,
1872
+ // as they are currently not used. We verify though that they are of
1873
+ // CONSTANT_Integer type, cases where this does not hold will be
1874
+ // analyzed further.
1875
+ bool recognized = true ;
1876
+ for (size_t i = 3 ; i < num_bootstrap_arguments; i++)
1877
+ {
1878
+ u2 skipped_argument = u2_values[i];
1879
+ recognized &= pool_entry (skipped_argument).tag == CONSTANT_Integer;
1930
1880
}
1931
- else
1881
+
1882
+ if (!recognized)
1932
1883
{
1933
- lambda_method_handlet lambda_method_handle;
1934
- lambda_method_handle.handle_type = method_handle_typet::UNKNOWN_HANDLE;
1935
- lambda_method_handle.u2_values = std::move (u2_values);
1936
- parsed_class.lambda_method_handle_map [{parsed_class.name , i}] =
1937
- lambda_method_handle;
1938
- error () << " ERROR: num_bootstrap_arguments must be at least 3" << eom;
1884
+ debug () << " format of BootstrapMethods entry not recognized: extra "
1885
+ " arguments of wrong type"
1886
+ << eom;
1887
+ store_unknown_method_handle (
1888
+ parsed_class, bootstrap_method_index, std::move (u2_values));
1889
+ continue ;
1890
+ }
1891
+
1892
+ const pool_entryt &interface_type_argument =
1893
+ pool_entry (interface_type_index);
1894
+ const pool_entryt &method_handle_argument = pool_entry (method_handle_index);
1895
+ const pool_entryt &method_type_argument = pool_entry (method_type_index);
1896
+
1897
+ if (
1898
+ interface_type_argument.tag != CONSTANT_MethodType ||
1899
+ method_handle_argument.tag != CONSTANT_MethodHandle ||
1900
+ method_type_argument.tag != CONSTANT_MethodType)
1901
+ {
1902
+ debug () << " format of BootstrapMethods entry not recognized: arguments "
1903
+ " wrong type"
1904
+ << eom;
1905
+ store_unknown_method_handle (
1906
+ parsed_class, bootstrap_method_index, std::move (u2_values));
1907
+ continue ;
1908
+ }
1909
+
1910
+ debug () << " INFO: parse lambda handle" << eom;
1911
+ optionalt<lambda_method_handlet> lambda_method_handle =
1912
+ parse_method_handle (method_handle_infot{method_handle_argument});
1913
+
1914
+ if (!lambda_method_handle.has_value ())
1915
+ {
1916
+ debug () << " format of BootstrapMethods entry not recognized: method "
1917
+ " handle not recognised"
1918
+ << eom;
1919
+ store_unknown_method_handle (
1920
+ parsed_class, bootstrap_method_index, std::move (u2_values));
1921
+ continue ;
1939
1922
}
1923
+
1924
+ // If parse_method_handle can't parse the lambda method, it should return {}
1925
+ POSTCONDITION (
1926
+ lambda_method_handle->handle_type != method_handle_typet::UNKNOWN_HANDLE);
1927
+
1928
+ lambda_method_handle->interface_type =
1929
+ pool_entry (interface_type_argument.ref1 ).s ;
1930
+ lambda_method_handle->method_type = pool_entry (method_type_argument.ref1 ).s ;
1931
+ lambda_method_handle->u2_values = std::move (u2_values);
1932
+ debug () << " lambda function reference "
1933
+ << id2string (lambda_method_handle->lambda_method_name )
1934
+ << " in class \" " << parsed_class.name << " \" "
1935
+ << " \n interface type is "
1936
+ << id2string (pool_entry (interface_type_argument.ref1 ).s )
1937
+ << " \n method type is "
1938
+ << id2string (pool_entry (method_type_argument.ref1 ).s ) << eom;
1939
+ parsed_class.add_method_handle (
1940
+ bootstrap_method_index, *lambda_method_handle);
1940
1941
}
1941
1942
}
1943
+
1944
+ // / Creates an unknown method handle and puts it into the parsed_class
1945
+ // / \param parsed_class: The class whose bootstrap method handles we are using
1946
+ // / \param bootstrap_method_index: The current index in the bootstrap entry
1947
+ // / table
1948
+ // / \param u2_values: The indices of the arguments for the call
1949
+ void java_bytecode_parsert::store_unknown_method_handle (
1950
+ java_bytecode_parsert::classt &parsed_class,
1951
+ size_t bootstrap_method_index,
1952
+ java_bytecode_parsert::u2_valuest u2_values) const
1953
+ {
1954
+ const lambda_method_handlet lambda_method_handle =
1955
+ lambda_method_handlet::create_unknown_handle (move (u2_values));
1956
+ parsed_class.add_method_handle (bootstrap_method_index, lambda_method_handle);
1957
+ }
0 commit comments