Skip to content

Commit 9262c73

Browse files
committed
Refactor error handling of function pointer restriction
1 parent 31916dc commit 9262c73

File tree

3 files changed

+147
-94
lines changed

3 files changed

+147
-94
lines changed

src/goto-programs/restrict_function_pointers.cpp

Lines changed: 124 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -20,66 +20,6 @@ Author: Diffblue Ltd.
2020

2121
namespace
2222
{
23-
void typecheck_function_pointer_restrictions(
24-
const goto_modelt &goto_model,
25-
const function_pointer_restrictionst &restrictions)
26-
{
27-
const std::string options =
28-
"--" RESTRICT_FUNCTION_POINTER_OPT "/"
29-
"--" RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT "/"
30-
"--" RESTRICT_FUNCTION_POINTER_BY_NAME_OPT;
31-
32-
for(auto const &restriction : restrictions.restrictions)
33-
{
34-
auto const function_pointer_sym =
35-
goto_model.symbol_table.lookup(restriction.first);
36-
if(function_pointer_sym == nullptr)
37-
{
38-
throw invalid_command_line_argument_exceptiont{
39-
id2string(restriction.first) + " not found in the symbol table",
40-
options};
41-
}
42-
auto const &function_pointer_type = function_pointer_sym->type;
43-
if(function_pointer_type.id() != ID_pointer)
44-
{
45-
throw invalid_command_line_argument_exceptiont{
46-
"not a function pointer: " + id2string(restriction.first),
47-
options};
48-
}
49-
auto const &function_type =
50-
to_pointer_type(function_pointer_type).subtype();
51-
if(function_type.id() != ID_code)
52-
{
53-
throw invalid_command_line_argument_exceptiont{
54-
"not a function pointer: " + id2string(restriction.first),
55-
options};
56-
}
57-
auto const &ns = namespacet{goto_model.symbol_table};
58-
for(auto const &function_pointer_target : restriction.second)
59-
{
60-
auto const function_pointer_target_sym =
61-
goto_model.symbol_table.lookup(function_pointer_target);
62-
if(function_pointer_target_sym == nullptr)
63-
{
64-
throw invalid_command_line_argument_exceptiont{
65-
"symbol not found: " + id2string(function_pointer_target),
66-
options};
67-
}
68-
auto const &function_pointer_target_type =
69-
function_pointer_target_sym->type;
70-
if(function_type != function_pointer_target_type)
71-
{
72-
throw invalid_command_line_argument_exceptiont{
73-
"type mismatch: `" + id2string(restriction.first) + "' points to `" +
74-
type2c(function_type, ns) + "', but restriction `" +
75-
id2string(function_pointer_target) + "' has type `" +
76-
type2c(function_pointer_target_type, ns) + "'",
77-
options};
78-
}
79-
}
80-
}
81-
}
82-
8323
source_locationt make_function_pointer_restriction_assertion_source_location(
8424
source_locationt source_location,
8525
const function_pointer_restrictionst::restrictiont restriction)
@@ -200,12 +140,83 @@ void restrict_function_pointer(
200140
}
201141
} // namespace
202142

143+
function_pointer_restrictionst::invalid_restriction_exceptiont::
144+
invalid_restriction_exceptiont(std::string reason, std::string correct_format)
145+
: reason(std::move(reason)), correct_format(std::move(correct_format))
146+
{
147+
148+
}
149+
150+
std::string
151+
function_pointer_restrictionst::invalid_restriction_exceptiont::what() const
152+
{
153+
std::string res;
154+
155+
res += "Invalid restriction";
156+
res += "\nReason: " + reason;
157+
158+
if(!correct_format.empty())
159+
{
160+
res += "\nFormat: " + correct_format;
161+
}
162+
163+
return res;
164+
}
165+
166+
void function_pointer_restrictionst::typecheck_function_pointer_restrictions(
167+
const goto_modelt &goto_model,
168+
const function_pointer_restrictionst::restrictionst &restrictions)
169+
{
170+
for(auto const &restriction : restrictions)
171+
{
172+
auto const function_pointer_sym =
173+
goto_model.symbol_table.lookup(restriction.first);
174+
if(function_pointer_sym == nullptr)
175+
{
176+
throw invalid_restriction_exceptiont{
177+
id2string(restriction.first) + " not found in the symbol table"};
178+
}
179+
auto const &function_pointer_type = function_pointer_sym->type;
180+
if(function_pointer_type.id() != ID_pointer)
181+
{
182+
throw invalid_restriction_exceptiont{
183+
"not a function pointer: " + id2string(restriction.first)};
184+
}
185+
auto const &function_type =
186+
to_pointer_type(function_pointer_type).subtype();
187+
if(function_type.id() != ID_code)
188+
{
189+
throw invalid_restriction_exceptiont{
190+
"not a function pointer: " + id2string(restriction.first)};
191+
}
192+
auto const &ns = namespacet{goto_model.symbol_table};
193+
for(auto const &function_pointer_target : restriction.second)
194+
{
195+
auto const function_pointer_target_sym =
196+
goto_model.symbol_table.lookup(function_pointer_target);
197+
if(function_pointer_target_sym == nullptr)
198+
{
199+
throw invalid_restriction_exceptiont{
200+
"symbol not found: " + id2string(function_pointer_target)};
201+
}
202+
auto const &function_pointer_target_type =
203+
function_pointer_target_sym->type;
204+
if(function_type != function_pointer_target_type)
205+
{
206+
throw invalid_restriction_exceptiont{
207+
"type mismatch: `" + id2string(restriction.first) + "' points to `" +
208+
type2c(function_type, ns) + "', but restriction `" +
209+
id2string(function_pointer_target) + "' has type `" +
210+
type2c(function_pointer_target_type, ns) + "'"};
211+
}
212+
}
213+
}
214+
}
215+
203216
void restrict_function_pointers(
204217
goto_modelt &goto_model,
205218
const function_pointer_restrictionst &restrictions)
206219
{
207-
typecheck_function_pointer_restrictions(goto_model, restrictions);
208-
209220
for(auto &function_item : goto_model.goto_functions.function_map)
210221
{
211222
goto_functiont &goto_function = function_item.second;
@@ -283,10 +294,9 @@ function_pointer_restrictionst::parse_function_pointer_restrictions(
283294

284295
if(!inserted)
285296
{
286-
throw invalid_command_line_argument_exceptiont{
297+
throw invalid_restriction_exceptiont{
287298
"function pointer restriction for `" + id2string(restriction.first) +
288-
"' was specified twice",
289-
option};
299+
"' was specified twice"};
290300
}
291301
}
292302

@@ -335,25 +345,22 @@ function_pointer_restrictionst::parse_function_pointer_restriction(
335345

336346
if(pointer_name_end == std::string::npos)
337347
{
338-
throw invalid_command_line_argument_exceptiont{
348+
throw invalid_restriction_exceptiont{
339349
"couldn't find '/' in `" + restriction_opt + "'",
340-
option,
341350
restriction_format_message};
342351
}
343352

344353
if(pointer_name_end == restriction_opt.size())
345354
{
346-
throw invalid_command_line_argument_exceptiont{
355+
throw invalid_restriction_exceptiont{
347356
"couldn't find names of targets after '/' in `" + restriction_opt + "'",
348-
option,
349357
restriction_format_message};
350358
}
351359

352360
if(pointer_name_end == 0)
353361
{
354-
throw invalid_command_line_argument_exceptiont{
355-
"couldn't find target name before '/' in `" + restriction_opt + "'",
356-
option};
362+
throw invalid_restriction_exceptiont{
363+
"couldn't find target name before '/' in `" + restriction_opt + "'"};
357364
}
358365

359366
auto const pointer_name = restriction_opt.substr(0, pointer_name_end);
@@ -363,9 +370,8 @@ function_pointer_restrictionst::parse_function_pointer_restriction(
363370

364371
if(target_name_strings.size() == 1 && target_name_strings[0].empty())
365372
{
366-
throw invalid_command_line_argument_exceptiont{
373+
throw invalid_restriction_exceptiont{
367374
"missing target list for function pointer restriction " + pointer_name,
368-
option,
369375
restriction_format_message};
370376
}
371377

@@ -376,9 +382,8 @@ function_pointer_restrictionst::parse_function_pointer_restriction(
376382
{
377383
if(target_name == ID_empty_string)
378384
{
379-
throw invalid_command_line_argument_exceptiont(
385+
throw invalid_restriction_exceptiont(
380386
"leading or trailing comma in restrictions for `" + pointer_name + "'",
381-
option,
382387
restriction_format_message);
383388
}
384389
}
@@ -436,18 +441,49 @@ function_pointer_restrictionst function_pointer_restrictionst::from_options(
436441
{
437442
auto const restriction_opts =
438443
options.get_list_option(RESTRICT_FUNCTION_POINTER_OPT);
439-
auto const commandline_restrictions =
440-
parse_function_pointer_restrictions_from_command_line(restriction_opts);
441-
442-
auto const restriction_file_opts =
443-
options.get_list_option(RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT);
444-
auto const file_restrictions = parse_function_pointer_restrictions_from_file(
445-
restriction_file_opts, message_handler);
446-
447-
auto const restriction_name_opts =
448-
options.get_list_option(RESTRICT_FUNCTION_POINTER_BY_NAME_OPT);
449-
auto const name_restrictions = get_function_pointer_by_name_restrictions(
450-
restriction_name_opts, goto_model);
444+
445+
restrictionst commandline_restrictions;
446+
try
447+
{
448+
commandline_restrictions =
449+
parse_function_pointer_restrictions_from_command_line(restriction_opts);
450+
typecheck_function_pointer_restrictions(
451+
goto_model, commandline_restrictions);
452+
}
453+
catch(const invalid_restriction_exceptiont &e)
454+
{
455+
throw invalid_command_line_argument_exceptiont{
456+
e.reason, "--" RESTRICT_FUNCTION_POINTER_OPT, e.correct_format};
457+
}
458+
459+
restrictionst file_restrictions;
460+
try
461+
{
462+
auto const restriction_file_opts =
463+
options.get_list_option(RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT);
464+
file_restrictions = parse_function_pointer_restrictions_from_file(
465+
restriction_file_opts, message_handler);
466+
typecheck_function_pointer_restrictions(goto_model, file_restrictions);
467+
}
468+
catch(const invalid_restriction_exceptiont &e)
469+
{
470+
throw deserialization_exceptiont{e.what()};
471+
}
472+
473+
restrictionst name_restrictions;
474+
try
475+
{
476+
auto const restriction_name_opts =
477+
options.get_list_option(RESTRICT_FUNCTION_POINTER_BY_NAME_OPT);
478+
name_restrictions = get_function_pointer_by_name_restrictions(
479+
restriction_name_opts, goto_model);
480+
typecheck_function_pointer_restrictions(goto_model, name_restrictions);
481+
}
482+
catch(const invalid_restriction_exceptiont &e)
483+
{
484+
throw invalid_command_line_argument_exceptiont{
485+
e.reason, "--" RESTRICT_FUNCTION_POINTER_BY_NAME_OPT, e.correct_format};
486+
}
451487

452488
return {merge_function_pointer_restrictions(
453489
commandline_restrictions,

src/goto-programs/restrict_function_pointers.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,23 @@ class function_pointer_restrictionst
8282
void write_to_file(const std::string &filename) const;
8383

8484
protected:
85+
class invalid_restriction_exceptiont : public cprover_exception_baset
86+
{
87+
public:
88+
explicit invalid_restriction_exceptiont(
89+
std::string reason,
90+
std::string correct_format = "");
91+
92+
std::string what() const override;
93+
94+
std::string reason;
95+
std::string correct_format;
96+
};
97+
98+
static void typecheck_function_pointer_restrictions(
99+
const goto_modelt &goto_model,
100+
const restrictionst &restrictions);
101+
85102
static restrictionst merge_function_pointer_restrictions(
86103
restrictionst lhs,
87104
const restrictionst &rhs);

unit/goto-programs/restrict_function_pointers.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,29 @@ void restriction_parsing_test()
4545

4646
REQUIRE_THROWS_AS(
4747
fp_restrictionst::parse_function_pointer_restriction("func", "test"),
48-
invalid_command_line_argument_exceptiont);
48+
fp_restrictionst::invalid_restriction_exceptiont);
4949

5050
REQUIRE_THROWS_AS(
5151
fp_restrictionst::parse_function_pointer_restriction("/func", "test"),
52-
invalid_command_line_argument_exceptiont);
52+
fp_restrictionst::invalid_restriction_exceptiont);
5353

5454
REQUIRE_THROWS_AS(
5555
fp_restrictionst::parse_function_pointer_restriction("func/", "test"),
56-
invalid_command_line_argument_exceptiont);
56+
fp_restrictionst::invalid_restriction_exceptiont);
5757

5858
REQUIRE_THROWS_AS(
5959
fp_restrictionst::parse_function_pointer_restriction("func/,", "test"),
60-
invalid_command_line_argument_exceptiont);
60+
fp_restrictionst::invalid_restriction_exceptiont);
6161

6262
REQUIRE_THROWS_AS(
6363
fp_restrictionst::parse_function_pointer_restriction(
6464
"func1/func2,", "test"),
65-
invalid_command_line_argument_exceptiont);
65+
fp_restrictionst::invalid_restriction_exceptiont);
6666

6767
REQUIRE_THROWS_AS(
6868
fp_restrictionst::parse_function_pointer_restriction(
6969
"func1/,func2", "test"),
70-
invalid_command_line_argument_exceptiont);
70+
fp_restrictionst::invalid_restriction_exceptiont);
7171
}
7272

7373
void merge_restrictions_test()

0 commit comments

Comments
 (0)