Skip to content

Commit 36c2e2d

Browse files
author
Daniel Kroening
authored
Merge pull request #604 from mgudemann/limit_class_loading
Limit class loading
2 parents 272bce3 + 53fad70 commit 36c2e2d

19 files changed

+161
-54
lines changed

regression/cbmc-java/jar-file4/A.jar

721 Bytes
Binary file not shown.

regression/cbmc-java/jar-file4/B.jar

721 Bytes
Binary file not shown.

regression/cbmc-java/jar-file4/C.jar

934 Bytes
Binary file not shown.
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"jar":
3+
[
4+
"A.jar",
5+
"B.jar"
6+
],
7+
"classFiles":
8+
[
9+
"jarfile3$A.class",
10+
"jarfile3.class"
11+
]
12+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
C.jar
3+
--function jarfile3.f --java-cp-include-files "@jar.json"
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
.*SUCCESS$
7+
.*FAILURE$
8+
^VERIFICATION FAILED
9+
--
10+
^warning: ignoring

src/cbmc/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \
2828
../assembler/assembler$(LIBEXT) \
2929
../solvers/solvers$(LIBEXT) \
3030
../util/util$(LIBEXT) \
31-
../miniz/miniz$(OBJEXT)
31+
../miniz/miniz$(OBJEXT) \
32+
../json/json$(LIBEXT)
3233

3334
INCLUDES= -I ..
3435

src/cbmc/cbmc_parse_options.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,7 @@ void cbmc_parse_optionst::help()
11581158
// NOLINTNEXTLINE(whitespace/line_length)
11591159
" --java-max-vla-length limit the length of user-code-created arrays\n"
11601160
// NOLINTNEXTLINE(whitespace/line_length)
1161+
" --java-cp-include-files regexp or JSON list of files to load (with '@' prefix)\n"
11611162
" --java-unwind-enum-static try to unwind loops in static initialization of enums\n"
11621163
"\n"
11631164
"Semantic transformations:\n"

src/cbmc/cbmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class optionst;
5555
"(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \
5656
"(graphml-witness):" \
5757
"(java-max-vla-length):(java-unwind-enum-static)" \
58+
"(java-cp-include-files):" \
5859
"(localize-faults)(localize-faults-method):" \
5960
"(lazy-methods)" \
6061
"(fixedbv)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)

src/cegis/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \
116116
../cbmc/cbmc_dimacs$(OBJEXT) ../cbmc/all_properties$(OBJEXT) \
117117
../cbmc/fault_localization$(OBJEXT) \
118118
../cbmc/symex_coverage$(OBJEXT) \
119-
../miniz/miniz$(OBJEXT)
119+
../miniz/miniz$(OBJEXT) \
120+
../json/json$(LIBEXT)
120121

121122
INCLUDES= -I ..
122123

src/goto-cc/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ OBJ += ../big-int/big-int$(LIBEXT) \
1414
../xmllang/xmllang$(LIBEXT) \
1515
../assembler/assembler$(LIBEXT) \
1616
../langapi/langapi$(LIBEXT) \
17-
../miniz/miniz$(OBJEXT)
17+
../miniz/miniz$(OBJEXT) \
18+
../json/json$(LIBEXT)
1819

1920
INCLUDES= -I ..
2021

src/goto-diff/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \
1414
../xmllang/xmllang$(LIBEXT) \
1515
../util/util$(LIBEXT) \
1616
../solvers/solvers$(LIBEXT) \
17-
../miniz/miniz$(OBJEXT)
17+
../miniz/miniz$(OBJEXT) \
18+
../json/json$(LIBEXT)
1819

1920
INCLUDES= -I ..
2021

src/goto-instrument/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ OBJ += ../ansi-c/ansi-c$(LIBEXT) \
3838
../xmllang/xmllang$(LIBEXT) \
3939
../util/util$(LIBEXT) \
4040
../solvers/solvers$(LIBEXT) \
41-
../miniz/miniz$(OBJEXT)
41+
../miniz/miniz$(OBJEXT) \
42+
../json/json$(LIBEXT)
4243

4344
INCLUDES= -I ..
4445

src/java_bytecode/jar_file.cpp

+60-27
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ Author: Daniel Kroening, [email protected]
88

99
#include <cstring>
1010
#include <cassert>
11-
#include <sstream>
11+
#include <unordered_set>
1212

13+
#include <json/json_parser.h>
14+
#include <util/suffix.h>
1315
#include "jar_file.h"
14-
1516
/*******************************************************************\
1617
1718
Function: jar_filet::open
@@ -24,7 +25,9 @@ Function: jar_filet::open
2425
2526
\*******************************************************************/
2627

27-
void jar_filet::open(const std::string &filename)
28+
void jar_filet::open(
29+
std::string &java_cp_include_files,
30+
const std::string &filename)
2831
{
2932
if(!mz_ok)
3033
{
@@ -35,11 +38,37 @@ void jar_filet::open(const std::string &filename)
3538

3639
if(mz_ok)
3740
{
41+
// '@' signals file reading with list of class files to load
42+
bool regex_match=java_cp_include_files[0]!='@';
43+
std::regex regex_matcher;
44+
std::smatch string_matcher;
45+
std::unordered_set<std::string> set_matcher;
46+
jsont json_cp_config;
47+
if(regex_match)
48+
regex_matcher=std::regex(java_cp_include_files);
49+
else
50+
{
51+
assert(java_cp_include_files.length()>1);
52+
if(parse_json(
53+
java_cp_include_files.substr(1),
54+
get_message_handler(),
55+
json_cp_config))
56+
throw "cannot read JSON input configuration for JAR loading";
57+
if(!json_cp_config.is_object())
58+
throw "the JSON file has a wrong format";
59+
jsont include_files=json_cp_config["classFiles"];
60+
if(!include_files.is_array())
61+
throw "the JSON file has a wrong format";
62+
for(const jsont &file_entry : include_files.array)
63+
{
64+
assert(file_entry.is_string());
65+
set_matcher.insert(file_entry.value);
66+
}
67+
}
68+
3869
std::size_t number_of_files=
3970
mz_zip_reader_get_num_files(&zip);
4071

41-
index.reserve(number_of_files);
42-
4372
for(std::size_t i=0; i<number_of_files; i++)
4473
{
4574
mz_uint filename_length=mz_zip_reader_get_filename(&zip, i, nullptr, 0);
@@ -48,8 +77,23 @@ void jar_filet::open(const std::string &filename)
4877
mz_zip_reader_get_filename(&zip, i, filename_char, filename_length);
4978
assert(filename_length==filename_len);
5079
std::string file_name(filename_char);
80+
81+
// non-class files are loaded in any case
82+
bool add_file=!has_suffix(file_name, ".class");
83+
// load .class file only if they match regex
84+
if(regex_match)
85+
add_file|=std::regex_match(file_name, string_matcher, regex_matcher);
86+
// load .class file only if it is in the match set
87+
else
88+
add_file|=set_matcher.find(file_name)!=set_matcher.end();
89+
if(add_file)
90+
{
91+
if(has_suffix(file_name, ".class"))
92+
status() << "read class file " << file_name
93+
<< " from " << filename << eom;
94+
filtered_jar[file_name]=i;
95+
}
5196
delete[] filename_char;
52-
index.push_back(file_name);
5397
}
5498
}
5599
}
@@ -87,25 +131,27 @@ Function: jar_filet::get_entry
87131
88132
\*******************************************************************/
89133

90-
std::string jar_filet::get_entry(std::size_t i)
134+
std::string jar_filet::get_entry(const irep_idt &name)
91135
{
92136
if(!mz_ok)
93137
return std::string("");
94138

95-
assert(i<index.size());
96-
97139
std::string dest;
98140

141+
auto entry=filtered_jar.find(name);
142+
assert(entry!=filtered_jar.end());
143+
144+
size_t real_index=entry->second;
99145
mz_zip_archive_file_stat file_stat;
100146
memset(&file_stat, 0, sizeof(file_stat));
101-
mz_bool stat_ok=mz_zip_reader_file_stat(&zip, i, &file_stat);
147+
mz_bool stat_ok=mz_zip_reader_file_stat(&zip, real_index, &file_stat);
102148
if(stat_ok!=MZ_TRUE)
103149
return std::string();
104150
std::vector<char> buffer;
105151
size_t bufsize=file_stat.m_uncomp_size;
106152
buffer.resize(bufsize);
107153
mz_bool read_ok=
108-
mz_zip_reader_extract_to_mem(&zip, i, buffer.data(), bufsize, 0);
154+
mz_zip_reader_extract_to_mem(&zip, real_index, buffer.data(), bufsize, 0);
109155
if(read_ok!=MZ_TRUE)
110156
return std::string();
111157

@@ -128,24 +174,11 @@ Function: jar_filet::get_manifest
128174

129175
jar_filet::manifestt jar_filet::get_manifest()
130176
{
131-
std::size_t i=0;
132-
bool found=false;
133-
134-
for(const auto &e : index)
135-
{
136-
if(e=="META-INF/MANIFEST.MF")
137-
{
138-
found=true;
139-
break;
140-
}
141-
142-
i++;
143-
}
144-
145-
if(!found)
177+
auto entry=filtered_jar.find("META-INF/MANIFEST.MF");
178+
if(entry==filtered_jar.end())
146179
return manifestt();
147180

148-
std::string dest=get_entry(i);
181+
std::string dest=get_entry(entry->first);
149182
std::istringstream in(dest);
150183

151184
manifestt manifest;

src/java_bytecode/jar_file.h

+20-14
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,26 @@ Author: Daniel Kroening, [email protected]
1515
#include <string>
1616
#include <vector>
1717
#include <map>
18+
#include <regex>
19+
#include <util/message.h>
1820

19-
class jar_filet
21+
class jar_filet:public messaget
2022
{
2123
public:
2224
jar_filet():mz_ok(false) { }
2325

24-
inline explicit jar_filet(const std::string &file_name)
25-
{
26-
open(file_name);
27-
}
28-
2926
~jar_filet();
3027

31-
void open(const std::string &);
28+
void open(std::string &java_cp_include_files, const std::string &);
3229

3330
// Test for error; 'true' means we are good.
34-
inline explicit operator bool() const { return true; // TODO
35-
}
31+
explicit operator bool() const { return mz_ok; }
3632

37-
typedef std::vector<std::string> indext;
38-
indext index;
33+
// map internal index to real index in jar central directory
34+
typedef std::map<irep_idt, size_t> filtered_jart;
35+
filtered_jart filtered_jar;
3936

40-
std::string get_entry(std::size_t i);
37+
std::string get_entry(const irep_idt &);
4138

4239
typedef std::map<std::string, std::string> manifestt;
4340
manifestt get_manifest();
@@ -47,16 +44,24 @@ class jar_filet
4744
bool mz_ok;
4845
};
4946

50-
class jar_poolt
47+
class jar_poolt:public messaget
5148
{
5249
public:
50+
void set_java_cp_include_files(std::string &_java_cp_include_files)
51+
{
52+
java_cp_include_files=_java_cp_include_files;
53+
}
54+
5355
jar_filet &operator()(const std::string &file_name)
5456
{
57+
if(java_cp_include_files.empty())
58+
throw "class regexp cannot be empty";
5559
file_mapt::iterator it=file_map.find(file_name);
5660
if(it==file_map.end())
5761
{
5862
jar_filet &jar_file=file_map[file_name];
59-
jar_file.open(file_name);
63+
jar_file.set_message_handler(get_message_handler());
64+
jar_file.open(java_cp_include_files, file_name);
6065
return jar_file;
6166
}
6267
else
@@ -66,6 +71,7 @@ class jar_poolt
6671
protected:
6772
typedef std::map<std::string, jar_filet> file_mapt;
6873
file_mapt file_map;
74+
std::string java_cp_include_files;
6975
};
7076

7177
#endif // CPROVER_JAVA_BYTECODE_JAR_FILE_H

src/java_bytecode/java_bytecode_language.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313
#include <util/config.h>
1414
#include <util/cmdline.h>
1515
#include <util/string2int.h>
16+
#include <json/json_parser.h>
1617

1718
#include <goto-programs/class_hierarchy.h>
1819

@@ -55,6 +56,36 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
5556
lazy_methods_mode=LAZY_METHODS_MODE_CONTEXT_INSENSITIVE;
5657
else
5758
lazy_methods_mode=LAZY_METHODS_MODE_EAGER;
59+
60+
if(cmd.isset("java-cp-include-files"))
61+
{
62+
java_cp_include_files=cmd.get_value("java-cp-include-files");
63+
// load file list from JSON file
64+
if(java_cp_include_files[0]=='@')
65+
{
66+
jsont json_cp_config;
67+
if(parse_json(
68+
java_cp_include_files.substr(1),
69+
get_message_handler(),
70+
json_cp_config))
71+
throw "cannot read JSON input configuration for JAR loading";
72+
73+
if(!json_cp_config.is_object())
74+
throw "the JSON file has a wrong format";
75+
jsont include_files=json_cp_config["jar"];
76+
if(!include_files.is_array())
77+
throw "the JSON file has a wrong format";
78+
79+
// add jars from JSON config file to classpath
80+
for(const jsont &file_entry : include_files.array)
81+
{
82+
assert(file_entry.is_string() && has_suffix(file_entry.value, ".jar"));
83+
config.java.classpath.push_back(file_entry.value);
84+
}
85+
}
86+
}
87+
else
88+
java_cp_include_files=".*";
5889
}
5990

6091
/*******************************************************************\
@@ -129,6 +160,7 @@ bool java_bytecode_languaget::parse(
129160
const std::string &path)
130161
{
131162
java_class_loader.set_message_handler(get_message_handler());
163+
java_class_loader.set_java_cp_include_files(java_cp_include_files);
132164

133165
// look at extension
134166
if(has_suffix(path, ".class"))

src/java_bytecode/java_bytecode_language.h

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class java_bytecode_languaget:public languaget
105105
lazy_methodst lazy_methods;
106106
lazy_methods_modet lazy_methods_mode;
107107
bool string_refinement_enabled;
108+
std::string java_cp_include_files;
108109
};
109110

110111
languaget *new_java_bytecode_language();

0 commit comments

Comments
 (0)