Skip to content

Commit a3ebc2c

Browse files
WIP file interface and refactor
1 parent 55c88ae commit a3ebc2c

File tree

3 files changed

+178
-18
lines changed

3 files changed

+178
-18
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,7 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
138138
cbmc_parse_optionst::set_default_options(options);
139139
parse_c_object_factory_options(cmdline, options);
140140

141-
options.set_option(
142-
RESTRICT_FUNCTION_POINTER_OPT,
143-
cmdline.get_values(RESTRICT_FUNCTION_POINTER_OPT));
141+
parse_function_pointer_restriction_options_from_cmdline(cmdline, options);
144142

145143
if(cmdline.isset("function"))
146144
options.set_option("function", cmdline.get_value("function"));
@@ -843,7 +841,7 @@ bool cbmc_parse_optionst::process_goto_program(
843841
<< messaget::eom;
844842

845843
const auto function_pointer_restrictions =
846-
function_pointer_restrictionst::from_options(options);
844+
function_pointer_restrictionst::from_options(options, log.get_message_handler());
847845
if(!function_pointer_restrictions.restrictions.empty()) {
848846
label_function_pointer_call_sites(goto_model);
849847
restrict_function_pointers(

src/goto-programs/restrict_function_pointers.cpp

Lines changed: 148 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@ Author: Diffblue Ltd.
99
#include "restrict_function_pointers.h"
1010

1111
#include <ansi-c/expr2c.h>
12+
#include <json/json_parser.h>
1213
#include <util/expr_iterator.h>
1314
#include <util/string_utils.h>
1415

16+
#include <algorithm>
17+
#include <fstream>
18+
#include <iostream>
19+
1520
namespace
1621
{
1722
void typecheck_function_pointer_restrictions(
@@ -77,7 +82,7 @@ source_locationt make_function_pointer_restriction_assertion_source_location(
7782
<< " must be ";
7883
if(restriction.second.size() == 1)
7984
{
80-
comment << restriction.second.front();
85+
comment << *restriction.second.begin();
8186
}
8287
else
8388
{
@@ -197,13 +202,46 @@ void restrict_function_pointers(
197202
}
198203
}
199204

200-
function_pointer_restrictionst
201-
function_pointer_restrictionst::from_options(const optionst &options)
205+
void parse_function_pointer_restriction_options_from_cmdline(
206+
const cmdlinet &cmdline,
207+
optionst &options)
208+
{
209+
options.set_option(
210+
RESTRICT_FUNCTION_POINTER_OPT,
211+
cmdline.get_values(RESTRICT_FUNCTION_POINTER_OPT));
212+
options.set_option(
213+
RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT,
214+
cmdline.get_values(RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT));
215+
}
216+
217+
namespace
218+
{
219+
function_pointer_restrictionst::restrictionst
220+
merge_function_pointer_restrictions(
221+
const function_pointer_restrictionst::restrictionst &lhs,
222+
const function_pointer_restrictionst::restrictionst &rhs)
223+
{
224+
auto result = lhs;
225+
for(auto const &restriction : rhs)
226+
{
227+
auto emplace_result = result.emplace(restriction.first, restriction.second);
228+
if(!emplace_result.second)
229+
{
230+
for(auto const &target : restriction.second)
231+
{
232+
emplace_result.first->second.insert(target);
233+
}
234+
}
235+
}
236+
return result;
237+
}
238+
239+
function_pointer_restrictionst::restrictionst
240+
parse_function_pointer_restrictions_from_command_line(
241+
const std::list<std::string> &restriction_opts)
202242
{
203243
auto function_pointer_restrictions =
204-
std::unordered_map<irep_idt, std::vector<irep_idt>>{};
205-
auto const restriction_opts =
206-
options.get_list_option(RESTRICT_FUNCTION_POINTER_OPT);
244+
function_pointer_restrictionst::restrictionst{};
207245
for(auto const &restriction_opt : restriction_opts)
208246
{
209247
// the format for restrictions is <pointer_name>/<target[,more_targets]*>
@@ -244,11 +282,11 @@ function_pointer_restrictionst::from_options(const optionst &options)
244282
restriction_format_message};
245283
}
246284
auto const target_names = ([&target_name_strings] {
247-
auto target_names = std::vector<irep_idt>(target_name_strings.size());
285+
auto target_names = std::unordered_set<irep_idt>{};
248286
std::transform(
249287
target_name_strings.begin(),
250288
target_name_strings.end(),
251-
target_names.begin(),
289+
std::inserter(target_names, target_names.end()),
252290
string2id);
253291
return target_names;
254292
})();
@@ -273,5 +311,106 @@ function_pointer_restrictionst::from_options(const optionst &options)
273311
"--" RESTRICT_FUNCTION_POINTER_OPT};
274312
};
275313
}
276-
return {function_pointer_restrictions};
314+
return function_pointer_restrictions;
315+
}
316+
317+
function_pointer_restrictionst::restrictionst
318+
parse_function_pointer_restrictions_from_file(
319+
const std::list<std::string> &filenames,
320+
message_handlert &message_handler)
321+
{
322+
auto merged_restrictions = function_pointer_restrictionst::restrictionst{};
323+
for(auto const &filename : filenames)
324+
{
325+
auto const restrictions =
326+
function_pointer_restrictionst::read_from_file(filename, message_handler);
327+
merged_restrictions = merge_function_pointer_restrictions(
328+
merged_restrictions, restrictions.restrictions);
329+
}
330+
return merged_restrictions;
331+
}
332+
} // namespace
333+
334+
function_pointer_restrictionst function_pointer_restrictionst::from_options(
335+
const optionst &options,
336+
message_handlert &message_handler)
337+
{
338+
auto const restriction_opts =
339+
options.get_list_option(RESTRICT_FUNCTION_POINTER_OPT);
340+
auto const commandline_restrictions =
341+
parse_function_pointer_restrictions_from_command_line(restriction_opts);
342+
auto const file_restrictions = parse_function_pointer_restrictions_from_file(
343+
options.get_list_option(RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT),
344+
message_handler);
345+
return {merge_function_pointer_restrictions(
346+
file_restrictions, commandline_restrictions)};
347+
}
348+
349+
function_pointer_restrictionst function_pointer_restrictionst::read_from_file(
350+
const std::string &filename,
351+
message_handlert &message_handler)
352+
{
353+
auto failed = [](bool failFlag) { return failFlag; };
354+
function_pointer_restrictionst::restrictionst restrictions;
355+
auto inFile = std::ifstream{filename};
356+
jsont json;
357+
if(failed(parse_json(inFile, filename, message_handler, json)))
358+
{
359+
throw system_exceptiont{
360+
"failed to read function pointer restrictions from " + filename};
361+
}
362+
if(!json.is_object())
363+
{
364+
throw system_exceptiont{"top level item is not an object"};
365+
}
366+
for(auto const &kv_pair : to_json_object(json))
367+
{
368+
restrictions.emplace(irep_idt{kv_pair.first}, [&] {
369+
if(!kv_pair.second.is_array())
370+
{
371+
throw system_exceptiont{"In " + filename + ", value of " +
372+
kv_pair.first + " is not an array"};
373+
}
374+
auto possible_targets = std::unordered_set<irep_idt>{};
375+
auto const &array = to_json_array(kv_pair.second);
376+
std::transform(
377+
array.begin(),
378+
array.end(),
379+
std::inserter(possible_targets, possible_targets.end()),
380+
[&](const jsont &array_element) {
381+
if(!array_element.is_string())
382+
{
383+
throw system_exceptiont{"In " + filename + ", value of " +
384+
kv_pair.first +
385+
"contains a non-string array element"};
386+
}
387+
return irep_idt{to_json_string(array_element).value};
388+
});
389+
return possible_targets;
390+
}());
391+
}
392+
return function_pointer_restrictionst{restrictions};
393+
}
394+
void function_pointer_restrictionst::write_to_file(
395+
const std::string &filename) const
396+
{
397+
auto function_pointer_restrictions_json = jsont{};
398+
auto &restrictions_json_object =
399+
function_pointer_restrictions_json.make_object();
400+
for(auto const &restriction : restrictions)
401+
{
402+
auto &targets_array =
403+
restrictions_json_object[id2string(restriction.first)].make_array();
404+
for(auto const &target : restriction.second)
405+
{
406+
targets_array.push_back(json_stringt{target});
407+
}
408+
}
409+
auto outFile = std::ofstream{filename};
410+
if(!outFile)
411+
{
412+
throw system_exceptiont{"cannot open " + filename +
413+
" for writing function pointer restrictions"};
414+
}
415+
function_pointer_restrictions_json.output(outFile);
277416
}

src/goto-programs/restrict_function_pointers.h

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Author: Diffblue Ltd.
1717
#ifndef CPROVER_GOTO_PROGRAMS_RESTRICT_FUNCTION_POINTERS_H
1818
#define CPROVER_GOTO_PROGRAMS_RESTRICT_FUNCTION_POINTERS_H
1919

20-
#include <vector>
20+
#include <unordered_map>
21+
#include <unordered_set>
2122

2223
#include <util/cmdline.h>
2324
#include <util/irep.h>
@@ -26,27 +27,49 @@ Author: Diffblue Ltd.
2627
#include <util/options.h>
2728

2829
#define RESTRICT_FUNCTION_POINTER_OPT "restrict-function-pointer"
29-
#define OPT_RESTRICT_FUNCTION_POINTER "(" RESTRICT_FUNCTION_POINTER_OPT "):"
30+
#define RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT \
31+
"function-pointer-restrictions-file"
32+
33+
#define OPT_RESTRICT_FUNCTION_POINTER \
34+
"(" RESTRICT_FUNCTION_POINTER_OPT \
35+
"):" \
36+
"(" RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT "):"
3037

3138
#define RESTRICT_FUNCTION_POINTER_HELP \
3239
"--" RESTRICT_FUNCTION_POINTER_OPT \
3340
" <pointer_name>/<target[,targets]*>\n" \
3441
" restrict a function pointer to a set of possible targets\n" \
3542
" targets must all exist in the symbol table with a matching " \
3643
"type\n" \
37-
" works for globals and function parameters right now\n"
44+
" works for globals and function parameters right now\n" \
45+
"--" RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT \
46+
" <file_name>\n" \
47+
" add from function pointer restrictions from file"
48+
49+
void parse_function_pointer_restriction_options_from_cmdline(
50+
const cmdlinet &cmdline,
51+
optionst &options);
3852

53+
class message_handlert;
3954
struct function_pointer_restrictionst
4055
{
41-
using restrictionst = std::unordered_map<irep_idt, std::vector<irep_idt>>;
56+
using restrictionst =
57+
std::unordered_map<irep_idt, std::unordered_set<irep_idt>>;
4258
using value_type = restrictionst::value_type;
4359
const restrictionst restrictions;
4460

4561
/// parse function pointer restrictions from command line
4662
///
4763
/// Note: These are are only syntactically checked at this stage,
4864
/// because type checking them requires a goto_modelt
49-
static function_pointer_restrictionst from_options(const optionst &options);
65+
static function_pointer_restrictionst
66+
from_options(const optionst &options, message_handlert &message_handler);
67+
68+
static function_pointer_restrictionst read_from_file(
69+
const std::string &filename,
70+
message_handlert &message_handler);
71+
72+
void write_to_file(const std::string &filename) const;
5073
};
5174

5275
/// Apply a function pointer restrictions to a goto_model. Each restriction is a

0 commit comments

Comments
 (0)