Skip to content

Commit 55029d6

Browse files
authored
Merge pull request #3118 from xbauch/program_table_identifier_consistency
Consistency between goto programs and symbol table
2 parents 9d5497d + 60a833e commit 55029d6

12 files changed

+307
-1
lines changed

src/goto-programs/goto_function.h

+13
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,18 @@ class goto_functiont
118119
void validate(const namespacet &ns, const validation_modet vm) const
119120
{
120121
body.validate(ns, vm);
122+
123+
find_symbols_sett typetags;
124+
find_type_symbols(type, typetags);
125+
const symbolt *symbol;
126+
for(const auto &identifier : typetags)
127+
{
128+
DATA_CHECK(
129+
vm,
130+
!ns.lookup(identifier, symbol),
131+
id2string(identifier) + " not found");
132+
}
133+
121134
validate_full_type(type, ns, vm);
122135
}
123136
};

src/goto-programs/goto_functions.h

+9
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ class goto_functionst
127127
for(const auto &entry : function_map)
128128
{
129129
const goto_functiont &goto_function = entry.second;
130+
const auto &function_name = entry.first;
131+
132+
DATA_CHECK(
133+
vm,
134+
goto_function.type == ns.lookup(function_name).type,
135+
id2string(function_name) + " type inconsistency\ngoto program type: " +
136+
goto_function.type.id_string() +
137+
"\nsymbol table type: " + ns.lookup(function_name).type.id_string());
138+
130139
goto_function.validate(ns, vm);
131140
}
132141
}

src/goto-programs/goto_program.cpp

+47
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Author: Daniel Kroening, [email protected]
1414
#include <ostream>
1515
#include <iomanip>
1616

17+
#include <util/expr_iterator.h>
18+
#include <util/find_symbols.h>
1719
#include <util/std_expr.h>
1820
#include <util/validate.h>
1921

@@ -677,6 +679,45 @@ void goto_programt::instructiont::validate(
677679
validate_full_expr(guard, ns, vm);
678680

679681
const symbolt *table_symbol;
682+
DATA_CHECK_WITH_DIAGNOSTICS(
683+
vm,
684+
!ns.lookup(function, table_symbol),
685+
id2string(function) + " not found",
686+
source_location);
687+
688+
auto expr_symbol_finder = [&](const exprt &e) {
689+
find_symbols_sett typetags;
690+
find_type_symbols(e.type(), typetags);
691+
find_symbols(e, typetags);
692+
const symbolt *symbol;
693+
for(const auto &identifier : typetags)
694+
{
695+
DATA_CHECK_WITH_DIAGNOSTICS(
696+
vm,
697+
!ns.lookup(identifier, symbol),
698+
id2string(identifier) + " not found",
699+
source_location);
700+
}
701+
};
702+
703+
auto &current_source_location = source_location;
704+
auto type_finder =
705+
[&ns, vm, &table_symbol, &current_source_location](const exprt &e) {
706+
if(e.id() == ID_symbol)
707+
{
708+
const auto &goto_symbol_expr = to_symbol_expr(e);
709+
const auto &goto_id = goto_symbol_expr.get_identifier();
710+
711+
if(!ns.lookup(goto_id, table_symbol))
712+
DATA_CHECK_WITH_DIAGNOSTICS(
713+
vm,
714+
base_type_eq(goto_symbol_expr.type(), table_symbol->type, ns),
715+
id2string(goto_id) + " type inconsistency\n" +
716+
"goto program type: " + goto_symbol_expr.type().id_string() +
717+
"\n" + "symbol table type: " + table_symbol->type.id_string(),
718+
current_source_location);
719+
}
720+
};
680721

681722
switch(type)
682723
{
@@ -708,6 +749,9 @@ void goto_programt::instructiont::validate(
708749
targets.empty(),
709750
"assert instruction should not have a target",
710751
source_location);
752+
753+
std::for_each(guard.depth_begin(), guard.depth_end(), expr_symbol_finder);
754+
std::for_each(guard.depth_begin(), guard.depth_end(), type_finder);
711755
break;
712756
case OTHER:
713757
break;
@@ -772,6 +816,9 @@ void goto_programt::instructiont::validate(
772816
code.get_statement() == ID_function_call,
773817
"function call instruction should contain a call statement",
774818
source_location);
819+
820+
std::for_each(code.depth_begin(), code.depth_end(), expr_symbol_finder);
821+
std::for_each(code.depth_begin(), code.depth_end(), type_finder);
775822
break;
776823
case THROW:
777824
break;

unit/Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@ 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_model_function_type_consistency.cpp \
1819
goto-programs/goto_program_assume.cpp \
1920
goto-programs/goto_program_dead.cpp \
2021
goto-programs/goto_program_declaration.cpp \
2122
goto-programs/goto_program_function_call.cpp \
2223
goto-programs/goto_program_goto_target.cpp \
24+
goto-programs/goto_program_symbol_type_table_consistency.cpp \
25+
goto-programs/goto_program_table_consistency.cpp \
2326
goto-programs/goto_trace_output.cpp \
2427
goto-symex/ssa_equation.cpp \
2528
interpreter/interpreter.cpp \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for goto_model::validate
4+
5+
Author: Diffblue Ltd.
6+
7+
\*******************************************************************/
8+
9+
#include <goto-programs/goto_model.h>
10+
#include <testing-utils/catch.hpp>
11+
#include <util/arith_tools.h>
12+
13+
SCENARIO(
14+
"Validation of consistent program/table pair (function type)",
15+
"[core][goto-programs][validate]")
16+
{
17+
GIVEN("A model with one function")
18+
{
19+
const typet type1 = signedbv_typet(32);
20+
const typet type2 = signedbv_typet(64);
21+
code_typet fun_type1({}, type1);
22+
code_typet fun_type2({}, type2);
23+
24+
symbolt function_symbol;
25+
irep_idt function_symbol_name = "foo";
26+
function_symbol.name = function_symbol_name;
27+
28+
goto_modelt goto_model;
29+
goto_model.goto_functions.function_map[function_symbol.name] =
30+
goto_functiont();
31+
goto_model.goto_functions.function_map[function_symbol.name].type =
32+
fun_type1;
33+
34+
WHEN("Symbol table has the right type")
35+
{
36+
function_symbol.type = fun_type1;
37+
goto_model.symbol_table.insert(function_symbol);
38+
39+
THEN("The consistency check succeeds")
40+
{
41+
goto_model.validate(validation_modet::INVARIANT);
42+
43+
REQUIRE(true);
44+
}
45+
}
46+
47+
WHEN("Symbol table has the wrong type")
48+
{
49+
function_symbol.type = fun_type2;
50+
goto_model.symbol_table.insert(function_symbol);
51+
52+
THEN("The consistency check fails")
53+
{
54+
bool caught = false;
55+
try
56+
{
57+
goto_model.validate(validation_modet::EXCEPTION);
58+
}
59+
catch(incorrect_goto_program_exceptiont &e)
60+
{
61+
caught = true;
62+
}
63+
REQUIRE(caught);
64+
}
65+
}
66+
}
67+
}

unit/goto-programs/goto_program_assume.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ SCENARIO(
1919
symbol_tablet symbol_table;
2020
const typet type1 = signedbv_typet(32);
2121
symbolt symbol;
22+
symbolt fun_symbol;
23+
irep_idt fun_name = "foo";
24+
fun_symbol.name = fun_name;
2225
irep_idt symbol_name = "a";
2326
symbol.name = symbol_name;
2427
symbol_exprt varx(symbol_name, type1);
@@ -31,8 +34,10 @@ SCENARIO(
3134

3235
symbol.type = type1;
3336
symbol_table.insert(symbol);
37+
symbol_table.insert(fun_symbol);
3438
namespacet ns(symbol_table);
3539
instructions.back().make_assertion(x_le_10);
40+
instructions.back().function = fun_name;
3641

3742
WHEN("Instruction has no targets")
3843
{

unit/goto-programs/goto_program_dead.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ SCENARIO(
1919
symbol_tablet symbol_table;
2020
const signedbv_typet type1(32);
2121

22+
symbolt fun_symbol;
23+
irep_idt fun_name = "foo";
24+
fun_symbol.name = fun_name;
25+
2226
symbolt var_symbol;
2327
irep_idt var_symbol_name = "a";
2428
var_symbol.type = type1;
@@ -31,6 +35,8 @@ SCENARIO(
3135
code_deadt removal(var_a);
3236
instructions.back().make_dead();
3337
instructions.back().code = removal;
38+
instructions.back().function = fun_name;
39+
symbol_table.insert(fun_symbol);
3440

3541
WHEN("Removing known symbol")
3642
{

unit/goto-programs/goto_program_declaration.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ SCENARIO(
1919
symbol_tablet symbol_table;
2020
const signedbv_typet type1(32);
2121

22+
symbolt fun_symbol;
23+
irep_idt fun_name = "foo";
24+
fun_symbol.name = fun_name;
25+
2226
symbolt var_symbol;
2327
irep_idt var_symbol_name = "a";
2428
var_symbol.type = type1;
@@ -30,6 +34,8 @@ SCENARIO(
3034
instructions.emplace_back(goto_program_instruction_typet::DECL);
3135
code_declt declaration(var_a);
3236
instructions.back().make_decl(declaration);
37+
instructions.back().function = fun_name;
38+
symbol_table.insert(fun_symbol);
3339

3440
WHEN("Declaring known symbol")
3541
{

unit/goto-programs/goto_program_function_call.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,16 @@ SCENARIO(
3434
symbolt fun_symbol;
3535
irep_idt fun_symbol_name = "foo";
3636
fun_symbol.name = fun_symbol_name;
37+
fun_symbol.type = code_type;
3738
symbol_exprt fun_foo(fun_symbol_name, code_type);
3839

3940
goto_functiont goto_function;
4041
auto &instructions = goto_function.body.instructions;
4142
instructions.emplace_back(goto_program_instruction_typet::FUNCTION_CALL);
43+
instructions.back().function = fun_symbol_name;
4244

4345
var_symbol.type = type1;
4446
var_symbol2.type = type2;
45-
fun_symbol.type = type1;
4647
symbol_table.insert(var_symbol);
4748
symbol_table.insert(var_symbol2);
4849
symbol_table.insert(fun_symbol);

unit/goto-programs/goto_program_goto_target.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ SCENARIO(
1818
{
1919
symbol_tablet symbol_table;
2020
const typet type1 = signedbv_typet(32);
21+
symbolt fun_symbol;
22+
irep_idt fun_name = "foo";
23+
fun_symbol.name = fun_name;
24+
2125
symbolt symbol;
2226
irep_idt symbol_name = "a";
2327
symbol.name = symbol_name;
@@ -29,12 +33,15 @@ SCENARIO(
2933
auto &instructions = goto_function.body.instructions;
3034
instructions.emplace_back(goto_program_instruction_typet::ASSERT);
3135
instructions.back().make_assertion(x_le_10);
36+
instructions.back().function = fun_name;
3237

3338
instructions.emplace_back(goto_program_instruction_typet::GOTO);
3439
instructions.back().make_goto(instructions.begin());
40+
instructions.back().function = fun_name;
3541

3642
symbol.type = type1;
3743
symbol_table.insert(symbol);
44+
symbol_table.insert(fun_symbol);
3845
namespacet ns(symbol_table);
3946

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

0 commit comments

Comments
 (0)