Skip to content

Commit 60a833e

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Program table symbol type consistency
Look up the symbol id in symbol table and call base_type_eq on every symbol expression in guard and code whenever relevant. Includes a unit test. Also fixes unit tests that these new checks brake.
1 parent a0289a7 commit 60a833e

8 files changed

+126
-1
lines changed

src/goto-programs/goto_program.cpp

+24
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/expr_iterator.h>
1718
#include <util/find_symbols.h>
1819
#include <util/std_expr.h>
1920
#include <util/validate.h>
@@ -699,6 +700,25 @@ void goto_programt::instructiont::validate(
699700
}
700701
};
701702

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+
};
721+
702722
switch(type)
703723
{
704724
case NO_INSTRUCTION_TYPE:
@@ -729,7 +749,9 @@ void goto_programt::instructiont::validate(
729749
targets.empty(),
730750
"assert instruction should not have a target",
731751
source_location);
752+
732753
std::for_each(guard.depth_begin(), guard.depth_end(), expr_symbol_finder);
754+
std::for_each(guard.depth_begin(), guard.depth_end(), type_finder);
733755
break;
734756
case OTHER:
735757
break;
@@ -794,7 +816,9 @@ void goto_programt::instructiont::validate(
794816
code.get_statement() == ID_function_call,
795817
"function call instruction should contain a call statement",
796818
source_location);
819+
797820
std::for_each(code.depth_begin(), code.depth_end(), expr_symbol_finder);
821+
std::for_each(code.depth_begin(), code.depth_end(), type_finder);
798822
break;
799823
case THROW:
800824
break;

unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ SRC += analyses/ai/ai.cpp \
2121
goto-programs/goto_program_declaration.cpp \
2222
goto-programs/goto_program_function_call.cpp \
2323
goto-programs/goto_program_goto_target.cpp \
24+
goto-programs/goto_program_symbol_type_table_consistency.cpp \
2425
goto-programs/goto_program_table_consistency.cpp \
2526
goto-programs/goto_trace_output.cpp \
2627
goto-symex/ssa_equation.cpp \

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)