Skip to content

Commit 6afa932

Browse files
committed
Java bytecode front-end: fix main method detection
When parsing Java classes with just a class name (without method signature), JBMC was incorrectly using `resolve_friendly_method_name` which could report 'main method is ambiguous' errors. This fix checks if `config.main` contains a method signature (has a colon) and handles simple class names separately by looking for the standard main method signature directly. This aligns the Java front-end with Java's specification, where only `public static void main(String[] args)` is recognized as a valid program entry point. Fixes: #759
1 parent 4fe3ade commit 6afa932

File tree

4 files changed

+69
-12
lines changed

4 files changed

+69
-12
lines changed
616 Bytes
Binary file not shown.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Test case for GitHub issue #759
2+
// CBMC should not produce CONVERSION ERROR when there are multiple
3+
// methods named 'main' with different signatures.
4+
// Only the method with signature void main(String[]) is a valid entry point.
5+
6+
public class Test {
7+
8+
// Invalid main method - no parameters
9+
public static void main() {
10+
}
11+
12+
// Valid main method - String[] parameter
13+
public static void main(String[] args) {
14+
assert false; // This should be the entry point
15+
}
16+
17+
// Invalid main method - single String parameter
18+
public static void main(String arg) {
19+
}
20+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
4+
^EXIT=(0|10)$
5+
^SIGNAL=0$
6+
--
7+
^CONVERSION ERROR
8+
^warning: ignoring

jbmc/src/java_bytecode/java_entry_point.cpp

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -555,23 +555,52 @@ main_function_resultt get_main_symbol(
555555
// find main symbol
556556
if(config.main.has_value())
557557
{
558-
std::string error_message;
559-
irep_idt main_symbol_id = resolve_friendly_method_name(
560-
config.main.value(), symbol_table, error_message);
558+
std::string config_main = config.main.value();
561559

562-
if(main_symbol_id.empty())
560+
// Check if config.main contains a method signature (has a colon)
561+
// If it's just a class name, treat it the same as the main_class parameter
562+
if(config_main.find(':') == std::string::npos)
563563
{
564-
message.error()
565-
<< "main symbol resolution failed: " << error_message << messaget::eom;
566-
return main_function_resultt::Error;
564+
// config.main is just a class name, remove .class suffix if present
565+
if(has_suffix(config_main, ".class"))
566+
config_main = config_main.substr(0, config_main.length() - 6);
567+
568+
// Look for the standard main method
569+
std::string entry_method =
570+
"java::" + config_main + "." + JAVA_MAIN_METHOD;
571+
const symbolt *symbol = symbol_table.lookup(entry_method);
572+
573+
// has the class a correct main method?
574+
if(!symbol || !is_java_main(*symbol))
575+
{
576+
// no, but we allow this situation to output symbol table,
577+
// goto functions, etc
578+
return main_function_resultt::NotFound;
579+
}
580+
581+
return *symbol;
567582
}
583+
else
584+
{
585+
// config.main contains a full method specification, use friendly name resolution
586+
std::string error_message;
587+
irep_idt main_symbol_id =
588+
resolve_friendly_method_name(config_main, symbol_table, error_message);
568589

569-
const symbolt *symbol = symbol_table.lookup(main_symbol_id);
570-
INVARIANT(
571-
symbol != nullptr,
572-
"resolve_friendly_method_name should return a symbol-table identifier");
590+
if(main_symbol_id.empty())
591+
{
592+
message.error() << "main symbol resolution failed: " << error_message
593+
<< messaget::eom;
594+
return main_function_resultt::Error;
595+
}
573596

574-
return *symbol; // Return found function
597+
const symbolt *symbol = symbol_table.lookup(main_symbol_id);
598+
INVARIANT(
599+
symbol != nullptr,
600+
"resolve_friendly_method_name should return a symbol-table identifier");
601+
602+
return *symbol; // Return found function
603+
}
575604
}
576605
else
577606
{

0 commit comments

Comments
 (0)