mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
Improve negation of ConstExpr
* Instead of creating a NegExpr for negation of a literal/constant, a ConstExpr is now created directly. * For negation of integer literals, there's now an additional check for whether the integer would be outside the range of possible 'int' values. This can also help prevent the undefined behavior due to overflow as a result of trying to represent the minimum 'int' value of -9223372036854775808 as a literal in a script -- the unsigned value is cast to signed yielding INT64_MIN, then INT64_MIN is negated.
This commit is contained in:
parent
1b88e63e78
commit
a44b056e81
3 changed files with 41 additions and 0 deletions
30
src/parse.y
30
src/parse.y
|
@ -330,6 +330,36 @@ expr:
|
||||||
{
|
{
|
||||||
zeek::detail::set_location(@1, @2);
|
zeek::detail::set_location(@1, @2);
|
||||||
$$ = new zeek::detail::NegExpr({zeek::AdoptRef{}, $2});
|
$$ = new zeek::detail::NegExpr({zeek::AdoptRef{}, $2});
|
||||||
|
|
||||||
|
if ( ! $$->IsError() && $2->IsConst() )
|
||||||
|
{
|
||||||
|
auto v = $2->ExprVal();
|
||||||
|
auto tag = v->GetType()->Tag();
|
||||||
|
|
||||||
|
if ( tag == zeek::TYPE_COUNT )
|
||||||
|
{
|
||||||
|
auto c = v->AsCount();
|
||||||
|
uint64_t int_max = static_cast<uint64_t>(INT64_MAX) + 1;
|
||||||
|
|
||||||
|
if ( c <= int_max )
|
||||||
|
{
|
||||||
|
auto ce = new zeek::detail::ConstExpr(zeek::val_mgr->Int(-c));
|
||||||
|
Unref($$);
|
||||||
|
$$ = ce;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$$->Error("literal is outside range of 'int' values");
|
||||||
|
$$->SetError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto ce = new zeek::detail::ConstExpr($$->Eval(nullptr));
|
||||||
|
Unref($$);
|
||||||
|
$$ = ce;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
| '+' expr %prec '!'
|
| '+' expr %prec '!'
|
||||||
|
|
2
testing/btest/Baseline/language.int-negation-range/out
Normal file
2
testing/btest/Baseline/language.int-negation-range/out
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.int-negation-range/int-negation-range.zeek, line 8: literal is outside range of 'int' values (-9223372036854775809)
|
||||||
|
error in /home/jon/pro/zeek/zeek/testing/btest/.tmp/language.int-negation-range/int-negation-range.zeek, line 9: literal is outside range of 'int' values (-9223372036854775810)
|
9
testing/btest/language/int-negation-range.zeek
Normal file
9
testing/btest/language/int-negation-range.zeek
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# @TEST-EXEC-FAIL: zeek -b %INPUT >out 2>&1
|
||||||
|
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff out
|
||||||
|
|
||||||
|
local i_min = -9223372036854775808;
|
||||||
|
local i_min_p1 = -9223372036854775807;
|
||||||
|
|
||||||
|
# These should be caught at parse-time as outside the range of a 64-bit ints.
|
||||||
|
local i_min_m1 = -9223372036854775809;
|
||||||
|
local i_min_m2 = -9223372036854775810;
|
Loading…
Add table
Add a link
Reference in a new issue