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.
This commit is contained in:
Alexandre Duret-Lutz 2019-09-25 21:57:25 +02:00
parent 0da5f44cd2
commit 6bdb135724
23 changed files with 104 additions and 19 deletions

View file

@ -153,6 +153,8 @@ static output_file* bogus_output = nullptr;
static int static int
parse_opt(int key, char* arg, struct argp_state*) parse_opt(int key, char* arg, struct argp_state*)
{ {
// Called from C code, so should not raise any exception.
BEGIN_EXCEPTION_PROTECT;
switch (key) switch (key)
{ {
case 'F': case 'F':
@ -214,6 +216,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -688,6 +688,8 @@ product_or(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -1154,6 +1156,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -24,6 +24,7 @@
#include "common_aoutput.hh" #include "common_aoutput.hh"
#include "common_post.hh" #include "common_post.hh"
#include "common_cout.hh" #include "common_cout.hh"
#include "common_setup.hh"
#include <unistd.h> #include <unistd.h>
#include <ctime> #include <ctime>
@ -304,6 +305,8 @@ const struct argp aoutput_o_format_argp = { o_options,
int parse_opt_aoutput(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -358,6 +361,7 @@ int parse_opt_aoutput(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2017 Laboratoire de Recherche et Développement de // Copyright (C) 2017, 2019 Laboratoire de Recherche et Développement
// l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -19,6 +19,7 @@
#include "common_sys.hh" #include "common_sys.hh"
#include "common_color.hh" #include "common_color.hh"
#include "common_setup.hh"
#include <argp.h> #include <argp.h>
#include <unistd.h> #include <unistd.h>
@ -77,6 +78,8 @@ static const argp_option options_color[] =
static int static int
parse_opt_color(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -91,6 +94,7 @@ parse_opt_color(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2012-2017 Laboratoire de Recherche // Copyright (C) 2012-2017, 2019 Laboratoire de Recherche et
// et Développement de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // 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 int
parse_opt_finput(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -80,6 +82,7 @@ parse_opt_finput(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2015 Laboratoire de Recherche et Développement de // Copyright (C) 2015, 2019 Laboratoire de Recherche et Développement
// l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -18,6 +18,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "common_hoaread.hh" #include "common_hoaread.hh"
#include "common_setup.hh"
#include "argmatch.h" #include "argmatch.h"
#include "error.h" #include "error.h"
@ -72,6 +73,8 @@ static bool parse_bool(const char* opt, const char* arg)
static int static int
parse_opt_hoaread(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -81,6 +84,7 @@ parse_opt_hoaread(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -20,6 +20,7 @@
#include "common_sys.hh" #include "common_sys.hh"
#include "common_output.hh" #include "common_output.hh"
#include "common_aoutput.hh" #include "common_aoutput.hh"
#include "common_setup.hh"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <spot/tl/print.hh> #include <spot/tl/print.hh>
@ -304,6 +305,8 @@ static std::map<std::string, std::unique_ptr<output_file>> outputfiles;
int int
parse_opt_output(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -344,6 +347,7 @@ parse_opt_output(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -20,6 +20,7 @@
#include "common_post.hh" #include "common_post.hh"
#include "common_r.hh" #include "common_r.hh"
#include "common_aoutput.hh" #include "common_aoutput.hh"
#include "common_setup.hh"
#include "error.h" #include "error.h"
#include "argmatch.h" #include "argmatch.h"
@ -154,6 +155,8 @@ static const argp_option options_disabled[] =
static int static int
parse_opt_post(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -253,6 +256,7 @@ parse_opt_post(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -150,6 +150,8 @@ static const argp_option options_hidden[] =
static int static int
parse_opt_misc(int key, char*, struct argp_state* state) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -170,6 +172,7 @@ parse_opt_misc(int key, char*, struct argp_state* state)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }
@ -181,6 +184,18 @@ const struct argp misc_argp_hidden = { options_hidden, parse_opt_misc,
nullptr, nullptr, nullptr, nullptr, nullptr, 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<int()> mainfun) int protected_main(char** progname, std::function<int()> mainfun)
{ {
@ -189,13 +204,9 @@ int protected_main(char** progname, std::function<int()> mainfun)
setup(progname); setup(progname);
return mainfun(); return mainfun();
} }
catch (const std::runtime_error& e) catch (...)
{ {
error(2, 0, "%s", e.what()); handle_any_exception();
}
catch (const std::invalid_argument& e)
{
error(2, 0, "%s", e.what());
} }
SPOT_UNREACHABLE(); SPOT_UNREACHABLE();
return 2; return 2;

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // 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. // Call setup(progname) then Run mainfun() and handle exceptions.
int protected_main(char** progname, std::function<int()> mainfun); int protected_main(char** progname, std::function<int()> mainfun);
// Diagnose exceptions.
[[noreturn]] void handle_any_exception();
#define BEGIN_EXCEPTION_PROTECT try { (void)0;
#define END_EXCEPTION_PROTECT } catch (...) { handle_any_exception(); }

View file

@ -18,6 +18,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "common_trans.hh" #include "common_trans.hh"
#include "common_setup.hh"
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <cassert> #include <cassert>
@ -902,6 +903,8 @@ bool opt_relabel = false;
static int parse_opt_trans(int key, char* arg, struct argp_state*) 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) switch (key)
{ {
case 't': case 't':
@ -930,6 +933,7 @@ static int parse_opt_trans(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -83,6 +83,8 @@ static spot::option_map extra_options;
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -102,6 +104,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -97,11 +97,14 @@ enqueue_job(int pattern, const char* range_str)
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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) if (key >= gen::AUT_BEGIN && key < gen::AUT_END)
{ {
enqueue_job(key, arg); enqueue_job(key, arg);
return 0; return 0;
} }
END_EXCEPTION_PROTECT;
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }

View file

@ -261,6 +261,8 @@ enqueue_job(int pattern, const char* range_str = nullptr)
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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) if (key >= gen::LTL_BEGIN && key < gen::LTL_END)
{ {
enqueue_job(key, arg); enqueue_job(key, arg);
@ -278,6 +280,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -85,6 +85,8 @@ static spot::postprocessor::output_pref unambig = 0;
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -112,6 +114,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -109,6 +109,8 @@ bool opt_with_artificial_livelock = false;
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -154,6 +156,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -440,6 +440,8 @@ std::vector<std::string> formulas;
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -556,6 +558,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -164,6 +164,8 @@ const struct argp_child children[] =
static int static int
parse_opt(int key, char* arg, struct argp_state*) parse_opt(int key, char* arg, struct argp_state*)
{ {
// Called from C code, so should not raise any exception.
BEGIN_EXCEPTION_PROTECT;
switch (key) switch (key)
{ {
case OPT_ERRORS: case OPT_ERRORS:
@ -197,6 +199,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -345,6 +345,8 @@ parse_formula_arg(const std::string& input)
static int static int
parse_opt(int key, char* arg, struct argp_state*) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -545,6 +547,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -131,6 +131,8 @@ namespace
static int static int
parse_opt(int key, char* arg, struct argp_state*) parse_opt(int key, char* arg, struct argp_state*)
{ {
// Called from C code, so should not raise any exception.
BEGIN_EXCEPTION_PROTECT;
switch (key) switch (key)
{ {
case 'm': case 'm':
@ -177,6 +179,7 @@ parse_opt(int key, char* arg, struct argp_state*)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -412,6 +412,8 @@ namespace
static int static int
parse_opt(int key, char* arg, struct argp_state*) parse_opt(int key, char* arg, struct argp_state*)
{ {
// Called from C code, so should not raise any exception.
BEGIN_EXCEPTION_PROTECT;
switch (key) switch (key)
{ {
case OPT_INPUT: case OPT_INPUT:
@ -452,6 +454,7 @@ parse_opt(int key, char* arg, struct argp_state*)
verbose = true; verbose = true;
break; break;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -182,6 +182,8 @@ looks_like_a_range(const char* str)
static int static int
parse_opt(int key, char* arg, struct argp_state* as) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -264,6 +266,7 @@ parse_opt(int key, char* arg, struct argp_state* as)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- 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). // et Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -159,6 +159,8 @@ static bool ap_count_given = false;
static int static int
parse_opt(int key, char* arg, struct argp_state* as) 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. // This switch is alphabetically-ordered.
switch (key) switch (key)
{ {
@ -231,6 +233,7 @@ parse_opt(int key, char* arg, struct argp_state* as)
default: default:
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
} }
END_EXCEPTION_PROTECT;
return 0; return 0;
} }