Skip to content

Commit 60a833e

Browse files
Petr BauchPetr Bauch
authored andcommitted
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

File tree

8 files changed

+126
-1
lines changed

8 files changed

+126
-1
lines changed

src/goto-programs/goto_program.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, kroening@kroening.com
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 5 additions & 0 deletions
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

Lines changed: 6 additions & 0 deletions
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

Lines changed: 6 additions & 0 deletions
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 7 additions & 0 deletions
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")
Lines changed: 75 additions & 0 deletions
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)