Skip to content

Commit eb0a469

Browse files
author
owen-jones-diffblue
authored
Merge pull request diffblue#437 from diffblue/CBMC_merge_2018-06-04
SEC-440: Cbmc merge 2018-06-04
2 parents c1f0127 + 0e48032 commit eb0a469

File tree

173 files changed

+1867
-1076
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

173 files changed

+1867
-1076
lines changed

.travis.yml

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ jobs:
7070
- g++-5
7171
- libubsan0
7272
- python3-pip
73+
- libc6-dev-i386
7374
before_install:
7475
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
7576
# Install pytest locally and adjust PATH so pip3 can find it
@@ -137,6 +138,7 @@ jobs:
137138
- libubsan0
138139
- parallel
139140
- python3-pip
141+
- libc6-dev-i386
140142
before_install:
141143
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
142144
# Install pytest locally and adjust PATH so pip3 can find it
@@ -171,6 +173,7 @@ jobs:
171173
- libubsan0
172174
- parallel
173175
- python3-pip
176+
- libc6-dev-i386
174177
before_install:
175178
- mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc
176179
- export CCACHE_CPP2=yes
@@ -203,6 +206,7 @@ jobs:
203206
- libstdc++-5-dev
204207
- libubsan0
205208
- python3-pip
209+
- libc6-dev-i386
206210
before_install:
207211
- mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc
208212
- export CCACHE_CPP2=yes

cbmc/.travis.yml

+7-2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ jobs:
8383
- g++-5
8484
- libubsan0
8585
- parallel
86+
- libc6-dev-i386
8687
before_install:
8788
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
8889
# env: COMPILER=g++-5 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover -fno-omit-frame-pointer"
@@ -115,6 +116,7 @@ jobs:
115116
- libwww-perl
116117
- g++-5
117118
- libubsan0
119+
- libc6-dev-i386
118120
before_install:
119121
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
120122
# env: COMPILER=g++-5 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover -fno-omit-frame-pointer"
@@ -140,8 +142,9 @@ jobs:
140142
- libstdc++-5-dev
141143
- libubsan0
142144
- parallel
145+
- libc6-dev-i386
143146
before_install:
144-
- mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc
147+
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
145148
- export CCACHE_CPP2=yes
146149
# env: COMPILER=clang++-3.7 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined,integer -fno-omit-frame-pointer"
147150
env:
@@ -165,8 +168,9 @@ jobs:
165168
- clang-3.7
166169
- libstdc++-5-dev
167170
- libubsan0
171+
- libc6-dev-i386
168172
before_install:
169-
- mkdir bin ; ln -s /usr/bin/clang-3.7 bin/gcc
173+
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
170174
- export CCACHE_CPP2=yes
171175
# env: COMPILER=clang++-3.7 SAN_FLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined,integer -fno-omit-frame-pointer"
172176
env:
@@ -188,6 +192,7 @@ jobs:
188192
- ubuntu-toolchain-r-test
189193
packages:
190194
- g++-5
195+
- libc6-dev-i386
191196
before_install:
192197
- mkdir bin ; ln -s /usr/bin/gcc-5 bin/gcc
193198
install:

cbmc/buildspec.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ phases:
66
- echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu trusty main" > /etc/apt/sources.list.d/toolchain.list
77
- apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA9EF27F
88
- apt-get update -y
9-
- apt-get install -y g++-5 flex bison make git libwww-perl patch ccache
9+
- apt-get install -y g++-5 flex bison make git libwww-perl patch ccache libc6-dev-i386
1010
- apt-get install -y openjdk-7-jdk
1111
- update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 1
1212
- update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 1
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
public @interface ExampleAnnotation {
3+
4+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
public enum ExampleEnum {
3+
4+
}
5+
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
interface ExampleInterface {
3+
4+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
; Compile me with Jasmin 2.1+ (https://sourceforge.net/projects/jasmin/)
2+
3+
.class public synthetic ExampleSynthetic
4+
.super java/lang/Object
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
public class Test {
3+
4+
public static void main() {
5+
6+
assert ExampleAnnotation.class.isAnnotation();
7+
assert ExampleInterface.class.isInterface();
8+
assert ExampleEnum.class.isEnum();
9+
assert ExampleSynthetic.class.isSynthetic();
10+
11+
assert char[].class.isArray();
12+
assert short[].class.isArray();
13+
assert int[].class.isArray();
14+
assert long[].class.isArray();
15+
assert float[].class.isArray();
16+
assert double[].class.isArray();
17+
assert boolean[].class.isArray();
18+
assert Object[].class.isArray();
19+
assert Object[][].class.isArray();
20+
21+
// Note use of '==' not '.equals', as we expect the same exact literal,
22+
// which in jbmc always have the same address.
23+
// Note names of array classes are not tested yet, as arrays' types are
24+
// printed as their raw signature, to be addressed separately.
25+
// Note also primitive types (e.g. int.class) are not addresses here, as
26+
// they are created through box types' static initializers (e.g. Integer
27+
// has a static member TYPE that holds the Class for `int.class`)
28+
29+
assert ExampleAnnotation.class.getName() == "ExampleAnnotation";
30+
assert ExampleInterface.class.getName() == "ExampleInterface";
31+
assert ExampleEnum.class.getName() == "ExampleEnum";
32+
33+
}
34+
35+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package java.lang;
2+
3+
public class Class {
4+
5+
private String name;
6+
7+
private boolean isAnnotation;
8+
private boolean isArray;
9+
private boolean isInterface;
10+
private boolean isSynthetic;
11+
private boolean isLocalClass;
12+
private boolean isMemberClass;
13+
private boolean isEnum;
14+
15+
public void cproverInitializeClassLiteral(
16+
String name,
17+
boolean isAnnotation,
18+
boolean isArray,
19+
boolean isInterface,
20+
boolean isSynthetic,
21+
boolean isLocalClass,
22+
boolean isMemberClass,
23+
boolean isEnum) {
24+
25+
this.name = name;
26+
this.isAnnotation = isAnnotation;
27+
this.isArray = isArray;
28+
this.isInterface = isInterface;
29+
this.isSynthetic = isSynthetic;
30+
this.isLocalClass = isLocalClass;
31+
this.isMemberClass = isMemberClass;
32+
this.isEnum = isEnum;
33+
34+
}
35+
36+
public String getName() { return name; }
37+
38+
public boolean isAnnotation() { return isAnnotation; }
39+
public boolean isArray() { return isArray; }
40+
public boolean isInterface() { return isInterface; }
41+
public boolean isSynthetic() { return isSynthetic; }
42+
public boolean isLocalClass() { return isLocalClass; }
43+
public boolean isMemberClass() { return isMemberClass; }
44+
public boolean isEnum() { return isEnum; }
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
Test.class
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE symex-driven-lazy-loading-expected-failure
2+
Test.class
3+
--lazy-methods
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
lazy-methods is incompatible with symex-driven lazy loading

cbmc/jbmc/src/java_bytecode/ci_lazy_methods.cpp

+40-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "java_string_library_preprocess.h"
1414
#include "remove_exceptions.h"
1515

16+
#include <util/expr_iterator.h>
1617
#include <util/suffix.h>
1718

1819
#include <goto-programs/resolve_inherited_component.h>
@@ -52,6 +53,31 @@ ci_lazy_methodst::ci_lazy_methodst(
5253
class_hierarchy(symbol_table);
5354
}
5455

56+
/// Checks if an expression refers to any class literals (e.g. MyType.class)
57+
/// These are expressed as ldc instructions in Java bytecode, and as symbols
58+
/// of the form `MyType@class_model` in GOTO programs.
59+
/// \param expr: expression to check
60+
/// \return true if the expression or any of its subexpressions refer to a
61+
/// class
62+
static bool references_class_model(const exprt &expr)
63+
{
64+
static const symbol_typet class_type("java::java.lang.Class");
65+
66+
for(auto it = expr.depth_begin(); it != expr.depth_end(); ++it)
67+
{
68+
if(can_cast_expr<symbol_exprt>(*it) &&
69+
it->type() == class_type &&
70+
has_suffix(
71+
id2string(to_symbol_expr(*it).get_identifier()),
72+
JAVA_CLASS_MODEL_SUFFIX))
73+
{
74+
return true;
75+
}
76+
}
77+
78+
return false;
79+
}
80+
5581
/// Uses a simple context-insensitive ('ci') analysis to determine which methods
5682
/// may be reachable from the main entry point. In brief, static methods are
5783
/// reachable if we find a callsite in another reachable site, while virtual
@@ -122,6 +148,7 @@ bool ci_lazy_methodst::operator()(
122148

123149
std::unordered_set<irep_idt> methods_already_populated;
124150
std::unordered_set<exprt, irep_hash> virtual_function_calls;
151+
bool class_initializer_seen = false;
125152

126153
bool any_new_classes = true;
127154
while(any_new_classes)
@@ -149,8 +176,19 @@ bool ci_lazy_methodst::operator()(
149176
// Couldn't convert this function
150177
continue;
151178
}
152-
gather_virtual_callsites(
153-
symbol_table.lookup_ref(mname).value, virtual_function_calls);
179+
const exprt &method_body = symbol_table.lookup_ref(mname).value;
180+
181+
gather_virtual_callsites(method_body, virtual_function_calls);
182+
183+
if(!class_initializer_seen && references_class_model(method_body))
184+
{
185+
class_initializer_seen = true;
186+
irep_idt initializer_signature =
187+
get_java_class_literal_initializer_signature();
188+
if(symbol_table.has_symbol(initializer_signature))
189+
methods_to_convert_later.insert(initializer_signature);
190+
}
191+
154192
any_new_methods=true;
155193
}
156194
}

cbmc/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

+35-7
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ void java_bytecode_convert_classt::convert(
265265
class_type.set_tag(c.name);
266266
class_type.set(ID_base_name, c.name);
267267
class_type.set(ID_abstract, c.is_abstract);
268+
class_type.set(ID_is_annotation, c.is_annotation);
269+
class_type.set(ID_interface, c.is_interface);
270+
class_type.set(ID_synthetic, c.is_synthetic);
268271
class_type.set_final(c.is_final);
269272
if(c.is_enum)
270273
{
@@ -875,8 +878,9 @@ void java_bytecode_convert_classt::add_array_types(symbol_tablet &symbol_table)
875878

876879
bool java_bytecode_convert_classt::is_overlay_method(const methodt &method)
877880
{
878-
return java_bytecode_parse_treet::does_annotation_exist(
879-
method.annotations, ID_overlay_method);
881+
return java_bytecode_parse_treet::find_annotation(
882+
method.annotations, ID_overlay_method)
883+
.has_value();
880884
}
881885

882886
bool java_bytecode_convert_class(
@@ -1015,24 +1019,48 @@ static void find_and_replace_parameters(
10151019
/// \param annotations: The java_annotationt collection to populate
10161020
void convert_annotations(
10171021
const java_bytecode_parse_treet::annotationst &parsed_annotations,
1018-
std::vector<java_annotationt> &annotations)
1022+
std::vector<java_annotationt> &java_annotations)
10191023
{
10201024
for(const auto &annotation : parsed_annotations)
10211025
{
1022-
annotations.emplace_back(annotation.type);
1026+
java_annotations.emplace_back(annotation.type);
10231027
std::vector<java_annotationt::valuet> &values =
1024-
annotations.back().get_values();
1028+
java_annotations.back().get_values();
10251029
std::transform(
10261030
annotation.element_value_pairs.begin(),
10271031
annotation.element_value_pairs.end(),
10281032
std::back_inserter(values),
1029-
[](const decltype(annotation.element_value_pairs)::value_type &value)
1030-
{
1033+
[](const decltype(annotation.element_value_pairs)::value_type &value) {
10311034
return java_annotationt::valuet(value.element_name, value.value);
10321035
});
10331036
}
10341037
}
10351038

1039+
/// Convert java annotations, e.g. as retrieved from the symbol table, back
1040+
/// to type annotationt (inverse of convert_annotations())
1041+
/// \param java_annotations: The java_annotationt collection to convert
1042+
/// \param annotations: The annotationt collection to populate
1043+
void convert_java_annotations(
1044+
const std::vector<java_annotationt> &java_annotations,
1045+
java_bytecode_parse_treet::annotationst &annotations)
1046+
{
1047+
for(const auto &java_annotation : java_annotations)
1048+
{
1049+
annotations.emplace_back(java_bytecode_parse_treet::annotationt());
1050+
auto &annotation = annotations.back();
1051+
annotation.type = java_annotation.get_type();
1052+
1053+
std::transform(
1054+
java_annotation.get_values().begin(),
1055+
java_annotation.get_values().end(),
1056+
std::back_inserter(annotation.element_value_pairs),
1057+
[](const java_annotationt::valuet &value)
1058+
-> java_bytecode_parse_treet::annotationt::element_value_pairt {
1059+
return {value.get_name(), value.get_value()};
1060+
});
1061+
}
1062+
}
1063+
10361064
/// Checks if the class is implicitly generic, i.e., it is an inner class of
10371065
/// any generic class. All uses of the implicit generic type parameters within
10381066
/// the inner class are updated to point to the type parameters of the

cbmc/jbmc/src/java_bytecode/java_bytecode_convert_class.h

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ void convert_annotations(
3333
const java_bytecode_parse_treet::annotationst &parsed_annotations,
3434
std::vector<java_annotationt> &annotations);
3535

36+
void convert_java_annotations(
37+
const std::vector<java_annotationt> &java_annotations,
38+
java_bytecode_parse_treet::annotationst &annotations);
39+
3640
void mark_java_implicitly_generic_class_type(
3741
const irep_idt &class_name,
3842
symbol_tablet &symbol_table);

cbmc/jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,9 @@ void java_bytecode_convert_method_lazy(
404404
}
405405

406406
method_symbol.type=member_type;
407+
// Not used in jbmc at present, but other codebases that use jbmc as a library
408+
// use this information.
409+
method_symbol.type.set(ID_C_abstract, m.is_abstract);
407410
symbol_table.add(method_symbol);
408411
}
409412

@@ -1185,7 +1188,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
11851188
{
11861189
if(cur_pc==it->handler_pc)
11871190
{
1188-
if(catch_type!=typet() || it->catch_type==symbol_typet())
1191+
if(catch_type != typet() || it->catch_type == symbol_typet(irep_idt()))
11891192
{
11901193
catch_type=symbol_typet("java::java.lang.Throwable");
11911194
break;

0 commit comments

Comments
 (0)