Skip to content

Commit b61cb56

Browse files
author
svorenova
committed
Resolving signature/descriptor mismatch for methods
We want to use signature whenever possible. In certain cases, the number of input parameters in the descriptor is higher than in the signature. For example for enums and inner classes, in these cases descriptor has the correct form (although without generics information).
1 parent 62675bb commit b61cb56

File tree

3 files changed

+77
-4
lines changed

3 files changed

+77
-4
lines changed

src/java_bytecode/java_bytecode_convert_class.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ void java_bytecode_convert_classt::convert(const classt &c)
203203
*class_symbol,
204204
method_identifier,
205205
method,
206-
symbol_table);
206+
symbol_table,
207+
get_message_handler());
207208
lazy_methods[method_identifier]=std::make_pair(class_symbol, &method);
208209
}
209210

src/java_bytecode/java_bytecode_convert_method.cpp

+73-2
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,69 @@ const exprt java_bytecode_convert_methodt::variable(
248248
}
249249
}
250250

251+
/// Returns the member type for a method, based on signature or descriptor
252+
/// \param descriptor
253+
/// descriptor of the method
254+
/// \param signature
255+
/// signature of the method
256+
/// \param class_name
257+
/// string containing the name of the corresponding class
258+
/// \param method_name
259+
/// string containing the name of the method
260+
/// \param message_handler
261+
/// message handler to collect warnings
262+
/// \return
263+
/// the constructed member type
264+
typet member_type_lazy(const std::string &descriptor,
265+
const optionalt<std::string> &signature,
266+
const std::string &class_name,
267+
const std::string &method_name,
268+
message_handlert &message_handler)
269+
{
270+
// In order to construct the method type, we can either use signature or
271+
// descriptor. Since only signature contains the generics info, we want to
272+
// use signature whenever possible. We revert to using descriptor if (1) the
273+
// signature does not exist, (2) an unsupported generics are present or
274+
// (3) in the special case when the number of parameters in the descriptor
275+
// does not match the number of parameters in the signature - e.g. for
276+
// certain types of inner classes and enums (see unit tests for examples).
277+
278+
messaget message(message_handler);
279+
280+
typet member_type_from_descriptor=java_type_from_string(descriptor);
281+
INVARIANT(member_type_from_descriptor.id()==ID_code, "Must be code type");
282+
if(signature.has_value())
283+
{
284+
try
285+
{
286+
typet member_type_from_signature=java_type_from_string(
287+
signature.value(),
288+
class_name);
289+
INVARIANT(member_type_from_signature.id()==ID_code, "Must be code type");
290+
if(to_code_type(member_type_from_signature).parameters().size()==
291+
to_code_type(member_type_from_descriptor).parameters().size())
292+
{
293+
return member_type_from_signature;
294+
}
295+
else
296+
{
297+
message.warning() << "method: " << class_name << "." << method_name
298+
<< "\n signature: " << signature.value() << "\n descriptor: "
299+
<< descriptor << "\n different number of parameters, reverting to "
300+
"descriptor" << message.eom;
301+
}
302+
}
303+
catch(unsupported_java_class_signature_exceptiont &e)
304+
{
305+
message.warning() << "method: " << class_name << "." << method_name
306+
<< "\n could not parse signature: " << signature.value() << "\n "
307+
<< e.what() << "\n" << " reverting to descriptor: "
308+
<< descriptor << message.eom;
309+
}
310+
}
311+
return member_type_from_descriptor;
312+
}
313+
251314
/// This creates a method symbol in the symtab, but doesn't actually perform
252315
/// method conversion just yet. The caller should call
253316
/// java_bytecode_convert_method later to give the symbol/method a body.
@@ -256,14 +319,22 @@ const exprt java_bytecode_convert_methodt::variable(
256319
/// (e.g. "x.y.z.f:(I)")
257320
/// `m`: parsed method object to convert
258321
/// `symbol_table`: global symbol table (will be modified)
322+
/// `message_handler`: message handler to collect warnings
259323
void java_bytecode_convert_method_lazy(
260324
const symbolt &class_symbol,
261325
const irep_idt &method_identifier,
262326
const java_bytecode_parse_treet::methodt &m,
263-
symbol_tablet &symbol_table)
327+
symbol_tablet &symbol_table,
328+
message_handlert &message_handler)
264329
{
265330
symbolt method_symbol;
266-
typet member_type=java_type_from_string(m.descriptor);
331+
332+
typet member_type=member_type_lazy(
333+
m.descriptor,
334+
m.signature,
335+
id2string(class_symbol.name),
336+
id2string(m.base_name),
337+
message_handler);
267338

268339
method_symbol.name=method_identifier;
269340
method_symbol.base_name=m.base_name;

src/java_bytecode/java_bytecode_convert_method.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ void java_bytecode_convert_method_lazy(
5353
const symbolt &class_symbol,
5454
const irep_idt &method_identifier,
5555
const java_bytecode_parse_treet::methodt &,
56-
symbol_tablet &symbol_table);
56+
symbol_tablet &symbol_table,
57+
message_handlert &);
5758

5859
#endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_METHOD_H

0 commit comments

Comments
 (0)