From d523ce8ba40db2471f131b3dc83202549730809f Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Wed, 25 Sep 2019 21:57:25 +0200 Subject: [PATCH] bin: handle any exception before returning from parse_opt() On some architectures (e.g., ARM, or even some -flto setups on Intel) C++ exceptions to not traverse the C functions. So even if the C++ main() has a try/catch, it will not catch the exception thrown by C++ code called from the argp module (which is compiled in C). * bin/common_setup.cc, bin/common_setup.hh: Define some macros and function to factorize exception handling. * bin/autcross.cc, bin/autfilt.cc, bin/common_aoutput.cc, bin/common_color.cc, bin/common_finput.cc, bin/common_hoaread.cc, bin/common_output.cc, bin/common_post.cc, bin/common_trans.cc, bin/dstar2tgba.cc, bin/genaut.cc, bin/genltl.cc, bin/ltl2tgba.cc, bin/ltl2tgta.cc, bin/ltlcross.cc, bin/ltldo.cc, bin/ltlfilt.cc, bin/ltlgrind.cc, bin/ltlsynt.cc, bin/randaut.cc, bin/randltl.cc: Protect all parse_opt() functions, even those where there is currently no exception risk. --- bin/autcross.cc | 3 +++ bin/autfilt.cc | 3 +++ bin/common_aoutput.cc | 4 ++++ bin/common_color.cc | 8 ++++++-- bin/common_finput.cc | 7 +++++-- bin/common_hoaread.cc | 8 ++++++-- bin/common_output.cc | 4 ++++ bin/common_post.cc | 6 +++++- bin/common_setup.cc | 23 +++++++++++++++++------ bin/common_setup.hh | 7 ++++++- bin/common_trans.cc | 4 ++++ bin/dstar2tgba.cc | 5 ++++- bin/genaut.cc | 3 +++ bin/genltl.cc | 3 +++ bin/ltl2tgba.cc | 3 +++ bin/ltl2tgta.cc | 5 ++++- bin/ltlcross.cc | 3 +++ bin/ltldo.cc | 3 +++ bin/ltlfilt.cc | 3 +++ bin/ltlgrind.cc | 5 ++++- bin/ltlsynt.cc | 3 +++ bin/randaut.cc | 5 ++++- bin/randltl.cc | 5 ++++- 23 files changed, 104 insertions(+), 19 deletions(-) diff --git a/bin/autcross.cc b/bin/autcross.cc index 8a1394ddb..437759429 100644 --- a/bin/autcross.cc +++ b/bin/autcross.cc @@ -153,6 +153,8 @@ static output_file* bogus_output = nullptr; static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; switch (key) { case 'F': @@ -214,6 +216,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/autfilt.cc b/bin/autfilt.cc index f8cbf7dc4..e0f8279b2 100644 --- a/bin/autfilt.cc +++ b/bin/autfilt.cc @@ -688,6 +688,8 @@ product_or(spot::twa_graph_ptr left, spot::twa_graph_ptr right) static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -1154,6 +1156,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_aoutput.cc b/bin/common_aoutput.cc index 9e8976da9..8ec651fbc 100644 --- a/bin/common_aoutput.cc +++ b/bin/common_aoutput.cc @@ -24,6 +24,7 @@ #include "common_aoutput.hh" #include "common_post.hh" #include "common_cout.hh" +#include "common_setup.hh" #include #include @@ -304,6 +305,8 @@ const struct argp aoutput_o_format_argp = { o_options, int parse_opt_aoutput(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -358,6 +361,7 @@ int parse_opt_aoutput(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_color.cc b/bin/common_color.cc index 7b6330356..5c49e2021 100644 --- a/bin/common_color.cc +++ b/bin/common_color.cc @@ -1,6 +1,6 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2017 Laboratoire de Recherche et Développement de -// l'Epita (LRDE). +// Copyright (C) 2017, 2019 Laboratoire de Recherche et Développement +// de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // @@ -19,6 +19,7 @@ #include "common_sys.hh" #include "common_color.hh" +#include "common_setup.hh" #include #include @@ -77,6 +78,8 @@ static const argp_option options_color[] = static int parse_opt_color(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -91,6 +94,7 @@ parse_opt_color(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_finput.cc b/bin/common_finput.cc index f19e64a6b..67e5a4353 100644 --- a/bin/common_finput.cc +++ b/bin/common_finput.cc @@ -1,6 +1,6 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012-2017 Laboratoire de Recherche -// et Développement de l'Epita (LRDE). +// Copyright (C) 2012-2017, 2019 Laboratoire de Recherche et +// Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // @@ -62,6 +62,8 @@ const struct argp finput_argp_headless = { options + 1, parse_opt_finput, int parse_opt_finput(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -80,6 +82,7 @@ parse_opt_finput(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_hoaread.cc b/bin/common_hoaread.cc index 809796b0c..919378da4 100644 --- a/bin/common_hoaread.cc +++ b/bin/common_hoaread.cc @@ -1,6 +1,6 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2015 Laboratoire de Recherche et Développement de -// l'Epita (LRDE). +// Copyright (C) 2015, 2019 Laboratoire de Recherche et Développement +// de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // @@ -18,6 +18,7 @@ // along with this program. If not, see . #include "common_hoaread.hh" +#include "common_setup.hh" #include "argmatch.h" #include "error.h" @@ -72,6 +73,8 @@ static bool parse_bool(const char* opt, const char* arg) static int parse_opt_hoaread(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -81,6 +84,7 @@ parse_opt_hoaread(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_output.cc b/bin/common_output.cc index 092a9329f..e9c61a513 100644 --- a/bin/common_output.cc +++ b/bin/common_output.cc @@ -20,6 +20,7 @@ #include "common_sys.hh" #include "common_output.hh" #include "common_aoutput.hh" +#include "common_setup.hh" #include #include #include @@ -304,6 +305,8 @@ static std::map> outputfiles; int parse_opt_output(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -344,6 +347,7 @@ parse_opt_output(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_post.cc b/bin/common_post.cc index ef97b0a26..e6ebfd29b 100644 --- a/bin/common_post.cc +++ b/bin/common_post.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012-2016, 2018 Laboratoire de Recherche et +// Copyright (C) 2012-2016, 2018-2019 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -20,6 +20,7 @@ #include "common_post.hh" #include "common_r.hh" #include "common_aoutput.hh" +#include "common_setup.hh" #include "error.h" #include "argmatch.h" @@ -154,6 +155,8 @@ static const argp_option options_disabled[] = static int parse_opt_post(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -253,6 +256,7 @@ parse_opt_post(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/common_setup.cc b/bin/common_setup.cc index 99b4eb202..dab5df571 100644 --- a/bin/common_setup.cc +++ b/bin/common_setup.cc @@ -150,6 +150,8 @@ static const argp_option options_hidden[] = static int parse_opt_misc(int key, char*, struct argp_state* state) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -170,6 +172,7 @@ parse_opt_misc(int key, char*, struct argp_state* state) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } @@ -181,6 +184,18 @@ const struct argp misc_argp_hidden = { options_hidden, parse_opt_misc, nullptr, nullptr, nullptr, nullptr, nullptr }; +[[noreturn]] void handle_any_exception() +{ + try + { + throw; + } + catch (const std::exception& e) + { + error(2, 0, "%s", e.what()); + } + SPOT_UNREACHABLE(); +} int protected_main(char** progname, std::function mainfun) { @@ -189,13 +204,9 @@ int protected_main(char** progname, std::function mainfun) setup(progname); return mainfun(); } - catch (const std::runtime_error& e) + catch (...) { - error(2, 0, "%s", e.what()); - } - catch (const std::invalid_argument& e) - { - error(2, 0, "%s", e.what()); + handle_any_exception(); } SPOT_UNREACHABLE(); return 2; diff --git a/bin/common_setup.hh b/bin/common_setup.hh index 41f4a71a2..e2fce84e0 100644 --- a/bin/common_setup.hh +++ b/bin/common_setup.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012, 2013, 2018 Laboratoire de Recherche et +// Copyright (C) 2012, 2013, 2018, 2019 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -31,3 +31,8 @@ extern const struct argp misc_argp_hidden; // Call setup(progname) then Run mainfun() and handle exceptions. int protected_main(char** progname, std::function mainfun); + +// Diagnose exceptions. +[[noreturn]] void handle_any_exception(); +#define BEGIN_EXCEPTION_PROTECT try { (void)0; +#define END_EXCEPTION_PROTECT } catch (...) { handle_any_exception(); } diff --git a/bin/common_trans.cc b/bin/common_trans.cc index bac0c15ba..e3df2316b 100644 --- a/bin/common_trans.cc +++ b/bin/common_trans.cc @@ -18,6 +18,7 @@ // along with this program. If not, see . #include "common_trans.hh" +#include "common_setup.hh" #include #include #include @@ -902,6 +903,8 @@ bool opt_relabel = false; static int parse_opt_trans(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; switch (key) { case 't': @@ -930,6 +933,7 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/dstar2tgba.cc b/bin/dstar2tgba.cc index 1abe45f23..3bf5b9393 100644 --- a/bin/dstar2tgba.cc +++ b/bin/dstar2tgba.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2013-2018 Laboratoire de Recherche et Développement +// Copyright (C) 2013-2019 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -83,6 +83,8 @@ static spot::option_map extra_options; static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -102,6 +104,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/genaut.cc b/bin/genaut.cc index 9e8f1939e..eb2163cab 100644 --- a/bin/genaut.cc +++ b/bin/genaut.cc @@ -97,11 +97,14 @@ enqueue_job(int pattern, const char* range_str) static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; if (key >= gen::AUT_BEGIN && key < gen::AUT_END) { enqueue_job(key, arg); return 0; } + END_EXCEPTION_PROTECT; return ARGP_ERR_UNKNOWN; } diff --git a/bin/genltl.cc b/bin/genltl.cc index c9f8374bd..6c632de7a 100644 --- a/bin/genltl.cc +++ b/bin/genltl.cc @@ -261,6 +261,8 @@ enqueue_job(int pattern, const char* range_str = nullptr) static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; if (key >= gen::LTL_BEGIN && key < gen::LTL_END) { enqueue_job(key, arg); @@ -278,6 +280,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltl2tgba.cc b/bin/ltl2tgba.cc index 332b0a81b..e24e7e856 100644 --- a/bin/ltl2tgba.cc +++ b/bin/ltl2tgba.cc @@ -85,6 +85,8 @@ static spot::postprocessor::output_pref unambig = 0; static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -112,6 +114,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltl2tgta.cc b/bin/ltl2tgta.cc index 198b9ccfe..8663f5513 100644 --- a/bin/ltl2tgta.cc +++ b/bin/ltl2tgta.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012-2018 Laboratoire de Recherche et Développement +// Copyright (C) 2012-2019 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -109,6 +109,8 @@ bool opt_with_artificial_livelock = false; static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -154,6 +156,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltlcross.cc b/bin/ltlcross.cc index edb5caa41..efafe7b31 100644 --- a/bin/ltlcross.cc +++ b/bin/ltlcross.cc @@ -440,6 +440,8 @@ std::vector formulas; static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -556,6 +558,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltldo.cc b/bin/ltldo.cc index 374d61c78..f3e68c34b 100644 --- a/bin/ltldo.cc +++ b/bin/ltldo.cc @@ -164,6 +164,8 @@ const struct argp_child children[] = static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; switch (key) { case OPT_ERRORS: @@ -197,6 +199,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltlfilt.cc b/bin/ltlfilt.cc index 72ca8bc3e..d16684ef8 100644 --- a/bin/ltlfilt.cc +++ b/bin/ltlfilt.cc @@ -345,6 +345,8 @@ parse_formula_arg(const std::string& input) static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -545,6 +547,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltlgrind.cc b/bin/ltlgrind.cc index 2e141e863..393656b00 100644 --- a/bin/ltlgrind.cc +++ b/bin/ltlgrind.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2014, 2015, 2016, 2017, 2018 Laboratoire de Recherche et +// Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -131,6 +131,8 @@ namespace static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; switch (key) { case 'm': @@ -177,6 +179,7 @@ parse_opt(int key, char* arg, struct argp_state*) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index 99e7410eb..8377b79d6 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -412,6 +412,8 @@ namespace static int parse_opt(int key, char* arg, struct argp_state*) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; switch (key) { case OPT_INPUT: @@ -452,6 +454,7 @@ parse_opt(int key, char* arg, struct argp_state*) verbose = true; break; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/randaut.cc b/bin/randaut.cc index 76e17085a..8a14ae740 100644 --- a/bin/randaut.cc +++ b/bin/randaut.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012, 2013, 2014, 2015, 2016, 2018 Laboratoire de Recherche et +// Copyright (C) 2012-2016, 2018-2019 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -182,6 +182,8 @@ looks_like_a_range(const char* str) static int parse_opt(int key, char* arg, struct argp_state* as) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -264,6 +266,7 @@ parse_opt(int key, char* arg, struct argp_state* as) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; } diff --git a/bin/randltl.cc b/bin/randltl.cc index 47bfdb3bf..cded77171 100644 --- a/bin/randltl.cc +++ b/bin/randltl.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012, 2013, 2014, 2015, 2016, 2018 Laboratoire de Recherche +// Copyright (C) 2012-2016, 2018-2019 Laboratoire de Recherche // et Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -159,6 +159,8 @@ static bool ap_count_given = false; static int parse_opt(int key, char* arg, struct argp_state* as) { + // Called from C code, so should not raise any exception. + BEGIN_EXCEPTION_PROTECT; // This switch is alphabetically-ordered. switch (key) { @@ -231,6 +233,7 @@ parse_opt(int key, char* arg, struct argp_state* as) default: return ARGP_ERR_UNKNOWN; } + END_EXCEPTION_PROTECT; return 0; }