@@ -53,7 +53,7 @@ class java_bytecode_parsert:public parsert
53
53
method_handle_typet;
54
54
typedef java_bytecode_parse_treet::classt::lambda_method_handlest
55
55
lambda_method_handlest;
56
- typedef java_bytecode_parse_treet::classt::lambda_method_handlest
56
+ typedef java_bytecode_parse_treet::classt::lambda_method_handle_mapt
57
57
lambda_method_handle_mapt;
58
58
59
59
java_bytecode_parse_treet parse_tree;
@@ -134,7 +134,7 @@ class java_bytecode_parsert:public parsert
134
134
void get_class_refs ();
135
135
void get_class_refs_rec (const typet &);
136
136
void parse_local_variable_type_table (methodt &method);
137
- void parse_methodhandle (const pool_entryt &, lambda_method_handlet &);
137
+ void parse_method_handle (const pool_entryt &, lambda_method_handlet &);
138
138
139
139
void skip_bytes (std::size_t bytes)
140
140
{
@@ -1418,11 +1418,11 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1418
1418
else if (attribute_name == " BootstrapMethods" )
1419
1419
{
1420
1420
INVARIANT (
1421
- !parsed_class.read_attribute_bootstrapmethods ,
1421
+ !parsed_class.attribute_bootstrapmethods_read ,
1422
1422
" only one BootstrapMethods argument is allowed in a class file" );
1423
1423
1424
1424
// mark as read in parsed class
1425
- parsed_class.read_attribute_bootstrapmethods = true ;
1425
+ parsed_class.attribute_bootstrapmethods_read = true ;
1426
1426
u2 num_bootstrap_methods = read_u2 ();
1427
1427
for (size_t i = 0 ; i < num_bootstrap_methods; i++)
1428
1428
{
@@ -1434,7 +1434,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1434
1434
debug () << " INFO: parse BootstrapMethod handle "
1435
1435
<< num_bootstrap_arguments << " #args"
1436
1436
<< eom;
1437
- parse_methodhandle (entry, handle);
1437
+ parse_method_handle (entry, handle);
1438
1438
if (
1439
1439
handle.handle_type ==
1440
1440
method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT ||
@@ -1465,29 +1465,47 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1465
1465
// CONSTANT_Double
1466
1466
// CONSTANT_MethodHandle
1467
1467
// CONSTANT_MethodType
1468
- u2 arg_index1 = read_u2 ();
1469
- u2 arg_index2 = read_u2 ();
1470
- u2 arg_index3 = read_u2 ();
1471
1468
1472
- // skip rest
1469
+ // We read the three arguments here to see whether they correspond to
1470
+ // our hypotheses for this being a lambda function entry.
1471
+
1472
+ u2 argument_index1 = read_u2 ();
1473
+ u2 argument_index2 = read_u2 ();
1474
+ u2 argument_index3 = read_u2 ();
1475
+
1476
+ // The additional arguments for the altmetafactory call are skipped,
1477
+ // as they are currently not used. We verify though that they are of
1478
+ // CONSTANT_Integer type, cases where this does not hold will be
1479
+ // analyzed further.
1480
+ bool recognized = true ;
1473
1481
for (size_t i = 3 ; i < num_bootstrap_arguments; i++)
1474
- read_u2 ();
1482
+ {
1483
+ u2 skipped_argument = read_u2 ();
1484
+ recognized |= pool_entry (skipped_argument).tag == CONSTANT_Integer;
1485
+ }
1486
+ if (!recognized)
1487
+ {
1488
+ debug () << " format of BootstrapMethods entry not recognized"
1489
+ << eom;
1490
+ return ;
1491
+ }
1475
1492
1476
- const pool_entryt &arg1 = pool_entry (arg_index1);
1477
- const pool_entryt &arg2 = pool_entry (arg_index2);
1478
- const pool_entryt &arg3 = pool_entry (arg_index3);
1493
+ const pool_entryt &interface_type_argument =
1494
+ pool_entry (argument_index1);
1495
+ const pool_entryt &method_handle_argument =
1496
+ pool_entry (argument_index2);
1497
+ const pool_entryt &method_type_argument = pool_entry (argument_index3);
1479
1498
1480
- if (!(arg1 .tag == CONSTANT_MethodType &&
1481
- arg2 .tag == CONSTANT_MethodHandle &&
1482
- arg3 .tag == CONSTANT_MethodType))
1499
+ if (!(interface_type_argument .tag == CONSTANT_MethodType &&
1500
+ method_handle_argument .tag == CONSTANT_MethodHandle &&
1501
+ method_type_argument .tag == CONSTANT_MethodType))
1483
1502
return ;
1484
1503
1485
- lambda_method_handlet real_handle ;
1504
+ lambda_method_handlet lambda_method_handle ;
1486
1505
debug () << " INFO: parse lambda handle" << eom;
1487
- const pool_entryt &lambda_entry = pool_entry (arg_index2);
1488
- parse_methodhandle (lambda_entry, real_handle);
1506
+ parse_method_handle (method_handle_argument, lambda_method_handle);
1489
1507
if (
1490
- real_handle .handle_type !=
1508
+ lambda_method_handle .handle_type !=
1491
1509
method_handle_typet::LAMBDA_METHOD_HANDLE)
1492
1510
{
1493
1511
lambda_method_handlet empty_handle;
@@ -1498,37 +1516,37 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
1498
1516
}
1499
1517
else
1500
1518
{
1501
- real_handle .interface_type = pool_entry (arg1 .ref1 ).s ;
1502
- real_handle .method_type = pool_entry (arg3 .ref1 ).s ;
1519
+ lambda_method_handle .interface_type = pool_entry (interface_type_argument .ref1 ).s ;
1520
+ lambda_method_handle .method_type = pool_entry (method_type_argument .ref1 ).s ;
1503
1521
parsed_class.lambda_method_handle_map [parsed_class.name ].push_back (
1504
- real_handle );
1522
+ lambda_method_handle );
1505
1523
debug ()
1506
1524
<< " lambda function reference "
1507
- << id2string (real_handle .lambda_method_name ) << " in class \" "
1525
+ << id2string (lambda_method_handle .lambda_method_name ) << " in class \" "
1508
1526
<< parsed_class.name << " \" "
1509
1527
<< " \n interface type is "
1510
- << id2string (pool_entry (arg1 .ref1 ).s )
1528
+ << id2string (pool_entry (interface_type_argument .ref1 ).s )
1511
1529
<< " \n method type is "
1512
- << id2string (pool_entry (arg3 .ref1 ).s )
1530
+ << id2string (pool_entry (method_type_argument .ref1 ).s )
1513
1531
<< eom;
1514
1532
}
1515
1533
}
1516
1534
else
1517
1535
{
1518
- // skip arguments here
1536
+ // skip bytes to align for next entry
1519
1537
for (size_t i = 0 ; i < num_bootstrap_arguments; i++)
1520
1538
read_u2 ();
1521
- error () << " ERROR: num_bootstrap_arguments must be 3" << eom;
1539
+ error () << " ERROR: num_bootstrap_arguments must be at least 3" << eom;
1522
1540
}
1523
1541
}
1524
1542
else
1525
1543
{
1526
1544
lambda_method_handlet empty_handle;
1527
1545
parsed_class.lambda_method_handle_map [parsed_class.name ].push_back (
1528
1546
empty_handle);
1529
- // skip arguments here
1547
+ // skip bytes to align for next entry
1530
1548
for (size_t i = 0 ; i < num_bootstrap_arguments; i++)
1531
- read_u2 ();
1549
+ read_u2 ();
1532
1550
error () << " ERROR: could not parse BootstrapMethods entry" << eom;
1533
1551
}
1534
1552
}
@@ -1665,9 +1683,9 @@ void java_bytecode_parsert::parse_local_variable_type_table(methodt &method)
1665
1683
// / Read method handle pointed to from constant pool entry at index, return type
1666
1684
// / of method handle and name if lambda function is found.
1667
1685
// / \param entry: the constant pool entry of the methodhandle_info structure
1668
- // / \param[out]: the method_handle type of the methodhandle_structure, either
1669
- // / for a recognized bootstrap method, for a lambda function or unknown
1670
- void java_bytecode_parsert::parse_methodhandle (
1686
+ // / \param[out] handle : the method_handle type of the methodhandle_structure,
1687
+ // / either for a recognized bootstrap method, for a lambda function or unknown
1688
+ void java_bytecode_parsert::parse_method_handle (
1671
1689
const pool_entryt &entry,
1672
1690
lambda_method_handlet &handle)
1673
1691
{
@@ -1694,17 +1712,15 @@ void java_bytecode_parsert::parse_methodhandle(
1694
1712
" lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/"
1695
1713
" MethodType;)Ljava/lang/invoke/CallSite;" )
1696
1714
handle.handle_type = method_handle_typet::BOOTSTRAP_METHOD_HANDLE;
1697
-
1698
1715
// names seem to be lambda$$POSTFIX$NUM
1699
1716
// where $POSTFIX is $FUN for a function name in which the lambda is define
1700
1717
// "static" when it is a static member of the class
1701
1718
// "new" when it is a class variable, instantiated in <init>
1702
- if (has_prefix (id2string (pool_entry (nameandtype_entry.ref1 ).s ), " lambda$" ))
1719
+ else if (has_prefix (id2string (pool_entry (nameandtype_entry.ref1 ).s ), " lambda$" ))
1703
1720
{
1704
1721
handle.lambda_method_name = pool_entry (nameandtype_entry.ref1 ).s ;
1705
1722
handle.handle_type = method_handle_typet::LAMBDA_METHOD_HANDLE;
1706
1723
}
1707
-
1708
1724
else if (
1709
1725
method_name ==
1710
1726
" java/lang/invoke/LambdaMetafactory.altMetafactory(Ljava/lang/invoke/"
0 commit comments