Skip to content

Commit 1efd6f1

Browse files
Petr BauchPetr Bauch
authored andcommitted
Symbol consistency between goto programs and symbol table
Iterate over all symbols in a goto program and for each one check that it is present in the symbol table as well. Includes a unit test for the check.
1 parent a778372 commit 1efd6f1

File tree

6 files changed

+156
-0
lines changed

6 files changed

+156
-0
lines changed

src/goto-programs/goto_function.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Date: May 2018
1616

1717
#include <iosfwd>
1818

19+
#include <util/find_symbols.h>
1920
#include <util/std_types.h>
2021

2122
#include "goto_program.h"
@@ -118,6 +119,13 @@ class goto_functiont
118119
void validate(const namespacet &ns, const validation_modet vm) const
119120
{
120121
body.validate(ns, vm);
122+
source_locationt nil_location;
123+
nil_location.make_nil();
124+
forall_subtypes(it, type)
125+
{
126+
find_typetag_in_namespace(*it, nil_location, ns, vm);
127+
}
128+
121129
validate_full_type(type, ns, vm);
122130
}
123131
};

src/goto-programs/goto_program.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include <ostream>
1515
#include <iomanip>
1616

17+
#include <util/find_symbols.h>
1718
#include <util/std_expr.h>
1819
#include <util/validate.h>
1920

@@ -676,6 +677,20 @@ void goto_programt::instructiont::validate(
676677
validate_full_code(code, ns, vm);
677678
validate_full_expr(guard, ns, vm);
678679

680+
const symbolt *symbol;
681+
DATA_CHECK_WITH_DIAGNOSTICS(
682+
!ns.lookup(function, symbol),
683+
id2string(function) + " not found",
684+
source_location);
685+
686+
auto expr_symbol_finder = [&](const exprt &e) {
687+
forall_subtypes(it, e.type())
688+
{
689+
find_typetag_in_namespace(*it, source_location, ns, vm);
690+
}
691+
find_symbol_in_namespace(e, source_location, ns, vm);
692+
};
693+
679694
switch(type)
680695
{
681696
case NO_INSTRUCTION_TYPE:
@@ -685,6 +700,7 @@ void goto_programt::instructiont::validate(
685700
case ASSUME:
686701
break;
687702
case ASSERT:
703+
guard.visit(expr_symbol_finder);
688704
break;
689705
case OTHER:
690706
break;
@@ -717,6 +733,7 @@ void goto_programt::instructiont::validate(
717733
case DEAD:
718734
break;
719735
case FUNCTION_CALL:
736+
code.visit(expr_symbol_finder);
720737
break;
721738
case THROW:
722739
break;

src/util/find_symbols.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,51 @@ void find_type_and_expr_symbols(const typet &src, find_symbols_sett &dest)
210210
{
211211
find_symbols(kindt::F_BOTH, src, dest);
212212
}
213+
214+
void find_typetag_in_namespace(
215+
const typet &src,
216+
const source_locationt &location,
217+
const namespacet &ns,
218+
const validation_modet vm)
219+
{
220+
irep_idt identifier = ID_nil;
221+
if(src.id() == ID_symbol_type)
222+
{
223+
identifier = to_symbol_type(src).get_identifier();
224+
}
225+
else if(
226+
src.id() == ID_c_enum_tag || src.id() == ID_struct_tag ||
227+
src.id() == ID_union_tag)
228+
{
229+
identifier = to_tag_type(src).get_identifier();
230+
}
231+
if(identifier != ID_nil)
232+
{
233+
const symbolt *symbol;
234+
if(location.is_nil())
235+
DATA_CHECK(
236+
!ns.lookup(identifier, symbol), id2string(identifier) + " not found");
237+
else
238+
DATA_CHECK_WITH_DIAGNOSTICS(
239+
!ns.lookup(identifier, symbol),
240+
id2string(identifier) + " not found",
241+
location);
242+
}
243+
}
244+
245+
void find_symbol_in_namespace(
246+
const exprt &src,
247+
const source_locationt &location,
248+
const namespacet &ns,
249+
const validation_modet vm)
250+
{
251+
if(src.id() == ID_symbol)
252+
{
253+
const symbolt *symbol;
254+
auto identifier = to_symbol_expr(src).get_identifier();
255+
DATA_CHECK_WITH_DIAGNOSTICS(
256+
!ns.lookup(identifier, symbol),
257+
id2string(identifier) + " not found",
258+
location);
259+
}
260+
}

src/util/find_symbols.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ Author: Daniel Kroening, [email protected]
1414
#include <unordered_set>
1515

1616
#include "irep.h"
17+
#include "namespace.h"
18+
#include "validate.h"
1719

1820
class exprt;
1921
class symbol_exprt;
2022
class typet;
23+
class symbolt;
24+
class source_locationt;
2125

2226
typedef std::unordered_set<irep_idt> find_symbols_sett;
2327

@@ -67,4 +71,16 @@ void find_type_and_expr_symbols(
6771
const exprt &src,
6872
find_symbols_sett &dest);
6973

74+
void find_typetag_in_namespace(
75+
const typet &src,
76+
const source_locationt &location,
77+
const namespacet &ns,
78+
const validation_modet vm);
79+
80+
void find_symbol_in_namespace(
81+
const exprt &src,
82+
const source_locationt &location,
83+
const namespacet &ns,
84+
const validation_modet vm);
85+
7086
#endif // CPROVER_UTIL_FIND_SYMBOLS_H

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SRC += analyses/ai/ai.cpp \
1515
analyses/does_remove_const/does_type_preserve_const_correctness.cpp \
1616
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
1717
compound_block_locations.cpp \
18+
goto-programs/goto_program_table_consistency.cpp \
1819
goto-programs/goto_trace_output.cpp \
1920
goto-symex/ssa_equation.cpp \
2021
interpreter/interpreter.cpp \
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for goto_program::validate
4+
Author: Diffblue Ltd.
5+
6+
\*******************************************************************/
7+
8+
#include <goto-programs/goto_function.h>
9+
#include <testing-utils/catch.hpp>
10+
#include <util/arith_tools.h>
11+
12+
SCENARIO(
13+
"Validation of consistent program/table pair",
14+
"[core][goto-programs][validate]")
15+
{
16+
GIVEN("A program with one assertion")
17+
{
18+
symbol_tablet symbol_table;
19+
const typet type = signedbv_typet(32);
20+
symbolt symbol;
21+
irep_idt symbol_name = "a";
22+
symbol.name = symbol_name;
23+
symbol_exprt varx(symbol_name, type);
24+
symbolt function_symbol;
25+
irep_idt function_name = "fun";
26+
function_symbol.name = function_name;
27+
28+
exprt val10 = from_integer(10, type);
29+
binary_relation_exprt x_le_10(varx, ID_le, val10);
30+
31+
goto_functiont goto_function;
32+
auto &instructions = goto_function.body.instructions;
33+
instructions.emplace_back(goto_program_instruction_typet::ASSERT);
34+
instructions.back().make_assertion(x_le_10);
35+
instructions.back().function = function_symbol.name;
36+
37+
symbol_table.insert(function_symbol);
38+
WHEN("Symbol table has the right symbol")
39+
{
40+
symbol_table.insert(symbol);
41+
const namespacet ns(symbol_table);
42+
THEN("The consistency check succeeds")
43+
{
44+
goto_function.validate(ns, validation_modet::INVARIANT);
45+
REQUIRE(true);
46+
}
47+
}
48+
WHEN("Symbol table does not have the symbol")
49+
{
50+
const namespacet ns(symbol_table);
51+
THEN("The consistency check fails")
52+
{
53+
bool caught = false;
54+
try
55+
{
56+
goto_function.validate(ns, validation_modet::EXCEPTION);
57+
}
58+
catch(incorrect_goto_program_exceptiont &e)
59+
{
60+
caught = true;
61+
}
62+
REQUIRE(caught);
63+
}
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)