Skip to content

Commit f55e413

Browse files
author
Daniel Kroening
authored
Merge pull request #737 from smowton/java_null_checks
Always check Java pointers for null before deref
2 parents f03c32d + f9cd371 commit f55e413

File tree

10 files changed

+50
-50
lines changed

10 files changed

+50
-50
lines changed

regression/cbmc-java/exceptions1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ test.class
44
^EXIT=10$
55
^SIGNAL=0$
66
^.*assertion at file test.java line 26 function.*: FAILURE$
7-
\*\* 1 of 9 failed \(2 iterations\)$
7+
\*\* 1 of [0-9]* failed \(2 iterations\)$
88
^VERIFICATION FAILED$
99
--
1010
^warning: ignoring

regression/cbmc-java/exceptions2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ test.class
44
^EXIT=10$
55
^SIGNAL=0$
66
^.*assertion at file test.java line 15 function.*: FAILURE$
7-
^\*\* 1 of 5 failed \(2 iterations\)$
7+
^\*\* 1 of [0-9]* failed \(2 iterations\)$
88
^VERIFICATION FAILED$
99
--
1010
^warning: ignoring
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
38 Bytes
Binary file not shown.

regression/cbmc-java/lazyloading3/test.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ public class test
55
{
66
public static void main(C c)
77
{
8+
if(c==null)
9+
return;
810
c.a.f();
911
}
1012
}

src/analyses/goto_check.cpp

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,19 @@ class goto_checkt
6262

6363
typedef goto_functionst::goto_functiont goto_functiont;
6464

65-
void goto_check(goto_functiont &goto_function);
66-
67-
irep_idt mode;
65+
void goto_check(goto_functiont &goto_function, const irep_idt &mode);
6866

6967
protected:
7068
const namespacet &ns;
7169
local_bitvector_analysist *local_bitvector_analysis;
7270
goto_programt::const_targett t;
7371

74-
void check_rec(const exprt &expr, guardt &guard, bool address);
75-
void check(const exprt &expr);
72+
void check_rec(
73+
const exprt &expr,
74+
guardt &guard,
75+
bool address,
76+
const irep_idt &mode);
77+
void check(const exprt &expr, const irep_idt &mode);
7678

7779
void bounds_check(const index_exprt &expr, const guardt &guard);
7880
void div_by_zero_check(const div_exprt &expr, const guardt &guard);
@@ -84,7 +86,8 @@ class goto_checkt
8486
const dereference_exprt &expr,
8587
const guardt &guard,
8688
const exprt &access_lb,
87-
const exprt &access_ub);
89+
const exprt &access_ub,
90+
const irep_idt &mode);
8891
void integer_overflow_check(const exprt &expr, const guardt &guard);
8992
void conversion_check(const exprt &expr, const guardt &guard);
9093
void float_overflow_check(const exprt &expr, const guardt &guard);
@@ -993,9 +996,10 @@ void goto_checkt::pointer_validity_check(
993996
const dereference_exprt &expr,
994997
const guardt &guard,
995998
const exprt &access_lb,
996-
const exprt &access_ub)
999+
const exprt &access_ub,
1000+
const irep_idt &mode)
9971001
{
998-
if(!enable_pointer_check)
1002+
if(mode!=ID_java && !enable_pointer_check)
9991003
return;
10001004

10011005
const exprt &pointer=expr.op0();
@@ -1373,7 +1377,8 @@ Function: goto_checkt::check_rec
13731377
void goto_checkt::check_rec(
13741378
const exprt &expr,
13751379
guardt &guard,
1376-
bool address)
1380+
bool address,
1381+
const irep_idt &mode)
13771382
{
13781383
// we don't look into quantifiers
13791384
if(expr.id()==ID_exists || expr.id()==ID_forall)
@@ -1384,26 +1389,26 @@ void goto_checkt::check_rec(
13841389
if(expr.id()==ID_dereference)
13851390
{
13861391
assert(expr.operands().size()==1);
1387-
check_rec(expr.op0(), guard, false);
1392+
check_rec(expr.op0(), guard, false, mode);
13881393
}
13891394
else if(expr.id()==ID_index)
13901395
{
13911396
assert(expr.operands().size()==2);
1392-
check_rec(expr.op0(), guard, true);
1393-
check_rec(expr.op1(), guard, false);
1397+
check_rec(expr.op0(), guard, true, mode);
1398+
check_rec(expr.op1(), guard, false, mode);
13941399
}
13951400
else
13961401
{
13971402
forall_operands(it, expr)
1398-
check_rec(*it, guard, true);
1403+
check_rec(*it, guard, true, mode);
13991404
}
14001405
return;
14011406
}
14021407

14031408
if(expr.id()==ID_address_of)
14041409
{
14051410
assert(expr.operands().size()==1);
1406-
check_rec(expr.op0(), guard, true);
1411+
check_rec(expr.op0(), guard, true, mode);
14071412
return;
14081413
}
14091414
else if(expr.id()==ID_and || expr.id()==ID_or)
@@ -1420,7 +1425,7 @@ void goto_checkt::check_rec(
14201425
throw "`"+expr.id_string()+"' takes Boolean operands only, but got "+
14211426
op.pretty();
14221427

1423-
check_rec(op, guard, false);
1428+
check_rec(op, guard, false, mode);
14241429

14251430
if(expr.id()==ID_or)
14261431
guard.add(not_exprt(op));
@@ -1445,19 +1450,19 @@ void goto_checkt::check_rec(
14451450
throw msg;
14461451
}
14471452

1448-
check_rec(expr.op0(), guard, false);
1453+
check_rec(expr.op0(), guard, false, mode);
14491454

14501455
{
14511456
guardt old_guard=guard;
14521457
guard.add(expr.op0());
1453-
check_rec(expr.op1(), guard, false);
1458+
check_rec(expr.op1(), guard, false, mode);
14541459
guard.swap(old_guard);
14551460
}
14561461

14571462
{
14581463
guardt old_guard=guard;
14591464
guard.add(not_exprt(expr.op0()));
1460-
check_rec(expr.op2(), guard, false);
1465+
check_rec(expr.op2(), guard, false, mode);
14611466
guard.swap(old_guard);
14621467
}
14631468

@@ -1470,7 +1475,7 @@ void goto_checkt::check_rec(
14701475
const dereference_exprt &deref=
14711476
to_dereference_expr(member.struct_op());
14721477

1473-
check_rec(deref.op0(), guard, false);
1478+
check_rec(deref.op0(), guard, false, mode);
14741479

14751480
exprt access_ub=nil_exprt();
14761481

@@ -1480,13 +1485,13 @@ void goto_checkt::check_rec(
14801485
if(member_offset.is_not_nil() && size.is_not_nil())
14811486
access_ub=plus_exprt(member_offset, size);
14821487

1483-
pointer_validity_check(deref, guard, member_offset, access_ub);
1488+
pointer_validity_check(deref, guard, member_offset, access_ub, mode);
14841489

14851490
return;
14861491
}
14871492

14881493
forall_operands(it, expr)
1489-
check_rec(*it, guard, false);
1494+
check_rec(*it, guard, false, mode);
14901495

14911496
if(expr.id()==ID_index)
14921497
{
@@ -1545,7 +1550,8 @@ void goto_checkt::check_rec(
15451550
to_dereference_expr(expr),
15461551
guard,
15471552
nil_exprt(),
1548-
size_of_expr(expr.type(), ns));
1553+
size_of_expr(expr.type(), ns),
1554+
mode);
15491555
}
15501556

15511557
/*******************************************************************\
@@ -1560,10 +1566,10 @@ Function: goto_checkt::check
15601566
15611567
\*******************************************************************/
15621568

1563-
void goto_checkt::check(const exprt &expr)
1569+
void goto_checkt::check(const exprt &expr, const irep_idt &mode)
15641570
{
15651571
guardt guard;
1566-
check_rec(expr, guard, false);
1572+
check_rec(expr, guard, false, mode);
15671573
}
15681574

15691575
/*******************************************************************\
@@ -1574,18 +1580,14 @@ Function: goto_checkt::goto_check
15741580
15751581
Outputs:
15761582
1577-
Purpose:[B
1583+
Purpose:
15781584
15791585
\*******************************************************************/
15801586

1581-
void goto_checkt::goto_check(goto_functiont &goto_function)
1587+
void goto_checkt::goto_check(
1588+
goto_functiont &goto_function,
1589+
const irep_idt &mode)
15821590
{
1583-
{
1584-
const symbolt *init_symbol;
1585-
if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol))
1586-
mode=init_symbol->mode;
1587-
}
1588-
15891591
assertions.clear();
15901592

15911593
local_bitvector_analysist local_bitvector_analysis_obj(goto_function);
@@ -1607,7 +1609,7 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
16071609
i.is_target())
16081610
assertions.clear();
16091611

1610-
check(i.guard);
1612+
check(i.guard, mode);
16111613

16121614
// magic ERROR label?
16131615
for(const auto &label : error_labels)
@@ -1633,20 +1635,20 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
16331635

16341636
if(statement==ID_expression)
16351637
{
1636-
check(i.code);
1638+
check(i.code, mode);
16371639
}
16381640
else if(statement==ID_printf)
16391641
{
16401642
forall_operands(it, i.code)
1641-
check(*it);
1643+
check(*it, mode);
16421644
}
16431645
}
16441646
else if(i.is_assign())
16451647
{
16461648
const code_assignt &code_assign=to_code_assign(i.code);
16471649

1648-
check(code_assign.lhs());
1649-
check(code_assign.rhs());
1650+
check(code_assign.lhs(), mode);
1651+
check(code_assign.rhs(), mode);
16501652

16511653
// the LHS might invalidate any assertion
16521654
invalidate(code_assign.lhs());
@@ -1686,7 +1688,7 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
16861688
}
16871689

16881690
forall_operands(it, code_function_call)
1689-
check(*it);
1691+
check(*it, mode);
16901692

16911693
// the call might invalidate any assertion
16921694
assertions.clear();
@@ -1695,7 +1697,7 @@ void goto_checkt::goto_check(goto_functiont &goto_function)
16951697
{
16961698
if(i.code.operands().size()==1)
16971699
{
1698-
check(i.code.op0());
1700+
check(i.code.op0(), mode);
16991701
// the return value invalidate any assertion
17001702
invalidate(i.code.op0());
17011703
}
@@ -1853,7 +1855,7 @@ void goto_check(
18531855
goto_functionst::goto_functiont &goto_function)
18541856
{
18551857
goto_checkt goto_check(ns, options);
1856-
goto_check.goto_check(goto_function);
1858+
goto_check.goto_check(goto_function, irep_idt());
18571859
}
18581860

18591861
/*******************************************************************\
@@ -1877,7 +1879,8 @@ void goto_check(
18771879

18781880
Forall_goto_functions(it, goto_functions)
18791881
{
1880-
goto_check.goto_check(it->second);
1882+
irep_idt mode=ns.lookup(it->first).mode;
1883+
goto_check.goto_check(it->second, mode);
18811884
}
18821885
}
18831886

@@ -1898,10 +1901,5 @@ void goto_check(
18981901
goto_modelt &goto_model)
18991902
{
19001903
const namespacet ns(goto_model.symbol_table);
1901-
goto_checkt goto_check(ns, options);
1902-
1903-
Forall_goto_functions(it, goto_model.goto_functions)
1904-
{
1905-
goto_check.goto_check(it->second);
1906-
}
1904+
goto_check(ns, options, goto_model.goto_functions);
19071905
}

src/analyses/goto_check.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void goto_check(
3737

3838
#define HELP_GOTO_CHECK \
3939
" --bounds-check enable array bounds checks\n" \
40-
" --pointer-check enable pointer checks\n" \
40+
" --pointer-check enable pointer checks (always enabled for Java)\n" /* NOLINT(whitespace/line_length) */ \
4141
" --memory-leak-check enable memory leak checks\n" \
4242
" --div-by-zero-check enable division by zero checks\n" \
4343
" --signed-overflow-check enable signed arithmetic over- and underflow checks\n" /* NOLINT(whitespace/line_length) */ \

0 commit comments

Comments
 (0)