mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
factoring out logic to check for overflows during coercions
This commit is contained in:
parent
9757d37332
commit
a67897135e
8 changed files with 89 additions and 37 deletions
|
@ -333,6 +333,7 @@ set(MAIN_SRCS
|
|||
Obj.cc
|
||||
OpaqueVal.cc
|
||||
Options.cc
|
||||
Overflow.cc
|
||||
PacketFilter.cc
|
||||
Pipe.cc
|
||||
PolicyFile.cc
|
||||
|
|
39
src/Overflow.cc
Normal file
39
src/Overflow.cc
Normal file
|
@ -0,0 +1,39 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include "zeek/Overflow.h"
|
||||
#include "zeek/Val.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
bool would_overflow(const zeek::Type* from_type, const zeek::Type* to_type,
|
||||
const Val* val)
|
||||
{
|
||||
if ( ! to_type || ! from_type )
|
||||
return true;
|
||||
|
||||
if ( same_type(to_type, from_type) )
|
||||
return false;
|
||||
|
||||
if ( to_type->InternalType() == TYPE_INTERNAL_DOUBLE )
|
||||
return false;
|
||||
|
||||
if ( to_type->InternalType() == TYPE_INTERNAL_UNSIGNED )
|
||||
{
|
||||
if ( from_type->InternalType() == TYPE_INTERNAL_DOUBLE )
|
||||
return double_to_count_would_overflow(val->InternalDouble());
|
||||
if ( from_type->InternalType() == TYPE_INTERNAL_INT )
|
||||
return int_to_count_would_overflow(val->InternalInt());
|
||||
}
|
||||
|
||||
if ( to_type->InternalType() == TYPE_INTERNAL_INT )
|
||||
{
|
||||
if ( from_type->InternalType() == TYPE_INTERNAL_DOUBLE )
|
||||
return double_to_int_would_overflow(val->InternalDouble());
|
||||
if ( from_type->InternalType() == TYPE_INTERNAL_UNSIGNED )
|
||||
return count_to_int_would_overflow(val->InternalUnsigned());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
33
src/Overflow.h
Normal file
33
src/Overflow.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zeek/Type.h"
|
||||
|
||||
namespace zeek::detail {
|
||||
|
||||
inline bool double_to_count_would_overflow(double v)
|
||||
{
|
||||
return v < 0.0 || v > static_cast<double>(UINT64_MAX);
|
||||
}
|
||||
|
||||
inline bool int_to_count_would_overflow(bro_int_t v)
|
||||
{
|
||||
return v < 0.0;
|
||||
}
|
||||
|
||||
inline bool double_to_int_would_overflow(double v)
|
||||
{
|
||||
return v < static_cast<double>(INT64_MIN) ||
|
||||
v > static_cast<double>(INT64_MAX);
|
||||
}
|
||||
|
||||
inline bool count_to_int_would_overflow(bro_uint_t v)
|
||||
{
|
||||
return v > INT64_MAX;
|
||||
}
|
||||
|
||||
extern bool would_overflow(const zeek::Type* from_type,
|
||||
const zeek::Type* to_type, const Val* val);
|
||||
|
||||
}
|
32
src/Val.cc
32
src/Val.cc
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "zeek/zeek-config.h"
|
||||
#include "zeek/Val.h"
|
||||
#include "zeek/Overflow.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -349,33 +350,6 @@ void Val::SetID(detail::ID* id)
|
|||
}
|
||||
#endif
|
||||
|
||||
bool Val::WouldOverflow(const zeek::Type* from_type, const zeek::Type* to_type, const Val* val)
|
||||
{
|
||||
if ( !to_type || !from_type )
|
||||
return true;
|
||||
else if ( same_type(to_type, from_type) )
|
||||
return false;
|
||||
|
||||
if ( to_type->InternalType() == TYPE_INTERNAL_DOUBLE )
|
||||
return false;
|
||||
else if ( to_type->InternalType() == TYPE_INTERNAL_UNSIGNED )
|
||||
{
|
||||
if ( from_type->InternalType() == TYPE_INTERNAL_DOUBLE )
|
||||
return (val->InternalDouble() < 0.0 || val->InternalDouble() > static_cast<double>(UINT64_MAX));
|
||||
else if ( from_type->InternalType() == TYPE_INTERNAL_INT )
|
||||
return (val->InternalInt() < 0);
|
||||
}
|
||||
else if ( to_type->InternalType() == TYPE_INTERNAL_INT )
|
||||
{
|
||||
if ( from_type->InternalType() == TYPE_INTERNAL_DOUBLE )
|
||||
return (val->InternalDouble() < static_cast<double>(INT64_MIN) ||
|
||||
val->InternalDouble() > static_cast<double>(INT64_MAX));
|
||||
else if ( from_type->InternalType() == TYPE_INTERNAL_UNSIGNED )
|
||||
return (val->InternalUnsigned() > INT64_MAX);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TableValPtr Val::GetRecordFields()
|
||||
{
|
||||
|
@ -3825,7 +3799,7 @@ ValPtr check_and_promote(ValPtr v,
|
|||
|
||||
switch ( it ) {
|
||||
case TYPE_INTERNAL_INT:
|
||||
if ( ( vit == TYPE_INTERNAL_UNSIGNED || vit == TYPE_INTERNAL_DOUBLE ) && Val::WouldOverflow(vt, t, v.get()) )
|
||||
if ( ( vit == TYPE_INTERNAL_UNSIGNED || vit == TYPE_INTERNAL_DOUBLE ) && detail::would_overflow(vt, t, v.get()) )
|
||||
{
|
||||
t->Error("overflow promoting from unsigned/double to signed arithmetic value", v.get(), false, expr_location);
|
||||
return nullptr;
|
||||
|
@ -3841,7 +3815,7 @@ ValPtr check_and_promote(ValPtr v,
|
|||
break;
|
||||
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
if ( ( vit == TYPE_INTERNAL_DOUBLE || vit == TYPE_INTERNAL_INT) && Val::WouldOverflow(vt, t, v.get()) )
|
||||
if ( ( vit == TYPE_INTERNAL_DOUBLE || vit == TYPE_INTERNAL_INT) && detail::would_overflow(vt, t, v.get()) )
|
||||
{
|
||||
t->Error("overflow promoting from signed/double to unsigned arithmetic value", v.get(), false, expr_location);
|
||||
return nullptr;
|
||||
|
|
|
@ -207,8 +207,6 @@ UNDERLYING_ACCESSOR_DECL(TypeVal, zeek::Type*, AsType)
|
|||
void SetID(detail::ID* id);
|
||||
#endif
|
||||
|
||||
static bool WouldOverflow(const zeek::Type* from_type, const zeek::Type* to_type, const Val* val);
|
||||
|
||||
TableValPtr GetRecordFields();
|
||||
|
||||
StringValPtr ToJSON(bool only_loggable=false, RE_Matcher* re=nullptr);
|
||||
|
|
|
@ -2134,8 +2134,6 @@ ExprPtr ArithCoerceExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
|||
if ( ! op->IsReduced(c) )
|
||||
op = op->ReduceToSingleton(c, red_stmt);
|
||||
|
||||
auto t = type->InternalType();
|
||||
|
||||
if ( op->Tag() == EXPR_CONST )
|
||||
{
|
||||
const auto& t = GetType();
|
||||
|
@ -2153,9 +2151,18 @@ ExprPtr ArithCoerceExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
|
|||
if ( c->Optimizing() )
|
||||
return ThisPtr();
|
||||
|
||||
auto bt = op->GetType()->InternalType();
|
||||
const auto& ot = op->GetType();
|
||||
auto bt = ot->InternalType();
|
||||
auto tt = type->InternalType();
|
||||
|
||||
if ( t == bt )
|
||||
if ( ot->Tag() == TYPE_VECTOR )
|
||||
{
|
||||
bt = ot->Yield()->InternalType();
|
||||
tt = type->Yield()->InternalType();
|
||||
}
|
||||
|
||||
if ( bt == tt )
|
||||
// Can drop the conversion.
|
||||
return op;
|
||||
|
||||
return AssignToTemporary(c, red_stmt);
|
||||
|
|
|
@ -1141,8 +1141,9 @@ eval frame[z.v1].double_val = double(frame[z.v2].uint_val);
|
|||
|
||||
|
||||
macro EvalCoerceVec(coercer)
|
||||
Unref(frame[z.v1].vector_val);
|
||||
auto old_v1 = frame[z.v1].vector_val;
|
||||
frame[z.v1].vector_val = coercer(frame[z.v2].vector_val);
|
||||
Unref(old_v1); // delayed to allow for same value on both sides
|
||||
|
||||
internal-op Coerce-UI-Vec
|
||||
type VV
|
||||
|
|
|
@ -98,7 +98,6 @@ static void vec_exec(ZOp op, TypePtr t, VectorVal*& v1, VectorVal* v2,
|
|||
auto res_zv = new VectorVal(yt); \
|
||||
auto n = v.size(); \
|
||||
res_zv->Resize(n); \
|
||||
ASSERT(0); \
|
||||
auto& res = *res_zv->RawVec(); \
|
||||
for ( auto i = 0U; i < n; ++i ) \
|
||||
if ( v[i] ) \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue