Skip to content

Commit b236ee4

Browse files
author
Matthias Güdemann
committed
allow regex to limit class files loaded from JAR
1 parent 2245eb2 commit b236ee4

File tree

7 files changed

+44
-16
lines changed

7 files changed

+44
-16
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,7 @@ void cbmc_parse_optionst::help()
11551155
// NOLINTNEXTLINE(whitespace/line_length)
11561156
" --java-max-vla-length limit the length of user-code-created arrays\n"
11571157
// NOLINTNEXTLINE(whitespace/line_length)
1158+
" --java-cp-include-files regexp of class files to load\n"
11581159
" --java-unwind-enum-static try to unwind loops in static initialization of enums\n"
11591160
"\n"
11601161
"Semantic transformations:\n"

src/cbmc/cbmc_parse_options.h

Lines changed: 1 addition & 0 deletions
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/java_bytecode/jar_file.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ Author: Daniel Kroening, [email protected]
99
#include <cstring>
1010
#include <cassert>
1111
#include <sstream>
12-
1312
#include "jar_file.h"
13+
#include <util/suffix.h>
1414

1515
/*******************************************************************\
1616
@@ -24,7 +24,7 @@ Function: jar_filet::open
2424
2525
\*******************************************************************/
2626

27-
void jar_filet::open(const std::string &filename)
27+
void jar_filet::open(std::string &java_cp_include_files, const std::string &filename)
2828
{
2929
if(!mz_ok)
3030
{
@@ -38,8 +38,7 @@ void jar_filet::open(const std::string &filename)
3838
std::size_t number_of_files=
3939
mz_zip_reader_get_num_files(&zip);
4040

41-
index.reserve(number_of_files);
42-
41+
size_t filtered_index=0;
4342
for(std::size_t i=0; i<number_of_files; i++)
4443
{
4544
mz_uint filename_length=mz_zip_reader_get_filename(&zip, i, nullptr, 0);
@@ -48,8 +47,17 @@ void jar_filet::open(const std::string &filename)
4847
mz_zip_reader_get_filename(&zip, i, filename_char, filename_length);
4948
assert(filename_length==filename_len);
5049
std::string file_name(filename_char);
50+
std::smatch string_matcher;
51+
std::regex matcher(java_cp_include_files);
52+
// load .class files only if they match regex
53+
if(std::regex_match(file_name, string_matcher, matcher) ||
54+
!has_suffix(file_name, ".class"))
55+
{
56+
index.push_back(file_name);
57+
filtered_jar[filtered_index]=i;
58+
filtered_index++;
59+
}
5160
delete[] filename_char;
52-
index.push_back(file_name);
5361
}
5462
}
5563
}
@@ -96,16 +104,17 @@ std::string jar_filet::get_entry(std::size_t i)
96104

97105
std::string dest;
98106

107+
size_t real_index=filtered_jar[i];
99108
mz_zip_archive_file_stat file_stat;
100109
memset(&file_stat, 0, sizeof(file_stat));
101-
mz_bool stat_ok=mz_zip_reader_file_stat(&zip, i, &file_stat);
110+
mz_bool stat_ok=mz_zip_reader_file_stat(&zip, real_index, &file_stat);
102111
if(stat_ok!=MZ_TRUE)
103112
return std::string();
104113
std::vector<char> buffer;
105114
size_t bufsize=file_stat.m_uncomp_size;
106115
buffer.resize(bufsize);
107116
mz_bool read_ok=
108-
mz_zip_reader_extract_to_mem(&zip, i, buffer.data(), bufsize, 0);
117+
mz_zip_reader_extract_to_mem(&zip, real_index, buffer.data(), bufsize, 0);
109118
if(read_ok!=MZ_TRUE)
110119
return std::string();
111120

src/java_bytecode/jar_file.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,26 @@ Author: Daniel Kroening, [email protected]
1515
#include <string>
1616
#include <vector>
1717
#include <map>
18+
#include <regex>
1819

1920
class jar_filet
2021
{
2122
public:
2223
jar_filet():mz_ok(false) { }
23-
24-
inline explicit jar_filet(const std::string &file_name)
25-
{
26-
open(file_name);
27-
}
24+
inline explicit jar_filet(const std::string &file_name) { }
2825

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+
inline explicit operator bool() const { return mz_ok; }
3632

3733
typedef std::vector<std::string> indext;
3834
indext index;
35+
// map internal index to real index in jar central directory
36+
typedef std::map<int, int> filtered_jart;
37+
filtered_jart filtered_jar;
3938

4039
std::string get_entry(std::size_t i);
4140

@@ -45,18 +44,25 @@ class jar_filet
4544
protected:
4645
mz_zip_archive zip;
4746
bool mz_ok;
47+
std::string matcher;
48+
std::map<int, int> index_map;
4849
};
4950

5051
class jar_poolt
5152
{
5253
public:
54+
void set_java_cp_include_files(std::string &_java_cp_include_files)
55+
{
56+
java_cp_include_files=_java_cp_include_files;
57+
}
5358
jar_filet &operator()(const std::string &file_name)
5459
{
60+
assert(!java_cp_include_files.empty() && "class regexp cannot be empty");
5561
file_mapt::iterator it=file_map.find(file_name);
5662
if(it==file_map.end())
5763
{
5864
jar_filet &jar_file=file_map[file_name];
59-
jar_file.open(file_name);
65+
jar_file.open(java_cp_include_files, file_name);
6066
return jar_file;
6167
}
6268
else
@@ -66,6 +72,7 @@ class jar_poolt
6672
protected:
6773
typedef std::map<std::string, jar_filet> file_mapt;
6874
file_mapt file_map;
75+
std::string java_cp_include_files;
6976
};
7077

7178
#endif // CPROVER_JAVA_BYTECODE_JAR_FILE_H

src/java_bytecode/java_bytecode_language.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ void java_bytecode_languaget::get_language_options(const cmdlinet &cmd)
5555
lazy_methods_mode=LAZY_METHODS_MODE_CONTEXT_INSENSITIVE;
5656
else
5757
lazy_methods_mode=LAZY_METHODS_MODE_EAGER;
58+
if(cmd.isset("java-cp-include-files"))
59+
java_cp_include_files=cmd.get_value("java-cp-include-files");
60+
else
61+
java_cp_include_files=".*";
5862
}
5963

6064
/*******************************************************************\
@@ -129,6 +133,7 @@ bool java_bytecode_languaget::parse(
129133
const std::string &path)
130134
{
131135
java_class_loader.set_message_handler(get_message_handler());
136+
java_class_loader.set_java_cp_include_files(java_cp_include_files);
132137

133138
// look at extension
134139
if(has_suffix(path, ".class"))

src/java_bytecode/java_bytecode_language.h

Lines changed: 1 addition & 0 deletions
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();

src/java_bytecode/java_class_loader.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class java_class_loadert:public messaget
2020
{
2121
public:
2222
java_bytecode_parse_treet &operator()(const irep_idt &);
23+
void set_java_cp_include_files(std::string &java_cp_include_files)
24+
{
25+
jar_pool.set_java_cp_include_files(java_cp_include_files);
26+
}
2327

2428
// maps class names to the parse trees
2529
typedef std::map<irep_idt, java_bytecode_parse_treet> class_mapt;

0 commit comments

Comments
 (0)