fix and check shifting issue
The exception raised by << and >> when shifting mark_t by too many bits are only enabled in SPOT_DEBUG, as those operations are quite low-level. However we were always testing them, and although we wanted them to be active in Python, it was not always the case. * spot/twa/acc.hh: introduce max_accsets() as a static constexpr method, so we can see it in Python. * spot/misc/bitset.hh: Fix preprocessing directive so the check is actually enabled when compiling the Python bindings. * bin/autcross.cc, bin/autfilt.cc, bin/ltlcross.cc: Use max_accsets(). * tests/core/acc.cc: Comment out the shifting exception when SPOT_DEBUG is unset. * tests/python/except.py: Make sure the exception is always raised in Python.
This commit is contained in:
parent
23e0d718fd
commit
b12eb0508f
7 changed files with 75 additions and 38 deletions
|
|
@ -509,7 +509,8 @@ namespace
|
||||||
const spot::const_twa_graph_ptr& aut_j,
|
const spot::const_twa_graph_ptr& aut_j,
|
||||||
size_t i, size_t j)
|
size_t i, size_t j)
|
||||||
{
|
{
|
||||||
if (aut_i->num_sets() + aut_j->num_sets() > SPOT_MAX_ACCSETS)
|
if (aut_i->num_sets() + aut_j->num_sets() >
|
||||||
|
spot::acc_cond::mark_t::max_accsets())
|
||||||
{
|
{
|
||||||
std::cerr << "info: building " << autname(i)
|
std::cerr << "info: building " << autname(i)
|
||||||
<< '*' << autname(j, true)
|
<< '*' << autname(j, true)
|
||||||
|
|
|
||||||
|
|
@ -649,7 +649,8 @@ static spot::twa_graph_ptr
|
||||||
product(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
|
product(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
|
||||||
{
|
{
|
||||||
if ((type == spot::postprocessor::BA)
|
if ((type == spot::postprocessor::BA)
|
||||||
&& (left->num_sets() + right->num_sets() > SPOT_MAX_ACCSETS))
|
&& (left->num_sets() + right->num_sets() >
|
||||||
|
spot::acc_cond::mark_t::max_accsets()))
|
||||||
{
|
{
|
||||||
left = ensure_tba(left);
|
left = ensure_tba(left);
|
||||||
right = ensure_tba(right);
|
right = ensure_tba(right);
|
||||||
|
|
@ -661,7 +662,8 @@ static spot::twa_graph_ptr
|
||||||
product_or(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
|
product_or(spot::twa_graph_ptr left, spot::twa_graph_ptr right)
|
||||||
{
|
{
|
||||||
if ((type == spot::postprocessor::BA)
|
if ((type == spot::postprocessor::BA)
|
||||||
&& (left->num_sets() + right->num_sets() > SPOT_MAX_ACCSETS))
|
&& (left->num_sets() + right->num_sets() >
|
||||||
|
spot::acc_cond::mark_t::max_accsets()))
|
||||||
{
|
{
|
||||||
left = ensure_tba(left);
|
left = ensure_tba(left);
|
||||||
right = ensure_tba(right);
|
right = ensure_tba(right);
|
||||||
|
|
@ -965,7 +967,8 @@ parse_opt(int key, char* arg, struct argp_state*)
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
error(2, 0, "acceptance sets should be non-negative:"
|
error(2, 0, "acceptance sets should be non-negative:"
|
||||||
" --mask-acc=%ld", res);
|
" --mask-acc=%ld", res);
|
||||||
if (static_cast<unsigned long>(res) > SPOT_MAX_ACCSETS)
|
if (static_cast<unsigned long>(res) >=
|
||||||
|
spot::acc_cond::mark_t::max_accsets())
|
||||||
error(2, 0, "this implementation does not support that many"
|
error(2, 0, "this implementation does not support that many"
|
||||||
" acceptance sets: --mask-acc=%ld", res);
|
" acceptance sets: --mask-acc=%ld", res);
|
||||||
opt_mask_acc.set(res);
|
opt_mask_acc.set(res);
|
||||||
|
|
|
||||||
|
|
@ -691,7 +691,8 @@ namespace
|
||||||
const spot::const_twa_graph_ptr& aut_j,
|
const spot::const_twa_graph_ptr& aut_j,
|
||||||
size_t i, size_t j, bool icomp, bool jcomp)
|
size_t i, size_t j, bool icomp, bool jcomp)
|
||||||
{
|
{
|
||||||
if (aut_i->num_sets() + aut_j->num_sets() > SPOT_MAX_ACCSETS)
|
if (aut_i->num_sets() + aut_j->num_sets() >
|
||||||
|
spot::acc_cond::mark_t::max_accsets())
|
||||||
{
|
{
|
||||||
// Report the skipped test if both automata are not
|
// Report the skipped test if both automata are not
|
||||||
// complemented, or the --verbose option is used,
|
// complemented, or the --verbose option is used,
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ namespace spot
|
||||||
|
|
||||||
bitset& operator<<=(unsigned s)
|
bitset& operator<<=(unsigned s)
|
||||||
{
|
{
|
||||||
#if SPOT_DEBUG || SWIG
|
#if SPOT_DEBUG || defined(SWIGPYTHON)
|
||||||
if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
|
if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
|
||||||
internal::report_bit_shift_too_big();
|
internal::report_bit_shift_too_big();
|
||||||
#else
|
#else
|
||||||
|
|
@ -191,7 +191,7 @@ namespace spot
|
||||||
|
|
||||||
bitset& operator>>=(unsigned s)
|
bitset& operator>>=(unsigned s)
|
||||||
{
|
{
|
||||||
#if SPOT_DEBUG || SWIG
|
#if SPOT_DEBUG || defined(SWIGPYTHON)
|
||||||
if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
|
if (SPOT_UNLIKELY(s >= 8 * N * sizeof(word_t)))
|
||||||
internal::report_bit_shift_too_big();
|
internal::report_bit_shift_too_big();
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,16 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief The maximum number of acceptance sets supported by
|
||||||
|
/// this implementation.
|
||||||
|
///
|
||||||
|
/// The value can be changed at compile-time using configure's
|
||||||
|
/// --enable-max-accsets=N option.
|
||||||
|
constexpr static unsigned max_accsets()
|
||||||
|
{
|
||||||
|
return SPOT_MAX_ACCSETS;
|
||||||
|
}
|
||||||
|
|
||||||
static mark_t all()
|
static mark_t all()
|
||||||
{
|
{
|
||||||
return mark_t(_value_t::mone());
|
return mark_t(_value_t::mone());
|
||||||
|
|
@ -220,7 +230,7 @@ namespace spot
|
||||||
return id ^ r.id;
|
return id ^ r.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SPOT_DEBUG || SWIG
|
#if SPOT_DEBUG || defined(SWIGPYTHON)
|
||||||
# define SPOT_WRAP_OP(ins) \
|
# define SPOT_WRAP_OP(ins) \
|
||||||
try \
|
try \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -567,7 +577,7 @@ namespace spot
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return inf({});
|
return inf({});
|
||||||
acc_cond::mark_t m = mark_t::all();
|
acc_cond::mark_t m = mark_t::all();
|
||||||
m >>= (SPOT_MAX_ACCSETS - n);
|
m >>= mark_t::max_accsets() - n;
|
||||||
return inf(m);
|
return inf(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -576,7 +586,7 @@ namespace spot
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return fin({});
|
return fin({});
|
||||||
acc_cond::mark_t m = mark_t::all();
|
acc_cond::mark_t m = mark_t::all();
|
||||||
m >>= (SPOT_MAX_ACCSETS - n);
|
m >>= mark_t::max_accsets() - n;
|
||||||
return fin(m);
|
return fin(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -833,6 +843,8 @@ namespace spot
|
||||||
|
|
||||||
acc_code& operator<<=(unsigned sets)
|
acc_code& operator<<=(unsigned sets)
|
||||||
{
|
{
|
||||||
|
if (SPOT_UNLIKELY(sets >= mark_t::max_accsets()))
|
||||||
|
report_too_many_sets();
|
||||||
if (empty())
|
if (empty())
|
||||||
return *this;
|
return *this;
|
||||||
unsigned pos = size();
|
unsigned pos = size();
|
||||||
|
|
@ -1247,9 +1259,11 @@ namespace spot
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
return -1U;
|
return -1U;
|
||||||
unsigned j = num_;
|
unsigned j = num_;
|
||||||
num_ += num;
|
num += j;
|
||||||
if (num_ > SPOT_MAX_ACCSETS)
|
if (num > mark_t::max_accsets())
|
||||||
report_too_many_sets();
|
report_too_many_sets();
|
||||||
|
// Make sure we do not update if we raised an exception.
|
||||||
|
num_ = num;
|
||||||
all_ = all_sets_();
|
all_ = all_sets_();
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
@ -1386,7 +1400,7 @@ namespace spot
|
||||||
protected:
|
protected:
|
||||||
mark_t all_sets_() const
|
mark_t all_sets_() const
|
||||||
{
|
{
|
||||||
return mark_t::all() >> (SPOT_MAX_ACCSETS - num_);
|
return mark_t::all() >> (spot::acc_cond::mark_t::max_accsets() - num_);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned num_;
|
unsigned num_;
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,10 @@ int main()
|
||||||
auto m1 = spot::acc_cond::mark_t({0, 2});
|
auto m1 = spot::acc_cond::mark_t({0, 2});
|
||||||
auto m2 = spot::acc_cond::mark_t({0, 3});
|
auto m2 = spot::acc_cond::mark_t({0, 3});
|
||||||
auto m3 = spot::acc_cond::mark_t({2, 1});
|
auto m3 = spot::acc_cond::mark_t({2, 1});
|
||||||
auto m4 = spot::acc_cond::mark_t({0, SPOT_MAX_ACCSETS - 2});
|
auto m4 =
|
||||||
if (!(m4.min_set() == 1 && m4.max_set() == SPOT_MAX_ACCSETS - 1))
|
spot::acc_cond::mark_t({0, spot::acc_cond::mark_t::max_accsets() - 2});
|
||||||
|
if (!((m4.min_set() == 1) &&
|
||||||
|
(m4.max_set() == spot::acc_cond::mark_t::max_accsets() - 1)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
spot::acc_cond::mark_t m0 = {};
|
spot::acc_cond::mark_t m0 = {};
|
||||||
|
|
@ -185,7 +187,22 @@ int main()
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
spot::acc_cond a{SPOT_MAX_ACCSETS + 1};
|
spot::acc_cond a{spot::acc_cond::mark_t::max_accsets() + 1};
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& e)
|
||||||
|
{
|
||||||
|
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SPOT_DEBUG
|
||||||
|
// Those error message are disabled in non-debugging code as
|
||||||
|
// shifting mark_t is usually done in the innermost loop of
|
||||||
|
// algorithms. However, they are still done in Python, and we
|
||||||
|
// test them in python/except.py
|
||||||
|
try
|
||||||
|
{
|
||||||
|
spot::acc_cond::mark_t m{0};
|
||||||
|
m <<= spot::acc_cond::mark_t::max_accsets() + 1;
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e)
|
catch (const std::runtime_error& e)
|
||||||
{
|
{
|
||||||
|
|
@ -195,22 +212,13 @@ int main()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
spot::acc_cond::mark_t m{0};
|
spot::acc_cond::mark_t m{0};
|
||||||
m <<= SPOT_MAX_ACCSETS + 1;
|
m >>= spot::acc_cond::mark_t::max_accsets() + 1;
|
||||||
}
|
|
||||||
catch (const std::runtime_error& e)
|
|
||||||
{
|
|
||||||
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
spot::acc_cond::mark_t m{0};
|
|
||||||
m >>= SPOT_MAX_ACCSETS + 1;
|
|
||||||
}
|
}
|
||||||
catch (const std::runtime_error& e)
|
catch (const std::runtime_error& e)
|
||||||
{
|
{
|
||||||
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
assert(!std::strncmp(e.what(), "Too many acceptance sets used.", 30));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,3 +129,13 @@ except RuntimeError as e:
|
||||||
assert "safety" in str(e)
|
assert "safety" in str(e)
|
||||||
else:
|
else:
|
||||||
report_missing_exception()
|
report_missing_exception()
|
||||||
|
|
||||||
|
n = spot.mark_t.max_accsets()
|
||||||
|
m = spot.mark_t([n - 1])
|
||||||
|
try:
|
||||||
|
m = spot.mark_t([0]) << n
|
||||||
|
except RuntimeError as e:
|
||||||
|
assert "Too many acceptance sets" in str(e)
|
||||||
|
else:
|
||||||
|
print(n, m)
|
||||||
|
report_missing_exception()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue