Skip to content

Commit 1f2bb67

Browse files
authored
Merge pull request #1229 from smowton/smowton/feature/use_null_check_annotation_everywhere
Use null check annotation everywhere
2 parents c659d13 + 1b47689 commit 1f2bb67

File tree

13 files changed

+90
-55
lines changed

13 files changed

+90
-55
lines changed

regression/cbmc-java/stack_var4/test.desc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ stack_test.class
33

44
^EXIT=0$
55
^SIGNAL=0$
6-
^.*assertion at file stack_test.java line 5 function.*: SUCCESS
7-
$
86
^VERIFICATION SUCCESSFUL$
97
--
108
^warning: ignoring

regression/cbmc-java/stack_var5/test.desc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ stack_test.class
33

44
^EXIT=0$
55
^SIGNAL=0$
6-
^.*assertion at file stack_test.java line 5 function.*: SUCCESS
7-
$
86
^VERIFICATION SUCCESSFUL$
97
--
108
^warning: ignoring

regression/cbmc-java/stack_var6/test.desc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ stack_test.class
33

44
^EXIT=0$
55
^SIGNAL=0$
6-
^.*assertion at file stack_test.java line 5 function.*: SUCCESS
7-
$
86
^VERIFICATION SUCCESSFUL$
97
--
108
^warning: ignoring

regression/cbmc-java/stack_var7/test.desc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ stack_test.class
33

44
^EXIT=0$
55
^SIGNAL=0$
6-
^.*assertion at file stack_test.java line 5 function.*: SUCCESS
7-
$
86
^VERIFICATION SUCCESSFUL$
97
--
108
^warning: ignoring

regression/strings/StaticCharMethods05/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ StaticCharMethods05.class
33
--refine-strings
44
^EXIT=10$
55
^SIGNAL=0$
6-
^\[pointer_dereference\.2\] reference is null in \*this->data: FAILURE$
6+
null-pointer-exception\.14\] Throw null: FAILURE
77
^\[.*assertion\.1\] .* line 12 .* FAILURE$
88
^\[.*assertion\.2\] .* line 22 .* FAILURE$
99
^VERIFICATION FAILED$

src/analyses/goto_check.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ void goto_checkt::pointer_validity_check(
909909
const exprt &access_ub,
910910
const irep_idt &mode)
911911
{
912-
if(mode!=ID_java && !enable_pointer_check)
912+
if(!enable_pointer_check)
913913
return;
914914

915915
const exprt &pointer=expr.op0();

src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,9 +524,7 @@ static member_exprt to_member(const exprt &pointer, const exprt &fieldref)
524524
exprt pointer2=
525525
typecast_exprt(pointer, java_reference_type(class_type));
526526

527-
dereference_exprt obj_deref(pointer2, class_type);
528-
// tag it so it's easy to identify during instrumentation
529-
obj_deref.set(ID_java_member_access, true);
527+
dereference_exprt obj_deref=checked_dereference(pointer2, class_type);
530528

531529
const member_exprt member_expr(
532530
obj_deref,

src/java_bytecode/java_bytecode_instrument.cpp

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,11 @@ class java_bytecode_instrumentt:public messaget
2929
java_bytecode_instrumentt(
3030
symbol_tablet &_symbol_table,
3131
const bool _throw_runtime_exceptions,
32-
message_handlert &_message_handler,
33-
const size_t _max_array_length,
34-
const size_t _max_tree_depth):
32+
message_handlert &_message_handler):
3533
messaget(_message_handler),
3634
symbol_table(_symbol_table),
3735
throw_runtime_exceptions(_throw_runtime_exceptions),
38-
message_handler(_message_handler),
39-
max_array_length(_max_array_length),
40-
max_tree_depth(_max_tree_depth)
36+
message_handler(_message_handler)
4137
{
4238
}
4339

@@ -47,8 +43,6 @@ class java_bytecode_instrumentt:public messaget
4743
symbol_tablet &symbol_table;
4844
const bool throw_runtime_exceptions;
4945
message_handlert &message_handler;
50-
const size_t max_array_length;
51-
const size_t max_tree_depth;
5246

5347
codet throw_exception(
5448
const exprt &cond,
@@ -566,29 +560,52 @@ void java_bytecode_instrumentt::operator()(exprt &expr)
566560
instrument_code(expr);
567561
}
568562

563+
/// Instruments the code attached to `symbol` with
564+
/// runtime exceptions or corresponding assertions.
565+
/// Exceptions are thrown when the `throw_runtime_exceptions` flag is set.
566+
/// Otherwise, assertions are emitted.
567+
/// \param symbol_table: global symbol table (may gain exception type stubs and
568+
/// similar)
569+
/// \param symbol: the symbol to instrument
570+
/// \param throw_runtime_exceptions: flag determining whether we instrument the
571+
/// code with runtime exceptions or with assertions. The former applies if
572+
/// this flag is set to true.
573+
/// \param message_handler: stream to report status and warnings
574+
void java_bytecode_instrument_symbol(
575+
symbol_tablet &symbol_table,
576+
symbolt &symbol,
577+
const bool throw_runtime_exceptions,
578+
message_handlert &message_handler)
579+
{
580+
java_bytecode_instrumentt instrument(
581+
symbol_table,
582+
throw_runtime_exceptions,
583+
message_handler);
584+
INVARIANT(
585+
symbol.value.id()==ID_code,
586+
"java_bytecode_instrument expects a code-typed symbol");
587+
instrument(symbol.value);
588+
}
589+
569590
/// Instruments all the code in the symbol_table with
570591
/// runtime exceptions or corresponding assertions.
571592
/// Exceptions are thrown when the `throw_runtime_exceptions` flag is set.
572593
/// Otherwise, assertions are emitted.
573-
/// \par parameters: `symbol_table`: the symbol table to instrument
574-
/// `throw_runtime_exceptions`: flag determining whether we instrument the code
575-
/// with runtime exceptions or with assertions. The former applies if this flag
576-
/// is set to true.
577-
/// `max_array_length`: maximum array length; the only reason we need this is
578-
/// in order to be able to call the object factory to create exceptions.
594+
/// \param symbol_table: global symbol table, all of whose code members
595+
/// will be annotated (may gain exception type stubs and similar)
596+
/// \param throw_runtime_exceptions: flag determining whether we instrument the
597+
/// code with runtime exceptions or with assertions. The former applies if
598+
/// this flag is set to true.
599+
/// \param message_handler: stream to report status and warnings
579600
void java_bytecode_instrument(
580601
symbol_tablet &symbol_table,
581602
const bool throw_runtime_exceptions,
582-
message_handlert &message_handler,
583-
const size_t max_array_length,
584-
const size_t max_tree_depth)
603+
message_handlert &message_handler)
585604
{
586605
java_bytecode_instrumentt instrument(
587606
symbol_table,
588607
throw_runtime_exceptions,
589-
message_handler,
590-
max_array_length,
591-
max_tree_depth);
608+
message_handler);
592609

593610
std::vector<irep_idt> symbols_to_instrument;
594611
forall_symbols(s_it, symbol_table.symbols)
@@ -600,9 +617,5 @@ void java_bytecode_instrument(
600617
// instrument(...) can add symbols to the table, so it's
601618
// not safe to hold a reference to a symbol across a call.
602619
for(const auto &symbol : symbols_to_instrument)
603-
{
604-
exprt value=symbol_table.lookup(symbol).value;
605-
instrument(value);
606-
symbol_table.lookup(symbol).value=value;
607-
}
620+
instrument(symbol_table.lookup(symbol).value);
608621
}

src/java_bytecode/java_bytecode_instrument.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ Date: June 2017
1111
#ifndef CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_INSTRUMENT_H
1212
#define CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_INSTRUMENT_H
1313

14+
void java_bytecode_instrument_symbol(
15+
symbol_tablet &symbol_table,
16+
symbolt &symbol,
17+
const bool throw_runtime_exceptions,
18+
message_handlert &_message_handler);
19+
1420
void java_bytecode_instrument(
1521
symbol_tablet &symbol_table,
1622
const bool throw_runtime_exceptions,
17-
message_handlert &_message_handler,
18-
const size_t max_array_length,
19-
const size_t max_depth);
23+
message_handlert &_message_handler);
24+
2025
#endif

src/java_bytecode/java_bytecode_language.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,9 +459,7 @@ bool java_bytecode_languaget::typecheck(
459459
java_bytecode_instrument(
460460
symbol_table,
461461
throw_runtime_exceptions,
462-
get_message_handler(),
463-
max_nondet_array_length,
464-
max_nondet_tree_depth);
462+
get_message_handler());
465463

466464
// now typecheck all
467465
if(java_bytecode_typecheck(
@@ -746,6 +744,13 @@ void java_bytecode_languaget::replace_string_methods(
746744
// Replace body of the function by code generated by string preprocess
747745
symbolt &symbol=context.lookup(id);
748746
symbol.value=generated_code;
747+
// Specifically instrument the new code, since this comes after the
748+
// blanket instrumentation pass called before typechecking.
749+
java_bytecode_instrument_symbol(
750+
context,
751+
symbol,
752+
throw_runtime_exceptions,
753+
get_message_handler());
749754
}
750755
}
751756
}

src/java_bytecode/java_string_library_preprocess.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Date: April 2017
2424
#include <util/string_expr.h>
2525
#include "java_types.h"
2626
#include "java_object_factory.h"
27+
#include "java_utils.h"
2728

2829
#include "java_string_library_preprocess.h"
2930

@@ -334,7 +335,8 @@ exprt::operandst java_string_library_preprocesst::process_operands(
334335
{
335336
if(implements_java_char_sequence(p.type()))
336337
{
337-
dereference_exprt deref(p, to_pointer_type(p.type()).subtype());
338+
dereference_exprt deref=
339+
checked_dereference(p, to_pointer_type(p.type()).subtype());
338340
process_single_operand(ops, deref, loc, symbol_table, init_code);
339341
}
340342
else if(is_java_char_array_pointer_type(p.type()))
@@ -371,14 +373,16 @@ exprt::operandst
371373
exprt op1=operands[1];
372374

373375
assert(implements_java_char_sequence(op0.type()));
374-
dereference_exprt deref0(op0, to_pointer_type(op0.type()).subtype());
376+
dereference_exprt deref0=
377+
checked_dereference(op0, to_pointer_type(op0.type()).subtype());
375378
process_single_operand(ops, deref0, loc, symbol_table, init_code);
376379

377380
// TODO: Manage the case where we have a non-String Object (this should
378381
// probably be handled upstream. At any rate, the following code should be
379382
// protected with assertions on the type of op1.
380383
typecast_exprt tcast(op1, to_pointer_type(op0.type()));
381-
dereference_exprt deref1(tcast, to_pointer_type(op0.type()).subtype());
384+
dereference_exprt deref1=
385+
checked_dereference(tcast, to_pointer_type(op0.type()).subtype());
382386
process_single_operand(ops, deref1, loc, symbol_table, init_code);
383387
return ops;
384388
}
@@ -466,9 +470,12 @@ string_exprt java_string_library_preprocesst::replace_char_array(
466470
code_blockt &code)
467471
{
468472
refined_string_typet ref_type=refined_string_type;
469-
dereference_exprt array(array_pointer, array_pointer.type().subtype());
473+
dereference_exprt array=
474+
checked_dereference(array_pointer, array_pointer.type().subtype());
470475
exprt array_data=get_data(array, symbol_table);
471476
// `deref_array` is *(array_pointer->data)`
477+
// No null-pointer-exception check here since all array structures
478+
// have non-null data
472479
const typet &content_type=ref_type.get_content_type();
473480
dereference_exprt deref_array(array_data, array_data.type().subtype());
474481

@@ -724,7 +731,7 @@ codet java_string_library_preprocesst::code_assign_components_to_java_string(
724731
symbol_tablet &symbol_table)
725732
{
726733
assert(implements_java_char_sequence(lhs.type()));
727-
dereference_exprt deref(lhs, lhs.type().subtype());
734+
dereference_exprt deref=checked_dereference(lhs, lhs.type().subtype());
728735

729736
code_blockt code;
730737

@@ -741,7 +748,7 @@ codet java_string_library_preprocesst::code_assign_components_to_java_string(
741748
struct_rhs.copy_to_operands(rhs_length);
742749
struct_rhs.copy_to_operands(rhs_array);
743750
code.add(code_assignt(
744-
dereference_exprt(lhs, lhs.type().subtype()), struct_rhs));
751+
checked_dereference(lhs, lhs.type().subtype()), struct_rhs));
745752

746753
return code;
747754
}
@@ -782,7 +789,7 @@ codet java_string_library_preprocesst::
782789
symbol_tablet &symbol_table)
783790
{
784791
assert(implements_java_char_sequence(lhs.type()));
785-
dereference_exprt deref(lhs, lhs.type().subtype());
792+
dereference_exprt deref=checked_dereference(lhs, lhs.type().subtype());
786793

787794
code_blockt code;
788795
exprt new_array=allocate_fresh_array(
@@ -816,7 +823,7 @@ codet java_string_library_preprocesst::code_assign_java_string_to_string_expr(
816823
else
817824
deref_type=rhs.type().subtype();
818825

819-
dereference_exprt deref(rhs, deref_type);
826+
dereference_exprt deref=checked_dereference(rhs, deref_type);
820827

821828
// Fields of the string object
822829
exprt rhs_length=get_length(deref, symbol_table);
@@ -1170,7 +1177,7 @@ codet java_string_library_preprocesst::make_string_to_char_array_code(
11701177
code.add(code_assignt(deref_data, string_expr.content()));
11711178

11721179
// lhs->data = &data[0]
1173-
dereference_exprt deref_lhs(lhs, lhs.type().subtype());
1180+
dereference_exprt deref_lhs=checked_dereference(lhs, lhs.type().subtype());
11741181
exprt lhs_data=get_data(deref_lhs, symbol_table);
11751182
index_exprt first_elt(
11761183
deref_data, from_integer(0, java_int_type()), java_char_type());
@@ -1519,7 +1526,7 @@ codet java_string_library_preprocesst::make_object_get_class_code(
15191526

15201527
// class_identifier is this->@class_identifier
15211528
member_exprt class_identifier(
1522-
dereference_exprt(this_obj, this_obj.type().subtype()),
1529+
checked_dereference(this_obj, this_obj.type().subtype()),
15231530
"@class_identifier",
15241531
string_typet());
15251532

@@ -1743,7 +1750,8 @@ codet java_string_library_preprocesst::make_string_length_code(
17431750

17441751
code_typet::parameterst params=type.parameters();
17451752
symbol_exprt arg_this(params[0].get_identifier(), params[0].type());
1746-
dereference_exprt deref(arg_this, arg_this.type().subtype());
1753+
dereference_exprt deref=
1754+
checked_dereference(arg_this, arg_this.type().subtype());
17471755

17481756
// Create a new string_exprt to be picked up by the solver
17491757
string_exprt str_expr=fresh_string_expr(loc, symbol_table, code);

src/java_bytecode/java_utils.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,11 @@ irep_idt resolve_friendly_method_name(
171171
}
172172
}
173173
}
174+
175+
dereference_exprt checked_dereference(const exprt &expr, const typet &type)
176+
{
177+
dereference_exprt result(expr, type);
178+
// tag it so it's easy to identify during instrumentation
179+
result.set(ID_java_member_access, true);
180+
return result;
181+
}

src/java_bytecode/java_utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
#include <util/type.h>
1111
#include <util/symbol_table.h>
1212
#include <util/message.h>
13+
#include <util/std_expr.h>
1314

1415
#include "java_bytecode_parse_tree.h"
1516

@@ -64,4 +65,9 @@ irep_idt resolve_friendly_method_name(
6465
const symbol_tablet &symbol_table,
6566
std::string &error);
6667

68+
/// Dereference an expression and flag it for a null-pointer check
69+
/// \param expr: expression to dereference and check
70+
/// \param type: expected result type (typically expr.type().subtype())
71+
dereference_exprt checked_dereference(const exprt &expr, const typet &type);
72+
6773
#endif // CPROVER_JAVA_BYTECODE_JAVA_UTILS_H

0 commit comments

Comments
 (0)