Skip to content

Commit 353c90c

Browse files
authored
Merge pull request #2753 from antlechner/antonia/jar-file-loading
Do not load whole jar file when --function is given
2 parents d85100d + 7d7424f commit 353c90c

File tree

8 files changed

+70
-7
lines changed

8 files changed

+70
-7
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class IrrelevantClass {
2+
3+
public static void notImportant() {
4+
assert true;
5+
}
6+
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public class RelatedClass {
2+
3+
public int i;
4+
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class RelevantClass {
2+
3+
public static void entry(RelatedClass rc) {
4+
assert false;
5+
}
6+
7+
}
Binary file not shown.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
jar_file.jar
3+
--function RelevantClass.entry --verbosity 10
4+
^EXIT=10
5+
^SIGNAL=0
6+
VERIFICATION FAILED
7+
Getting class `RelevantClass' from JAR jar_file.jar
8+
Getting class `RelatedClass' from JAR jar_file.jar
9+
--
10+
Getting class `IrrelevantClass' from JAR jar_file.jar
11+
--
12+
This test checks that when JBMC is given a jar file as an argument and an entry
13+
method is specified with --function, only classes that are (possibly
14+
transitively) referenced from the class containing the entry method are loaded
15+
by java_class_loadert.

jbmc/src/janalyzer/janalyzer_parse_options.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,12 @@ void janalyzer_parse_optionst::help()
733733
"Usage: Purpose:\n"
734734
"\n"
735735
" janalyzer [-?] [-h] [--help] show help\n"
736-
" janalyzer class name of class to be checked\n"
736+
" janalyzer class name of class or JAR file to be checked\n"
737+
" In the case of a JAR file, if a main class can be\n" // NOLINT(*)
738+
" inferred from --main-class, --function, or the JAR\n" // NOLINT(*)
739+
" manifest (checked in this order), the behavior is\n" // NOLINT(*)
740+
" the same as running janalyzer on the corresponding\n" // NOLINT(*)
741+
" class file."
737742
"\n"
738743
"Task options:\n"
739744
" --show display the abstract domains\n"

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,15 @@ bool java_bytecode_languaget::preprocess(
168168
return true;
169169
}
170170

171+
/// We set the main class (i.e.\ class to start the class loading analysis from,
172+
/// see \ref java_class_loadert) depending on the file type of `path`.
173+
/// `path` can be the name of either a .class file or a .jar file.
174+
/// If it is a .class file, the top-level class in this file is the main class.
175+
/// If it is a .jar file, we first check for the main class in three steps
176+
/// 1) the argument of the --main-class command-line option,
177+
/// 2) the class implied by the argument of the --function option,
178+
/// 3) the manifest file of the JAR.
179+
/// If no main class was found, all classes in the JAR file are loaded.
171180
bool java_bytecode_languaget::parse(
172181
std::istream &,
173182
const std::string &path)
@@ -207,12 +216,22 @@ bool java_bytecode_languaget::parse(
207216
java_cp_include_files);
208217
if(config.java.main_class.empty())
209218
{
210-
auto manifest = java_class_loader.jar_pool(path).get_manifest();
211-
std::string manifest_main_class=manifest["Main-Class"];
219+
const std::string &entry_method = config.main;
220+
// If we have an entry method, we can derive a main class.
221+
if(!entry_method.empty())
222+
{
223+
const auto last_dot_position = entry_method.find_last_of('.');
224+
main_class = entry_method.substr(0, last_dot_position);
225+
}
226+
else
227+
{
228+
auto manifest = java_class_loader.jar_pool(path).get_manifest();
229+
std::string manifest_main_class = manifest["Main-Class"];
212230

213-
// if the manifest declares a Main-Class line, we got a main class
214-
if(manifest_main_class!="")
215-
main_class=manifest_main_class;
231+
// if the manifest declares a Main-Class line, we got a main class
232+
if(!manifest_main_class.empty())
233+
main_class = manifest_main_class;
234+
}
216235
}
217236
else
218237
main_class=config.java.main_class;

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,12 @@ void jbmc_parse_optionst::help()
10181018
"Usage: Purpose:\n"
10191019
"\n"
10201020
" jbmc [-?] [-h] [--help] show help\n"
1021-
" jbmc class name of class to be checked\n"
1021+
" jbmc class name of class or JAR file to be checked\n"
1022+
" In the case of a JAR file, if a main class can be\n" // NOLINT(*)
1023+
" inferred from --main-class, --function, or the JAR\n" // NOLINT(*)
1024+
" manifest (checked in this order), the behavior is\n" // NOLINT(*)
1025+
" the same as running jbmc on the corresponding\n" // NOLINT(*)
1026+
" class file."
10221027
"\n"
10231028
"Analysis options:\n"
10241029
HELP_SHOW_PROPERTIES

0 commit comments

Comments
 (0)