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 74ceea89ee
commit d523ce8ba4
23 changed files with 104 additions and 19 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -24,6 +24,7 @@
#include "common_aoutput.hh"
#include "common_post.hh"
#include "common_cout.hh"
#include "common_setup.hh"
#include <unistd.h>
#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*)
{
// 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;
}

View file

@ -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 <argp.h>
#include <unistd.h>
@ -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;
}

View file

@ -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;
}

View file

@ -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 <http://www.gnu.org/licenses/>.
#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;
}

View file

@ -20,6 +20,7 @@
#include "common_sys.hh"
#include "common_output.hh"
#include "common_aoutput.hh"
#include "common_setup.hh"
#include <iostream>
#include <sstream>
#include <spot/tl/print.hh>
@ -304,6 +305,8 @@ static std::map<std::string, std::unique_ptr<output_file>> 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;
}

View file

@ -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;
}

View file

@ -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<int()> mainfun)
{
@ -189,13 +204,9 @@ int protected_main(char** progname, std::function<int()> 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;

View file

@ -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<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/>.
#include "common_trans.hh"
#include "common_setup.hh"
#include <cstring>
#include <cstdlib>
#include <cassert>
@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -440,6 +440,8 @@ std::vector<std::string> 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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}