mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
clang-format: Set IndentCaseBlocks to false
This commit is contained in:
parent
02206f3215
commit
4423574d26
58 changed files with 4729 additions and 4766 deletions
|
@ -47,7 +47,7 @@ ColumnLimit: 100
|
|||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
FixNamespaceComments: false
|
||||
IndentCaseLabels: true
|
||||
IndentCaseBlocks: true
|
||||
IndentCaseBlocks: false
|
||||
IndentExternBlock: NoIndent
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
|
|
559
src/Attr.cc
559
src/Attr.cc
|
@ -317,58 +317,96 @@ void Attributes::CheckAttr(Attr* a)
|
|||
|
||||
case ATTR_ADD_FUNC:
|
||||
case ATTR_DEL_FUNC:
|
||||
{
|
||||
bool is_add = a->Tag() == ATTR_ADD_FUNC;
|
||||
|
||||
const auto& at = a->GetExpr()->GetType();
|
||||
if ( at->Tag() != TYPE_FUNC )
|
||||
{
|
||||
bool is_add = a->Tag() == ATTR_ADD_FUNC;
|
||||
|
||||
const auto& at = a->GetExpr()->GetType();
|
||||
if ( at->Tag() != TYPE_FUNC )
|
||||
{
|
||||
a->GetExpr()->Error(is_add ? "&add_func must be a function"
|
||||
: "&delete_func must be a function");
|
||||
break;
|
||||
}
|
||||
|
||||
FuncType* aft = at->AsFuncType();
|
||||
if ( ! same_type(aft->Yield(), type) )
|
||||
{
|
||||
a->GetExpr()->Error(
|
||||
is_add ? "&add_func function must yield same type as variable"
|
||||
: "&delete_func function must yield same type as variable");
|
||||
break;
|
||||
}
|
||||
a->GetExpr()->Error(is_add ? "&add_func must be a function"
|
||||
: "&delete_func must be a function");
|
||||
break;
|
||||
}
|
||||
|
||||
FuncType* aft = at->AsFuncType();
|
||||
if ( ! same_type(aft->Yield(), type) )
|
||||
{
|
||||
a->GetExpr()->Error(is_add
|
||||
? "&add_func function must yield same type as variable"
|
||||
: "&delete_func function must yield same type as variable");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ATTR_DEFAULT:
|
||||
{
|
||||
// &default is allowed for global tables, since it's used in initialization
|
||||
// of table fields. it's not allowed otherwise.
|
||||
if ( global_var && ! type->IsTable() )
|
||||
{
|
||||
// &default is allowed for global tables, since it's used in initialization
|
||||
// of table fields. it's not allowed otherwise.
|
||||
if ( global_var && ! type->IsTable() )
|
||||
Error("&default is not valid for global variables except for tables");
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& atype = a->GetExpr()->GetType();
|
||||
|
||||
if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
|
||||
{
|
||||
if ( same_type(atype, type) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
// Record defaults may be promotable.
|
||||
if ( (type->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(), type->AsRecordType())) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
if ( type->Tag() == TYPE_TABLE && type->AsTableType()->IsUnspecifiedTable() )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
auto e = check_and_promote_expr(a->GetExpr(), type);
|
||||
|
||||
if ( e )
|
||||
{
|
||||
Error("&default is not valid for global variables except for tables");
|
||||
a->SetAttrExpr(std::move(e));
|
||||
// Ok.
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& atype = a->GetExpr()->GetType();
|
||||
a->GetExpr()->Error("&default value has inconsistent type", type.get());
|
||||
return;
|
||||
}
|
||||
|
||||
if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
|
||||
TableType* tt = type->AsTableType();
|
||||
const auto& ytype = tt->Yield();
|
||||
|
||||
if ( ! in_record )
|
||||
{
|
||||
// &default applies to the type itself.
|
||||
if ( ! same_type(atype, ytype) )
|
||||
{
|
||||
if ( same_type(atype, type) )
|
||||
// It can still be a default function.
|
||||
if ( atype->Tag() == TYPE_FUNC )
|
||||
{
|
||||
FuncType* f = atype->AsFuncType();
|
||||
if ( ! f->CheckArgs(tt->GetIndexTypes()) || ! same_type(f->Yield(), ytype) )
|
||||
Error("&default function type clash");
|
||||
|
||||
// Ok.
|
||||
break;
|
||||
}
|
||||
|
||||
// Record defaults may be promotable.
|
||||
if ( (type->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
// Table defaults may be promotable.
|
||||
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(),
|
||||
type->AsRecordType())) )
|
||||
ytype->AsRecordType())) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
if ( type->Tag() == TYPE_TABLE && type->AsTableType()->IsUnspecifiedTable() )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
auto e = check_and_promote_expr(a->GetExpr(), type);
|
||||
auto e = check_and_promote_expr(a->GetExpr(), ytype);
|
||||
|
||||
if ( e )
|
||||
{
|
||||
|
@ -377,120 +415,79 @@ void Attributes::CheckAttr(Attr* a)
|
|||
break;
|
||||
}
|
||||
|
||||
a->GetExpr()->Error("&default value has inconsistent type", type.get());
|
||||
return;
|
||||
Error("&default value has inconsistent type 2");
|
||||
}
|
||||
|
||||
TableType* tt = type->AsTableType();
|
||||
const auto& ytype = tt->Yield();
|
||||
// Ok.
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! in_record )
|
||||
{
|
||||
// &default applies to the type itself.
|
||||
if ( ! same_type(atype, ytype) )
|
||||
{
|
||||
// It can still be a default function.
|
||||
if ( atype->Tag() == TYPE_FUNC )
|
||||
{
|
||||
FuncType* f = atype->AsFuncType();
|
||||
if ( ! f->CheckArgs(tt->GetIndexTypes()) ||
|
||||
! same_type(f->Yield(), ytype) )
|
||||
Error("&default function type clash");
|
||||
|
||||
// Ok.
|
||||
break;
|
||||
}
|
||||
|
||||
// Table defaults may be promotable.
|
||||
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(),
|
||||
ytype->AsRecordType())) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
auto e = check_and_promote_expr(a->GetExpr(), ytype);
|
||||
|
||||
if ( e )
|
||||
{
|
||||
a->SetAttrExpr(std::move(e));
|
||||
// Ok.
|
||||
break;
|
||||
}
|
||||
|
||||
Error("&default value has inconsistent type 2");
|
||||
}
|
||||
else
|
||||
{
|
||||
// &default applies to record field.
|
||||
|
||||
if ( same_type(atype, type) )
|
||||
// Ok.
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
if ( (atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) )
|
||||
{
|
||||
// &default applies to record field.
|
||||
auto e = check_and_promote_expr(a->GetExpr(), type);
|
||||
|
||||
if ( same_type(atype, type) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
if ( (atype->Tag() == TYPE_TABLE &&
|
||||
atype->AsTableType()->IsUnspecifiedTable()) )
|
||||
if ( e )
|
||||
{
|
||||
auto e = check_and_promote_expr(a->GetExpr(), type);
|
||||
|
||||
if ( e )
|
||||
{
|
||||
a->SetAttrExpr(std::move(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Table defaults may be promotable.
|
||||
if ( ytype && ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType()) )
|
||||
// Ok.
|
||||
a->SetAttrExpr(std::move(e));
|
||||
break;
|
||||
|
||||
Error("&default value has inconsistent type");
|
||||
}
|
||||
}
|
||||
|
||||
// Table defaults may be promotable.
|
||||
if ( ytype && ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
|
||||
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType()) )
|
||||
// Ok.
|
||||
break;
|
||||
|
||||
Error("&default value has inconsistent type");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ATTR_EXPIRE_READ:
|
||||
{
|
||||
if ( Find(ATTR_BROKER_STORE) )
|
||||
Error("&broker_store and &read_expire cannot be used simultaneously");
|
||||
{
|
||||
if ( Find(ATTR_BROKER_STORE) )
|
||||
Error("&broker_store and &read_expire cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BACKEND) )
|
||||
Error("&backend and &read_expire cannot be used simultaneously");
|
||||
}
|
||||
if ( Find(ATTR_BACKEND) )
|
||||
Error("&backend and &read_expire cannot be used simultaneously");
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
case ATTR_EXPIRE_WRITE:
|
||||
case ATTR_EXPIRE_CREATE:
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("expiration only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
int num_expires = 0;
|
||||
|
||||
for ( const auto& a : attrs )
|
||||
{
|
||||
if ( a->Tag() == ATTR_EXPIRE_READ || a->Tag() == ATTR_EXPIRE_WRITE ||
|
||||
a->Tag() == ATTR_EXPIRE_CREATE )
|
||||
num_expires++;
|
||||
}
|
||||
|
||||
if ( num_expires > 1 )
|
||||
{
|
||||
Error("set/table can only have one of &read_expire, &write_expire, "
|
||||
"&create_expire");
|
||||
break;
|
||||
}
|
||||
Error("expiration only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
int num_expires = 0;
|
||||
|
||||
for ( const auto& a : attrs )
|
||||
{
|
||||
if ( a->Tag() == ATTR_EXPIRE_READ || a->Tag() == ATTR_EXPIRE_WRITE ||
|
||||
a->Tag() == ATTR_EXPIRE_CREATE )
|
||||
num_expires++;
|
||||
}
|
||||
|
||||
if ( num_expires > 1 )
|
||||
{
|
||||
Error("set/table can only have one of &read_expire, &write_expire, "
|
||||
"&create_expire");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//### not easy to test this w/o knowing the ID.
|
||||
if ( ! global_var )
|
||||
|
@ -500,172 +497,172 @@ void Attributes::CheckAttr(Attr* a)
|
|||
break;
|
||||
|
||||
case ATTR_EXPIRE_FUNC:
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("expiration only applicable to tables");
|
||||
break;
|
||||
}
|
||||
|
||||
type->AsTableType()->CheckExpireFuncCompatibility({NewRef{}, a});
|
||||
|
||||
if ( Find(ATTR_BROKER_STORE) )
|
||||
Error("&broker_store and &expire_func cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BACKEND) )
|
||||
Error("&backend and &expire_func cannot be used simultaneously");
|
||||
|
||||
Error("expiration only applicable to tables");
|
||||
break;
|
||||
}
|
||||
|
||||
type->AsTableType()->CheckExpireFuncCompatibility({NewRef{}, a});
|
||||
|
||||
if ( Find(ATTR_BROKER_STORE) )
|
||||
Error("&broker_store and &expire_func cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BACKEND) )
|
||||
Error("&backend and &expire_func cannot be used simultaneously");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ATTR_ON_CHANGE:
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("&on_change only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& change_func = a->GetExpr();
|
||||
|
||||
if ( change_func->GetType()->Tag() != TYPE_FUNC ||
|
||||
change_func->GetType()->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION )
|
||||
Error("&on_change attribute is not a function");
|
||||
|
||||
const FuncType* c_ft = change_func->GetType()->AsFuncType();
|
||||
|
||||
if ( c_ft->Yield()->Tag() != TYPE_VOID )
|
||||
{
|
||||
Error("&on_change must not return a value");
|
||||
break;
|
||||
}
|
||||
|
||||
const TableType* the_table = type->AsTableType();
|
||||
|
||||
if ( the_table->IsUnspecifiedTable() )
|
||||
break;
|
||||
|
||||
const auto& args = c_ft->ParamList()->GetTypes();
|
||||
const auto& t_indexes = the_table->GetIndexTypes();
|
||||
if ( args.size() != (type->IsSet() ? 2 : 3) + t_indexes.size() )
|
||||
{
|
||||
Error("&on_change function has incorrect number of arguments");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! same_type(args[0], the_table->AsTableType()) )
|
||||
{
|
||||
Error("&on_change: first argument must be of same type as table");
|
||||
break;
|
||||
}
|
||||
|
||||
// can't check exact type here yet - the data structures don't exist yet.
|
||||
if ( args[1]->Tag() != TYPE_ENUM )
|
||||
{
|
||||
Error("&on_change: second argument must be a TableChange enum");
|
||||
break;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < t_indexes.size(); i++ )
|
||||
{
|
||||
if ( ! same_type(args[2 + i], t_indexes[i]) )
|
||||
{
|
||||
Error("&on_change: index types do not match table");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! type->IsSet() )
|
||||
if ( ! same_type(args[2 + t_indexes.size()], the_table->Yield()) )
|
||||
{
|
||||
Error("&on_change: value type does not match table");
|
||||
break;
|
||||
}
|
||||
Error("&on_change only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& change_func = a->GetExpr();
|
||||
|
||||
if ( change_func->GetType()->Tag() != TYPE_FUNC ||
|
||||
change_func->GetType()->AsFuncType()->Flavor() != FUNC_FLAVOR_FUNCTION )
|
||||
Error("&on_change attribute is not a function");
|
||||
|
||||
const FuncType* c_ft = change_func->GetType()->AsFuncType();
|
||||
|
||||
if ( c_ft->Yield()->Tag() != TYPE_VOID )
|
||||
{
|
||||
Error("&on_change must not return a value");
|
||||
break;
|
||||
}
|
||||
|
||||
const TableType* the_table = type->AsTableType();
|
||||
|
||||
if ( the_table->IsUnspecifiedTable() )
|
||||
break;
|
||||
|
||||
const auto& args = c_ft->ParamList()->GetTypes();
|
||||
const auto& t_indexes = the_table->GetIndexTypes();
|
||||
if ( args.size() != (type->IsSet() ? 2 : 3) + t_indexes.size() )
|
||||
{
|
||||
Error("&on_change function has incorrect number of arguments");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! same_type(args[0], the_table->AsTableType()) )
|
||||
{
|
||||
Error("&on_change: first argument must be of same type as table");
|
||||
break;
|
||||
}
|
||||
|
||||
// can't check exact type here yet - the data structures don't exist yet.
|
||||
if ( args[1]->Tag() != TYPE_ENUM )
|
||||
{
|
||||
Error("&on_change: second argument must be a TableChange enum");
|
||||
break;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < t_indexes.size(); i++ )
|
||||
{
|
||||
if ( ! same_type(args[2 + i], t_indexes[i]) )
|
||||
{
|
||||
Error("&on_change: index types do not match table");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! type->IsSet() )
|
||||
if ( ! same_type(args[2 + t_indexes.size()], the_table->Yield()) )
|
||||
{
|
||||
Error("&on_change: value type does not match table");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ATTR_BACKEND:
|
||||
{
|
||||
if ( ! global_var || type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
if ( ! global_var || type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("&backend only applicable to global sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
// cannot do better equality check - the Broker types are not
|
||||
// actually existing yet when we are here. We will do that
|
||||
// later - before actually attaching to a broker store
|
||||
if ( a->GetExpr()->GetType()->Tag() != TYPE_ENUM )
|
||||
{
|
||||
Error("&backend must take an enum argument");
|
||||
break;
|
||||
}
|
||||
|
||||
// Only support atomic types for the moment, unless
|
||||
// explicitly overriden
|
||||
if ( ! type->AsTableType()->IsSet() &&
|
||||
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
|
||||
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
|
||||
{
|
||||
Error("&backend only supports atomic types as table value");
|
||||
}
|
||||
|
||||
if ( Find(ATTR_EXPIRE_FUNC) )
|
||||
Error("&backend and &expire_func cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_EXPIRE_READ) )
|
||||
Error("&backend and &read_expire cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BROKER_STORE) )
|
||||
Error("&backend and &broker_store cannot be used simultaneously");
|
||||
|
||||
Error("&backend only applicable to global sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
// cannot do better equality check - the Broker types are not
|
||||
// actually existing yet when we are here. We will do that
|
||||
// later - before actually attaching to a broker store
|
||||
if ( a->GetExpr()->GetType()->Tag() != TYPE_ENUM )
|
||||
{
|
||||
Error("&backend must take an enum argument");
|
||||
break;
|
||||
}
|
||||
|
||||
// Only support atomic types for the moment, unless
|
||||
// explicitly overriden
|
||||
if ( ! type->AsTableType()->IsSet() &&
|
||||
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
|
||||
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
|
||||
{
|
||||
Error("&backend only supports atomic types as table value");
|
||||
}
|
||||
|
||||
if ( Find(ATTR_EXPIRE_FUNC) )
|
||||
Error("&backend and &expire_func cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_EXPIRE_READ) )
|
||||
Error("&backend and &read_expire cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BROKER_STORE) )
|
||||
Error("&backend and &broker_store cannot be used simultaneously");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ATTR_BROKER_STORE:
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("&broker_store only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
if ( a->GetExpr()->GetType()->Tag() != TYPE_STRING )
|
||||
{
|
||||
Error("&broker_store must take a string argument");
|
||||
break;
|
||||
}
|
||||
|
||||
// Only support atomic types for the moment, unless
|
||||
// explicitly overriden
|
||||
if ( ! type->AsTableType()->IsSet() &&
|
||||
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
|
||||
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
|
||||
{
|
||||
Error("&broker_store only supports atomic types as table value");
|
||||
}
|
||||
|
||||
if ( Find(ATTR_EXPIRE_FUNC) )
|
||||
Error("&broker_store and &expire_func cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_EXPIRE_READ) )
|
||||
Error("&broker_store and &read_expire cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BACKEND) )
|
||||
Error("&backend and &broker_store cannot be used simultaneously");
|
||||
|
||||
Error("&broker_store only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
|
||||
case ATTR_BROKER_STORE_ALLOW_COMPLEX:
|
||||
if ( a->GetExpr()->GetType()->Tag() != TYPE_STRING )
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("&broker_allow_complex_type only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
Error("&broker_store must take a string argument");
|
||||
break;
|
||||
}
|
||||
|
||||
// Only support atomic types for the moment, unless
|
||||
// explicitly overriden
|
||||
if ( ! type->AsTableType()->IsSet() &&
|
||||
! input::Manager::IsCompatibleType(type->AsTableType()->Yield().get(), true) &&
|
||||
! Find(ATTR_BROKER_STORE_ALLOW_COMPLEX) )
|
||||
{
|
||||
Error("&broker_store only supports atomic types as table value");
|
||||
}
|
||||
|
||||
if ( Find(ATTR_EXPIRE_FUNC) )
|
||||
Error("&broker_store and &expire_func cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_EXPIRE_READ) )
|
||||
Error("&broker_store and &read_expire cannot be used simultaneously");
|
||||
|
||||
if ( Find(ATTR_BACKEND) )
|
||||
Error("&backend and &broker_store cannot be used simultaneously");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ATTR_BROKER_STORE_ALLOW_COMPLEX:
|
||||
{
|
||||
if ( type->Tag() != TYPE_TABLE )
|
||||
{
|
||||
Error("&broker_allow_complex_type only applicable to sets/tables");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case ATTR_TRACKED:
|
||||
// FIXME: Check here for global ID?
|
||||
break;
|
||||
|
@ -695,24 +692,24 @@ void Attributes::CheckAttr(Attr* a)
|
|||
break;
|
||||
|
||||
case ATTR_TYPE_COLUMN:
|
||||
{
|
||||
if ( type->Tag() != TYPE_PORT )
|
||||
{
|
||||
if ( type->Tag() != TYPE_PORT )
|
||||
{
|
||||
Error("type_column tag only applicable to ports");
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& atype = a->GetExpr()->GetType();
|
||||
|
||||
if ( atype->Tag() != TYPE_STRING )
|
||||
{
|
||||
Error("type column needs to have a string argument");
|
||||
break;
|
||||
}
|
||||
|
||||
Error("type_column tag only applicable to ports");
|
||||
break;
|
||||
}
|
||||
|
||||
const auto& atype = a->GetExpr()->GetType();
|
||||
|
||||
if ( atype->Tag() != TYPE_STRING )
|
||||
{
|
||||
Error("type column needs to have a string argument");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BadTag("Attributes::CheckAttr", attr_name(a->Tag()));
|
||||
}
|
||||
|
|
1099
src/CompHash.cc
1099
src/CompHash.cc
File diff suppressed because it is too large
Load diff
|
@ -348,19 +348,19 @@ void DbgBreakpoint::PrintHitMsg()
|
|||
case BP_STMT:
|
||||
case BP_FUNC:
|
||||
case BP_LINE:
|
||||
{
|
||||
ODesc d;
|
||||
Frame* f = g_frame_stack.back();
|
||||
const ScriptFunc* func = f->GetFunction();
|
||||
{
|
||||
ODesc d;
|
||||
Frame* f = g_frame_stack.back();
|
||||
const ScriptFunc* func = f->GetFunction();
|
||||
|
||||
if ( func )
|
||||
func->DescribeDebug(&d, f->GetFuncArgs());
|
||||
if ( func )
|
||||
func->DescribeDebug(&d, f->GetFuncArgs());
|
||||
|
||||
const Location* loc = at_stmt->GetLocationInfo();
|
||||
const Location* loc = at_stmt->GetLocationInfo();
|
||||
|
||||
debug_msg("Breakpoint %d, %s at %s:%d\n", GetID(), d.Description(), loc->filename,
|
||||
loc->first_line);
|
||||
}
|
||||
debug_msg("Breakpoint %d, %s at %s:%d\n", GetID(), d.Description(), loc->filename,
|
||||
loc->first_line);
|
||||
}
|
||||
return;
|
||||
|
||||
case BP_TIME:
|
||||
|
|
240
src/Expr.cc
240
src/Expr.cc
|
@ -320,75 +320,75 @@ const char* assign_to_index(ValPtr v1, ValPtr v2, ValPtr v3, bool& iterators_inv
|
|||
switch ( v1->GetType()->Tag() )
|
||||
{
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
const ListVal* lv = v2->AsListVal();
|
||||
VectorVal* v1_vect = v1->AsVectorVal();
|
||||
|
||||
if ( lv->Length() > 1 )
|
||||
{
|
||||
const ListVal* lv = v2->AsListVal();
|
||||
VectorVal* v1_vect = v1->AsVectorVal();
|
||||
auto len = v1_vect->Size();
|
||||
bro_int_t first = get_slice_index(lv->Idx(0)->CoerceToInt(), len);
|
||||
bro_int_t last = get_slice_index(lv->Idx(1)->CoerceToInt(), len);
|
||||
|
||||
if ( lv->Length() > 1 )
|
||||
{
|
||||
auto len = v1_vect->Size();
|
||||
bro_int_t first = get_slice_index(lv->Idx(0)->CoerceToInt(), len);
|
||||
bro_int_t last = get_slice_index(lv->Idx(1)->CoerceToInt(), len);
|
||||
// Remove the elements from the vector within the slice.
|
||||
for ( auto idx = first; idx < last; idx++ )
|
||||
v1_vect->Remove(first);
|
||||
|
||||
// Remove the elements from the vector within the slice.
|
||||
for ( auto idx = first; idx < last; idx++ )
|
||||
v1_vect->Remove(first);
|
||||
// Insert the new elements starting at the first
|
||||
// position.
|
||||
|
||||
// Insert the new elements starting at the first
|
||||
// position.
|
||||
VectorVal* v_vect = v3->AsVectorVal();
|
||||
|
||||
VectorVal* v_vect = v3->AsVectorVal();
|
||||
|
||||
for ( auto idx = 0u; idx < v_vect->Size(); idx++, first++ )
|
||||
v1_vect->Insert(first, v_vect->ValAt(idx));
|
||||
}
|
||||
|
||||
else if ( ! v1_vect->Assign(lv->Idx(0)->CoerceToUnsigned(), std::move(v3)) )
|
||||
{
|
||||
v3 = std::move(v_extra);
|
||||
|
||||
if ( v3 )
|
||||
{
|
||||
ODesc d;
|
||||
v3->Describe(&d);
|
||||
const auto& vt = v3->GetType();
|
||||
auto vtt = vt->Tag();
|
||||
std::string tn = vtt == TYPE_RECORD ? vt->GetName() : type_name(vtt);
|
||||
return util::fmt(
|
||||
"vector index assignment failed for invalid type '%s', value: %s",
|
||||
tn.data(), d.Description());
|
||||
}
|
||||
else
|
||||
return "assignment failed with null value";
|
||||
}
|
||||
break;
|
||||
for ( auto idx = 0u; idx < v_vect->Size(); idx++, first++ )
|
||||
v1_vect->Insert(first, v_vect->ValAt(idx));
|
||||
}
|
||||
|
||||
else if ( ! v1_vect->Assign(lv->Idx(0)->CoerceToUnsigned(), std::move(v3)) )
|
||||
{
|
||||
v3 = std::move(v_extra);
|
||||
|
||||
if ( v3 )
|
||||
{
|
||||
ODesc d;
|
||||
v3->Describe(&d);
|
||||
const auto& vt = v3->GetType();
|
||||
auto vtt = vt->Tag();
|
||||
std::string tn = vtt == TYPE_RECORD ? vt->GetName() : type_name(vtt);
|
||||
return util::fmt(
|
||||
"vector index assignment failed for invalid type '%s', value: %s",
|
||||
tn.data(), d.Description());
|
||||
}
|
||||
else
|
||||
return "assignment failed with null value";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
if ( ! v1->AsTableVal()->Assign(std::move(v2), std::move(v3), true,
|
||||
&iterators_invalidated) )
|
||||
{
|
||||
if ( ! v1->AsTableVal()->Assign(std::move(v2), std::move(v3), true,
|
||||
&iterators_invalidated) )
|
||||
v3 = std::move(v_extra);
|
||||
|
||||
if ( v3 )
|
||||
{
|
||||
v3 = std::move(v_extra);
|
||||
|
||||
if ( v3 )
|
||||
{
|
||||
ODesc d;
|
||||
v3->Describe(&d);
|
||||
const auto& vt = v3->GetType();
|
||||
auto vtt = vt->Tag();
|
||||
std::string tn = vtt == TYPE_RECORD ? vt->GetName() : type_name(vtt);
|
||||
return util::fmt(
|
||||
"table index assignment failed for invalid type '%s', value: %s",
|
||||
tn.data(), d.Description());
|
||||
}
|
||||
else
|
||||
return "assignment failed with null value";
|
||||
ODesc d;
|
||||
v3->Describe(&d);
|
||||
const auto& vt = v3->GetType();
|
||||
auto vtt = vt->Tag();
|
||||
std::string tn = vtt == TYPE_RECORD ? vt->GetName() : type_name(vtt);
|
||||
return util::fmt(
|
||||
"table index assignment failed for invalid type '%s', value: %s", tn.data(),
|
||||
d.Description());
|
||||
}
|
||||
|
||||
break;
|
||||
else
|
||||
return "assignment failed with null value";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_STRING:
|
||||
return "assignment via string index accessor not allowed";
|
||||
break;
|
||||
|
@ -925,54 +925,54 @@ ValPtr BinaryExpr::Fold(Val* v1, Val* v2) const
|
|||
DO_FOLD(*);
|
||||
break;
|
||||
case EXPR_DIVIDE:
|
||||
{
|
||||
if ( is_integral )
|
||||
{
|
||||
if ( is_integral )
|
||||
{
|
||||
if ( i2 == 0 )
|
||||
RuntimeError("division by zero");
|
||||
if ( i2 == 0 )
|
||||
RuntimeError("division by zero");
|
||||
|
||||
i3 = i1 / i2;
|
||||
}
|
||||
|
||||
else if ( is_unsigned )
|
||||
{
|
||||
if ( u2 == 0 )
|
||||
RuntimeError("division by zero");
|
||||
|
||||
u3 = u1 / u2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( d2 == 0 )
|
||||
RuntimeError("division by zero");
|
||||
|
||||
d3 = d1 / d2;
|
||||
}
|
||||
i3 = i1 / i2;
|
||||
}
|
||||
|
||||
else if ( is_unsigned )
|
||||
{
|
||||
if ( u2 == 0 )
|
||||
RuntimeError("division by zero");
|
||||
|
||||
u3 = u1 / u2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( d2 == 0 )
|
||||
RuntimeError("division by zero");
|
||||
|
||||
d3 = d1 / d2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_MOD:
|
||||
{
|
||||
if ( is_integral )
|
||||
{
|
||||
if ( is_integral )
|
||||
{
|
||||
if ( i2 == 0 )
|
||||
RuntimeError("modulo by zero");
|
||||
if ( i2 == 0 )
|
||||
RuntimeError("modulo by zero");
|
||||
|
||||
i3 = i1 % i2;
|
||||
}
|
||||
|
||||
else if ( is_unsigned )
|
||||
{
|
||||
if ( u2 == 0 )
|
||||
RuntimeError("modulo by zero");
|
||||
|
||||
u3 = u1 % u2;
|
||||
}
|
||||
|
||||
else
|
||||
RuntimeErrorWithCallStack("bad type in BinaryExpr::Fold");
|
||||
i3 = i1 % i2;
|
||||
}
|
||||
|
||||
else if ( is_unsigned )
|
||||
{
|
||||
if ( u2 == 0 )
|
||||
RuntimeError("modulo by zero");
|
||||
|
||||
u3 = u1 % u2;
|
||||
}
|
||||
|
||||
else
|
||||
RuntimeErrorWithCallStack("bad type in BinaryExpr::Fold");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EXPR_AND:
|
||||
|
@ -1061,13 +1061,13 @@ ValPtr BinaryExpr::StringFold(Val* v1, Val* v2) const
|
|||
|
||||
case EXPR_ADD:
|
||||
case EXPR_ADD_TO:
|
||||
{
|
||||
std::vector<const String*> strings;
|
||||
strings.push_back(s1);
|
||||
strings.push_back(s2);
|
||||
{
|
||||
std::vector<const String*> strings;
|
||||
strings.push_back(s1);
|
||||
strings.push_back(s2);
|
||||
|
||||
return make_intrusive<StringVal>(concatenate(strings));
|
||||
}
|
||||
return make_intrusive<StringVal>(concatenate(strings));
|
||||
}
|
||||
|
||||
default:
|
||||
BadTag("BinaryExpr::StringFold", expr_name(tag));
|
||||
|
@ -1102,24 +1102,24 @@ ValPtr BinaryExpr::SetFold(Val* v1, Val* v2) const
|
|||
return tv1->Intersection(*tv2);
|
||||
|
||||
case EXPR_OR:
|
||||
{
|
||||
auto rval = v1->Clone();
|
||||
{
|
||||
auto rval = v1->Clone();
|
||||
|
||||
if ( ! tv2->AddTo(rval.get(), false, false) )
|
||||
reporter->InternalError("set union failed to type check");
|
||||
if ( ! tv2->AddTo(rval.get(), false, false) )
|
||||
reporter->InternalError("set union failed to type check");
|
||||
|
||||
return rval;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
case EXPR_SUB:
|
||||
{
|
||||
auto rval = v1->Clone();
|
||||
{
|
||||
auto rval = v1->Clone();
|
||||
|
||||
if ( ! tv2->RemoveFrom(rval.get()) )
|
||||
reporter->InternalError("set difference failed to type check");
|
||||
if ( ! tv2->RemoveFrom(rval.get()) )
|
||||
reporter->InternalError("set difference failed to type check");
|
||||
|
||||
return rval;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
case EXPR_EQ:
|
||||
res = tv1->EqualTo(*tv2);
|
||||
|
@ -3020,15 +3020,15 @@ ValPtr IndexExpr::Fold(Val* v1, Val* v2) const
|
|||
switch ( v1->GetType()->Tag() )
|
||||
{
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
VectorVal* vect = v1->AsVectorVal();
|
||||
const ListVal* lv = v2->AsListVal();
|
||||
{
|
||||
VectorVal* vect = v1->AsVectorVal();
|
||||
const ListVal* lv = v2->AsListVal();
|
||||
|
||||
if ( lv->Length() == 1 )
|
||||
v = vect->ValAt(lv->Idx(0)->CoerceToUnsigned());
|
||||
else
|
||||
return index_slice(vect, lv);
|
||||
}
|
||||
if ( lv->Length() == 1 )
|
||||
v = vect->ValAt(lv->Idx(0)->CoerceToUnsigned());
|
||||
else
|
||||
return index_slice(vect, lv);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_TABLE:
|
||||
|
|
35
src/Func.cc
35
src/Func.cc
|
@ -272,26 +272,25 @@ void Func::CheckPluginResult(bool handled, const ValPtr& hook_result, FunctionFl
|
|||
break;
|
||||
|
||||
case FUNC_FLAVOR_FUNCTION:
|
||||
{
|
||||
const auto& yt = GetType()->Yield();
|
||||
|
||||
if ( (! yt) || yt->Tag() == TYPE_VOID )
|
||||
{
|
||||
const auto& yt = GetType()->Yield();
|
||||
|
||||
if ( (! yt) || yt->Tag() == TYPE_VOID )
|
||||
{
|
||||
if ( hook_result )
|
||||
reporter->InternalError(
|
||||
"plugin returned non-void result for void method %s", this->Name());
|
||||
}
|
||||
|
||||
else if ( hook_result && hook_result->GetType()->Tag() != yt->Tag() &&
|
||||
yt->Tag() != TYPE_ANY )
|
||||
{
|
||||
reporter->InternalError(
|
||||
"plugin returned wrong type (got %d, expecting %d) for %s",
|
||||
hook_result->GetType()->Tag(), yt->Tag(), this->Name());
|
||||
}
|
||||
|
||||
break;
|
||||
if ( hook_result )
|
||||
reporter->InternalError("plugin returned non-void result for void method %s",
|
||||
this->Name());
|
||||
}
|
||||
|
||||
else if ( hook_result && hook_result->GetType()->Tag() != yt->Tag() &&
|
||||
yt->Tag() != TYPE_ANY )
|
||||
{
|
||||
reporter->InternalError("plugin returned wrong type (got %d, expecting %d) for %s",
|
||||
hook_result->GetType()->Tag(), yt->Tag(), this->Name());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
600
src/IP.cc
600
src/IP.cc
|
@ -58,249 +58,244 @@ RecordValPtr IPv6_Hdr::ToVal(VectorValPtr chain) const
|
|||
switch ( type )
|
||||
{
|
||||
case IPPROTO_IPV6:
|
||||
{
|
||||
static auto ip6_hdr_type = id::find_type<RecordType>("ip6_hdr");
|
||||
rv = make_intrusive<RecordVal>(ip6_hdr_type);
|
||||
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
||||
rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20);
|
||||
rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff);
|
||||
rv->Assign(2, ntohs(ip6->ip6_plen));
|
||||
rv->Assign(3, ip6->ip6_nxt);
|
||||
rv->Assign(4, ip6->ip6_hlim);
|
||||
rv->Assign(5, make_intrusive<AddrVal>(IPAddr(ip6->ip6_src)));
|
||||
rv->Assign(6, make_intrusive<AddrVal>(IPAddr(ip6->ip6_dst)));
|
||||
if ( ! chain )
|
||||
chain =
|
||||
make_intrusive<VectorVal>(id::find_type<VectorType>("ip6_ext_hdr_chain"));
|
||||
rv->Assign(7, std::move(chain));
|
||||
}
|
||||
{
|
||||
static auto ip6_hdr_type = id::find_type<RecordType>("ip6_hdr");
|
||||
rv = make_intrusive<RecordVal>(ip6_hdr_type);
|
||||
const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data;
|
||||
rv->Assign(0, (ntohl(ip6->ip6_flow) & 0x0ff00000) >> 20);
|
||||
rv->Assign(1, ntohl(ip6->ip6_flow) & 0x000fffff);
|
||||
rv->Assign(2, ntohs(ip6->ip6_plen));
|
||||
rv->Assign(3, ip6->ip6_nxt);
|
||||
rv->Assign(4, ip6->ip6_hlim);
|
||||
rv->Assign(5, make_intrusive<AddrVal>(IPAddr(ip6->ip6_src)));
|
||||
rv->Assign(6, make_intrusive<AddrVal>(IPAddr(ip6->ip6_dst)));
|
||||
if ( ! chain )
|
||||
chain = make_intrusive<VectorVal>(id::find_type<VectorType>("ip6_ext_hdr_chain"));
|
||||
rv->Assign(7, std::move(chain));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_HOPOPTS:
|
||||
{
|
||||
static auto ip6_hopopts_type = id::find_type<RecordType>("ip6_hopopts");
|
||||
rv = make_intrusive<RecordVal>(ip6_hopopts_type);
|
||||
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
||||
rv->Assign(0, hbh->ip6h_nxt);
|
||||
rv->Assign(1, hbh->ip6h_len);
|
||||
uint16_t off = 2 * sizeof(uint8_t);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
}
|
||||
{
|
||||
static auto ip6_hopopts_type = id::find_type<RecordType>("ip6_hopopts");
|
||||
rv = make_intrusive<RecordVal>(ip6_hopopts_type);
|
||||
const struct ip6_hbh* hbh = (const struct ip6_hbh*)data;
|
||||
rv->Assign(0, hbh->ip6h_nxt);
|
||||
rv->Assign(1, hbh->ip6h_len);
|
||||
uint16_t off = 2 * sizeof(uint8_t);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_DSTOPTS:
|
||||
{
|
||||
static auto ip6_dstopts_type = id::find_type<RecordType>("ip6_dstopts");
|
||||
rv = make_intrusive<RecordVal>(ip6_dstopts_type);
|
||||
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
||||
rv->Assign(0, dst->ip6d_nxt);
|
||||
rv->Assign(1, dst->ip6d_len);
|
||||
uint16_t off = 2 * sizeof(uint8_t);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
}
|
||||
{
|
||||
static auto ip6_dstopts_type = id::find_type<RecordType>("ip6_dstopts");
|
||||
rv = make_intrusive<RecordVal>(ip6_dstopts_type);
|
||||
const struct ip6_dest* dst = (const struct ip6_dest*)data;
|
||||
rv->Assign(0, dst->ip6d_nxt);
|
||||
rv->Assign(1, dst->ip6d_len);
|
||||
uint16_t off = 2 * sizeof(uint8_t);
|
||||
rv->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ROUTING:
|
||||
{
|
||||
static auto ip6_routing_type = id::find_type<RecordType>("ip6_routing");
|
||||
rv = make_intrusive<RecordVal>(ip6_routing_type);
|
||||
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
||||
rv->Assign(0, rt->ip6r_nxt);
|
||||
rv->Assign(1, rt->ip6r_len);
|
||||
rv->Assign(2, rt->ip6r_type);
|
||||
rv->Assign(3, rt->ip6r_segleft);
|
||||
uint16_t off = 4 * sizeof(uint8_t);
|
||||
rv->Assign(4, new String(data + off, Length() - off, true));
|
||||
}
|
||||
{
|
||||
static auto ip6_routing_type = id::find_type<RecordType>("ip6_routing");
|
||||
rv = make_intrusive<RecordVal>(ip6_routing_type);
|
||||
const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data;
|
||||
rv->Assign(0, rt->ip6r_nxt);
|
||||
rv->Assign(1, rt->ip6r_len);
|
||||
rv->Assign(2, rt->ip6r_type);
|
||||
rv->Assign(3, rt->ip6r_segleft);
|
||||
uint16_t off = 4 * sizeof(uint8_t);
|
||||
rv->Assign(4, new String(data + off, Length() - off, true));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_FRAGMENT:
|
||||
{
|
||||
static auto ip6_fragment_type = id::find_type<RecordType>("ip6_fragment");
|
||||
rv = make_intrusive<RecordVal>(ip6_fragment_type);
|
||||
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
||||
rv->Assign(0, frag->ip6f_nxt);
|
||||
rv->Assign(1, frag->ip6f_reserved);
|
||||
rv->Assign(2, (ntohs(frag->ip6f_offlg) & 0xfff8) >> 3);
|
||||
rv->Assign(3, (ntohs(frag->ip6f_offlg) & 0x0006) >> 1);
|
||||
rv->Assign(4, static_cast<bool>(ntohs(frag->ip6f_offlg) & 0x0001));
|
||||
rv->Assign(5, ntohl(frag->ip6f_ident));
|
||||
}
|
||||
{
|
||||
static auto ip6_fragment_type = id::find_type<RecordType>("ip6_fragment");
|
||||
rv = make_intrusive<RecordVal>(ip6_fragment_type);
|
||||
const struct ip6_frag* frag = (const struct ip6_frag*)data;
|
||||
rv->Assign(0, frag->ip6f_nxt);
|
||||
rv->Assign(1, frag->ip6f_reserved);
|
||||
rv->Assign(2, (ntohs(frag->ip6f_offlg) & 0xfff8) >> 3);
|
||||
rv->Assign(3, (ntohs(frag->ip6f_offlg) & 0x0006) >> 1);
|
||||
rv->Assign(4, static_cast<bool>(ntohs(frag->ip6f_offlg) & 0x0001));
|
||||
rv->Assign(5, ntohl(frag->ip6f_ident));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_AH:
|
||||
{
|
||||
static auto ip6_ah_type = id::find_type<RecordType>("ip6_ah");
|
||||
rv = make_intrusive<RecordVal>(ip6_ah_type);
|
||||
rv->Assign(0, ((ip6_ext*)data)->ip6e_nxt);
|
||||
rv->Assign(1, ((ip6_ext*)data)->ip6e_len);
|
||||
rv->Assign(2, ntohs(((uint16_t*)data)[1]));
|
||||
rv->Assign(3, ntohl(((uint32_t*)data)[1]));
|
||||
{
|
||||
static auto ip6_ah_type = id::find_type<RecordType>("ip6_ah");
|
||||
rv = make_intrusive<RecordVal>(ip6_ah_type);
|
||||
rv->Assign(0, ((ip6_ext*)data)->ip6e_nxt);
|
||||
rv->Assign(1, ((ip6_ext*)data)->ip6e_len);
|
||||
rv->Assign(2, ntohs(((uint16_t*)data)[1]));
|
||||
rv->Assign(3, ntohl(((uint32_t*)data)[1]));
|
||||
|
||||
if ( Length() >= 12 )
|
||||
{
|
||||
// Sequence Number and ICV fields can only be extracted if
|
||||
// Payload Len was non-zero for this header.
|
||||
rv->Assign(4, ntohl(((uint32_t*)data)[2]));
|
||||
uint16_t off = 3 * sizeof(uint32_t);
|
||||
rv->Assign(5, new String(data + off, Length() - off, true));
|
||||
}
|
||||
if ( Length() >= 12 )
|
||||
{
|
||||
// Sequence Number and ICV fields can only be extracted if
|
||||
// Payload Len was non-zero for this header.
|
||||
rv->Assign(4, ntohl(((uint32_t*)data)[2]));
|
||||
uint16_t off = 3 * sizeof(uint32_t);
|
||||
rv->Assign(5, new String(data + off, Length() - off, true));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ESP:
|
||||
{
|
||||
static auto ip6_esp_type = id::find_type<RecordType>("ip6_esp");
|
||||
rv = make_intrusive<RecordVal>(ip6_esp_type);
|
||||
const uint32_t* esp = (const uint32_t*)data;
|
||||
rv->Assign(0, ntohl(esp[0]));
|
||||
rv->Assign(1, ntohl(esp[1]));
|
||||
}
|
||||
{
|
||||
static auto ip6_esp_type = id::find_type<RecordType>("ip6_esp");
|
||||
rv = make_intrusive<RecordVal>(ip6_esp_type);
|
||||
const uint32_t* esp = (const uint32_t*)data;
|
||||
rv->Assign(0, ntohl(esp[0]));
|
||||
rv->Assign(1, ntohl(esp[1]));
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_MOBILITY:
|
||||
{
|
||||
static auto ip6_mob_type = id::find_type<RecordType>("ip6_mobility_hdr");
|
||||
rv = make_intrusive<RecordVal>(ip6_mob_type);
|
||||
const struct ip6_mobility* mob = (const struct ip6_mobility*)data;
|
||||
rv->Assign(0, mob->ip6mob_payload);
|
||||
rv->Assign(1, mob->ip6mob_len);
|
||||
rv->Assign(2, mob->ip6mob_type);
|
||||
rv->Assign(3, mob->ip6mob_rsv);
|
||||
rv->Assign(4, ntohs(mob->ip6mob_chksum));
|
||||
|
||||
static auto ip6_mob_msg_type = id::find_type<RecordType>("ip6_mobility_msg");
|
||||
auto msg = make_intrusive<RecordVal>(ip6_mob_msg_type);
|
||||
msg->Assign(0, mob->ip6mob_type);
|
||||
|
||||
uint16_t off = sizeof(ip6_mobility);
|
||||
const u_char* msg_data = data + off;
|
||||
|
||||
static auto ip6_mob_brr_type = id::find_type<RecordType>("ip6_mobility_brr");
|
||||
static auto ip6_mob_hoti_type = id::find_type<RecordType>("ip6_mobility_hoti");
|
||||
static auto ip6_mob_coti_type = id::find_type<RecordType>("ip6_mobility_coti");
|
||||
static auto ip6_mob_hot_type = id::find_type<RecordType>("ip6_mobility_hot");
|
||||
static auto ip6_mob_cot_type = id::find_type<RecordType>("ip6_mobility_cot");
|
||||
static auto ip6_mob_bu_type = id::find_type<RecordType>("ip6_mobility_bu");
|
||||
static auto ip6_mob_back_type = id::find_type<RecordType>("ip6_mobility_back");
|
||||
static auto ip6_mob_be_type = id::find_type<RecordType>("ip6_mobility_be");
|
||||
|
||||
switch ( mob->ip6mob_type )
|
||||
{
|
||||
static auto ip6_mob_type = id::find_type<RecordType>("ip6_mobility_hdr");
|
||||
rv = make_intrusive<RecordVal>(ip6_mob_type);
|
||||
const struct ip6_mobility* mob = (const struct ip6_mobility*)data;
|
||||
rv->Assign(0, mob->ip6mob_payload);
|
||||
rv->Assign(1, mob->ip6mob_len);
|
||||
rv->Assign(2, mob->ip6mob_type);
|
||||
rv->Assign(3, mob->ip6mob_rsv);
|
||||
rv->Assign(4, ntohs(mob->ip6mob_chksum));
|
||||
|
||||
static auto ip6_mob_msg_type = id::find_type<RecordType>("ip6_mobility_msg");
|
||||
auto msg = make_intrusive<RecordVal>(ip6_mob_msg_type);
|
||||
msg->Assign(0, mob->ip6mob_type);
|
||||
|
||||
uint16_t off = sizeof(ip6_mobility);
|
||||
const u_char* msg_data = data + off;
|
||||
|
||||
static auto ip6_mob_brr_type = id::find_type<RecordType>("ip6_mobility_brr");
|
||||
static auto ip6_mob_hoti_type = id::find_type<RecordType>("ip6_mobility_hoti");
|
||||
static auto ip6_mob_coti_type = id::find_type<RecordType>("ip6_mobility_coti");
|
||||
static auto ip6_mob_hot_type = id::find_type<RecordType>("ip6_mobility_hot");
|
||||
static auto ip6_mob_cot_type = id::find_type<RecordType>("ip6_mobility_cot");
|
||||
static auto ip6_mob_bu_type = id::find_type<RecordType>("ip6_mobility_bu");
|
||||
static auto ip6_mob_back_type = id::find_type<RecordType>("ip6_mobility_back");
|
||||
static auto ip6_mob_be_type = id::find_type<RecordType>("ip6_mobility_be");
|
||||
|
||||
switch ( mob->ip6mob_type )
|
||||
case 0:
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_brr_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
off += sizeof(uint16_t);
|
||||
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(1, std::move(m));
|
||||
}
|
||||
break;
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_brr_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
off += sizeof(uint16_t);
|
||||
m->Assign(1, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(1, std::move(m));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_hoti_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
off += sizeof(uint16_t) + sizeof(uint64_t);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(2, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_coti_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
off += sizeof(uint16_t) + sizeof(uint64_t);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(3, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_hot_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
m->Assign(2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) +
|
||||
sizeof(uint64_t)))));
|
||||
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(4, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_cot_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
m->Assign(2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) +
|
||||
sizeof(uint64_t)))));
|
||||
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(5, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_bu_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
|
||||
0x8000));
|
||||
m->Assign(2, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
|
||||
0x4000));
|
||||
m->Assign(3, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
|
||||
0x2000));
|
||||
m->Assign(4, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) &
|
||||
0x1000));
|
||||
m->Assign(5, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
||||
off += 3 * sizeof(uint16_t);
|
||||
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(6, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_back_type);
|
||||
m->Assign(0, *((uint8_t*)msg_data));
|
||||
m->Assign(1, static_cast<bool>(
|
||||
*((uint8_t*)(msg_data + sizeof(uint8_t))) & 0x80));
|
||||
m->Assign(2, ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))));
|
||||
m->Assign(3, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
||||
off += 3 * sizeof(uint16_t);
|
||||
m->Assign(4, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(7, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_be_type);
|
||||
m->Assign(0, *((uint8_t*)msg_data));
|
||||
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16_t));
|
||||
m->Assign(1, make_intrusive<AddrVal>(IPAddr(*hoa)));
|
||||
off += sizeof(uint16_t) + sizeof(in6_addr);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(8, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->Weird("unknown_mobility_type", util::fmt("%d", mob->ip6mob_type));
|
||||
break;
|
||||
case 1:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_hoti_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
off += sizeof(uint16_t) + sizeof(uint64_t);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(2, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
rv->Assign(5, std::move(msg));
|
||||
case 2:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_coti_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
off += sizeof(uint16_t) + sizeof(uint64_t);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(3, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_hot_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
m->Assign(
|
||||
2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t)))));
|
||||
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(4, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_cot_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t)))));
|
||||
m->Assign(
|
||||
2, ntohll(*((uint64_t*)(msg_data + sizeof(uint16_t) + sizeof(uint64_t)))));
|
||||
off += sizeof(uint16_t) + 2 * sizeof(uint64_t);
|
||||
m->Assign(3, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(5, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_bu_type);
|
||||
m->Assign(0, ntohs(*((uint16_t*)msg_data)));
|
||||
m->Assign(1, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x8000));
|
||||
m->Assign(2, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x4000));
|
||||
m->Assign(3, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x2000));
|
||||
m->Assign(4, static_cast<bool>(
|
||||
ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))) & 0x1000));
|
||||
m->Assign(5, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
||||
off += 3 * sizeof(uint16_t);
|
||||
m->Assign(6, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(6, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_back_type);
|
||||
m->Assign(0, *((uint8_t*)msg_data));
|
||||
m->Assign(1,
|
||||
static_cast<bool>(*((uint8_t*)(msg_data + sizeof(uint8_t))) & 0x80));
|
||||
m->Assign(2, ntohs(*((uint16_t*)(msg_data + sizeof(uint16_t)))));
|
||||
m->Assign(3, ntohs(*((uint16_t*)(msg_data + 2 * sizeof(uint16_t)))));
|
||||
off += 3 * sizeof(uint16_t);
|
||||
m->Assign(4, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(7, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
auto m = make_intrusive<RecordVal>(ip6_mob_be_type);
|
||||
m->Assign(0, *((uint8_t*)msg_data));
|
||||
const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16_t));
|
||||
m->Assign(1, make_intrusive<AddrVal>(IPAddr(*hoa)));
|
||||
off += sizeof(uint16_t) + sizeof(in6_addr);
|
||||
m->Assign(2, BuildOptionsVal(data + off, Length() - off));
|
||||
msg->Assign(8, std::move(m));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->Weird("unknown_mobility_type", util::fmt("%d", mob->ip6mob_type));
|
||||
break;
|
||||
}
|
||||
|
||||
rv->Assign(5, std::move(msg));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -384,67 +379,67 @@ RecordValPtr IP_Hdr::ToPktHdrVal(RecordValPtr pkt_hdr, int sindex) const
|
|||
switch ( proto )
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
{
|
||||
const struct tcphdr* tp = (const struct tcphdr*)data;
|
||||
auto tcp_hdr = make_intrusive<RecordVal>(tcp_hdr_type);
|
||||
{
|
||||
const struct tcphdr* tp = (const struct tcphdr*)data;
|
||||
auto tcp_hdr = make_intrusive<RecordVal>(tcp_hdr_type);
|
||||
|
||||
int tcp_hdr_len = tp->th_off * 4;
|
||||
int data_len = PayloadLen() - tcp_hdr_len;
|
||||
int tcp_hdr_len = tp->th_off * 4;
|
||||
int data_len = PayloadLen() - tcp_hdr_len;
|
||||
|
||||
tcp_hdr->Assign(0, val_mgr->Port(ntohs(tp->th_sport), TRANSPORT_TCP));
|
||||
tcp_hdr->Assign(1, val_mgr->Port(ntohs(tp->th_dport), TRANSPORT_TCP));
|
||||
tcp_hdr->Assign(2, ntohl(tp->th_seq));
|
||||
tcp_hdr->Assign(3, ntohl(tp->th_ack));
|
||||
tcp_hdr->Assign(4, tcp_hdr_len);
|
||||
tcp_hdr->Assign(5, data_len);
|
||||
tcp_hdr->Assign(6, tp->th_x2);
|
||||
tcp_hdr->Assign(7, tp->th_flags);
|
||||
tcp_hdr->Assign(8, ntohs(tp->th_win));
|
||||
tcp_hdr->Assign(0, val_mgr->Port(ntohs(tp->th_sport), TRANSPORT_TCP));
|
||||
tcp_hdr->Assign(1, val_mgr->Port(ntohs(tp->th_dport), TRANSPORT_TCP));
|
||||
tcp_hdr->Assign(2, ntohl(tp->th_seq));
|
||||
tcp_hdr->Assign(3, ntohl(tp->th_ack));
|
||||
tcp_hdr->Assign(4, tcp_hdr_len);
|
||||
tcp_hdr->Assign(5, data_len);
|
||||
tcp_hdr->Assign(6, tp->th_x2);
|
||||
tcp_hdr->Assign(7, tp->th_flags);
|
||||
tcp_hdr->Assign(8, ntohs(tp->th_win));
|
||||
|
||||
pkt_hdr->Assign(sindex + 2, std::move(tcp_hdr));
|
||||
break;
|
||||
}
|
||||
pkt_hdr->Assign(sindex + 2, std::move(tcp_hdr));
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_UDP:
|
||||
{
|
||||
const struct udphdr* up = (const struct udphdr*)data;
|
||||
auto udp_hdr = make_intrusive<RecordVal>(udp_hdr_type);
|
||||
{
|
||||
const struct udphdr* up = (const struct udphdr*)data;
|
||||
auto udp_hdr = make_intrusive<RecordVal>(udp_hdr_type);
|
||||
|
||||
udp_hdr->Assign(0, val_mgr->Port(ntohs(up->uh_sport), TRANSPORT_UDP));
|
||||
udp_hdr->Assign(1, val_mgr->Port(ntohs(up->uh_dport), TRANSPORT_UDP));
|
||||
udp_hdr->Assign(2, ntohs(up->uh_ulen));
|
||||
udp_hdr->Assign(0, val_mgr->Port(ntohs(up->uh_sport), TRANSPORT_UDP));
|
||||
udp_hdr->Assign(1, val_mgr->Port(ntohs(up->uh_dport), TRANSPORT_UDP));
|
||||
udp_hdr->Assign(2, ntohs(up->uh_ulen));
|
||||
|
||||
pkt_hdr->Assign(sindex + 3, std::move(udp_hdr));
|
||||
break;
|
||||
}
|
||||
pkt_hdr->Assign(sindex + 3, std::move(udp_hdr));
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_ICMP:
|
||||
{
|
||||
const struct icmp* icmpp = (const struct icmp*)data;
|
||||
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
|
||||
{
|
||||
const struct icmp* icmpp = (const struct icmp*)data;
|
||||
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
|
||||
|
||||
icmp_hdr->Assign(0, icmpp->icmp_type);
|
||||
icmp_hdr->Assign(0, icmpp->icmp_type);
|
||||
|
||||
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
|
||||
break;
|
||||
}
|
||||
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
|
||||
break;
|
||||
}
|
||||
|
||||
case IPPROTO_ICMPV6:
|
||||
{
|
||||
const struct icmp6_hdr* icmpp = (const struct icmp6_hdr*)data;
|
||||
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
|
||||
{
|
||||
const struct icmp6_hdr* icmpp = (const struct icmp6_hdr*)data;
|
||||
auto icmp_hdr = make_intrusive<RecordVal>(icmp_hdr_type);
|
||||
|
||||
icmp_hdr->Assign(0, icmpp->icmp6_type);
|
||||
icmp_hdr->Assign(0, icmpp->icmp6_type);
|
||||
|
||||
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
|
||||
break;
|
||||
}
|
||||
pkt_hdr->Assign(sindex + 4, std::move(icmp_hdr));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// This is not a protocol we understand.
|
||||
break;
|
||||
}
|
||||
{
|
||||
// This is not a protocol we understand.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pkt_hdr;
|
||||
|
@ -585,30 +580,30 @@ void IPv6_Hdr_Chain::ProcessRoutingHeader(const struct ip6_rthdr* r, uint16_t le
|
|||
switch ( r->ip6r_type )
|
||||
{
|
||||
case 0: // Defined by RFC 2460, deprecated by RFC 5095
|
||||
{
|
||||
if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 )
|
||||
{
|
||||
if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 )
|
||||
{
|
||||
if ( r->ip6r_len % 2 == 0 )
|
||||
finalDst = new IPAddr(*addr);
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len");
|
||||
}
|
||||
|
||||
// Always raise a weird since this type is deprecated.
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr");
|
||||
if ( r->ip6r_len % 2 == 0 )
|
||||
finalDst = new IPAddr(*addr);
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len");
|
||||
}
|
||||
|
||||
// Always raise a weird since this type is deprecated.
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr");
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Defined by Mobile IPv6 RFC 6275.
|
||||
{
|
||||
if ( r->ip6r_segleft > 0 )
|
||||
{
|
||||
if ( r->ip6r_segleft > 0 )
|
||||
{
|
||||
if ( r->ip6r_len == 2 )
|
||||
finalDst = new IPAddr(*addr);
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_routing2_len");
|
||||
}
|
||||
if ( r->ip6r_len == 2 )
|
||||
finalDst = new IPAddr(*addr);
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_routing2_len");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -642,36 +637,35 @@ void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16_t len)
|
|||
len -= sizeof(uint8_t);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// Double-check that the len can hold the whole option structure.
|
||||
// Otherwise we get a buffer-overflow when we check the option_len.
|
||||
// Also check that it holds everything for the option itself.
|
||||
if ( len < sizeof(struct ip6_opt) || len < sizeof(struct ip6_opt) + opt->ip6o_len )
|
||||
{
|
||||
// Double-check that the len can hold the whole option structure.
|
||||
// Otherwise we get a buffer-overflow when we check the option_len.
|
||||
// Also check that it holds everything for the option itself.
|
||||
if ( len < sizeof(struct ip6_opt) ||
|
||||
len < sizeof(struct ip6_opt) + opt->ip6o_len )
|
||||
{
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt->ip6o_type ==
|
||||
201 ) // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
|
||||
{
|
||||
if ( opt->ip6o_len == sizeof(struct in6_addr) )
|
||||
{
|
||||
if ( homeAddr )
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts");
|
||||
else
|
||||
homeAddr =
|
||||
new IPAddr(*((const in6_addr*)(data + sizeof(struct ip6_opt))));
|
||||
}
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len");
|
||||
}
|
||||
|
||||
data += sizeof(struct ip6_opt) + opt->ip6o_len;
|
||||
len -= sizeof(struct ip6_opt) + opt->ip6o_len;
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_ipv6_dest_opt_len");
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt->ip6o_type ==
|
||||
201 ) // Home Address Option, Mobile IPv6 RFC 6275 section 6.3
|
||||
{
|
||||
if ( opt->ip6o_len == sizeof(struct in6_addr) )
|
||||
{
|
||||
if ( homeAddr )
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts");
|
||||
else
|
||||
homeAddr =
|
||||
new IPAddr(*((const in6_addr*)(data + sizeof(struct ip6_opt))));
|
||||
}
|
||||
else
|
||||
reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len");
|
||||
}
|
||||
|
||||
data += sizeof(struct ip6_opt) + opt->ip6o_len;
|
||||
len -= sizeof(struct ip6_opt) + opt->ip6o_len;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1285,38 +1285,38 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to, vector<IPPrefi
|
|||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
if ( prefix_vector )
|
||||
{
|
||||
if ( prefix_vector )
|
||||
prefix_vector->push_back(v->AsSubNet());
|
||||
delete mval;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t* n;
|
||||
uint32_t m[4];
|
||||
v->AsSubNet().Prefix().GetBytes(&n);
|
||||
v->AsSubNetVal()->Mask().CopyIPv6(m);
|
||||
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
m[i] = ntohl(m[i]);
|
||||
|
||||
bool is_v4_mask = m[0] == 0xffffffff && m[1] == m[0] && m[2] == m[0];
|
||||
|
||||
if ( v->AsSubNet().Prefix().GetFamily() == IPv4 && is_v4_mask )
|
||||
{
|
||||
prefix_vector->push_back(v->AsSubNet());
|
||||
delete mval;
|
||||
return true;
|
||||
mval->val = ntohl(*n);
|
||||
mval->mask = m[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t* n;
|
||||
uint32_t m[4];
|
||||
v->AsSubNet().Prefix().GetBytes(&n);
|
||||
v->AsSubNetVal()->Mask().CopyIPv6(m);
|
||||
|
||||
for ( unsigned int i = 0; i < 4; ++i )
|
||||
m[i] = ntohl(m[i]);
|
||||
|
||||
bool is_v4_mask = m[0] == 0xffffffff && m[1] == m[0] && m[2] == m[0];
|
||||
|
||||
if ( v->AsSubNet().Prefix().GetFamily() == IPv4 && is_v4_mask )
|
||||
{
|
||||
mval->val = ntohl(*n);
|
||||
mval->mask = m[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
rules_error("IPv6 subnets not supported");
|
||||
mval->val = 0;
|
||||
mval->mask = 0;
|
||||
}
|
||||
rules_error("IPv6 subnets not supported");
|
||||
mval->val = 0;
|
||||
mval->mask = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
44
src/Stmt.cc
44
src/Stmt.cc
|
@ -353,10 +353,10 @@ void do_print_stmt(const std::vector<ValPtr>& vals)
|
|||
case BifEnum::Log::REDIRECT_NONE:
|
||||
break;
|
||||
case BifEnum::Log::REDIRECT_ALL:
|
||||
{
|
||||
print_log(vals);
|
||||
return;
|
||||
}
|
||||
{
|
||||
print_log(vals);
|
||||
return;
|
||||
}
|
||||
case BifEnum::Log::REDIRECT_STDOUT:
|
||||
if ( f->FileHandle() == stdout )
|
||||
{
|
||||
|
@ -765,35 +765,35 @@ SwitchStmt::SwitchStmt(ExprPtr index, case_list* arg_cases)
|
|||
{
|
||||
// Simplify trivial unary plus/minus expressions on consts.
|
||||
case EXPR_NEGATE:
|
||||
{
|
||||
NegExpr* ne = (NegExpr*)(expr);
|
||||
{
|
||||
NegExpr* ne = (NegExpr*)(expr);
|
||||
|
||||
if ( ne->Op()->IsConst() )
|
||||
Unref(exprs.replace(j, new ConstExpr(ne->Eval(nullptr))));
|
||||
}
|
||||
if ( ne->Op()->IsConst() )
|
||||
Unref(exprs.replace(j, new ConstExpr(ne->Eval(nullptr))));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_POSITIVE:
|
||||
{
|
||||
PosExpr* pe = (PosExpr*)(expr);
|
||||
{
|
||||
PosExpr* pe = (PosExpr*)(expr);
|
||||
|
||||
if ( pe->Op()->IsConst() )
|
||||
Unref(exprs.replace(j, new ConstExpr(pe->Eval(nullptr))));
|
||||
}
|
||||
if ( pe->Op()->IsConst() )
|
||||
Unref(exprs.replace(j, new ConstExpr(pe->Eval(nullptr))));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_NAME:
|
||||
{
|
||||
NameExpr* ne = (NameExpr*)(expr);
|
||||
|
||||
if ( ne->Id()->IsConst() )
|
||||
{
|
||||
NameExpr* ne = (NameExpr*)(expr);
|
||||
auto v = ne->Eval(nullptr);
|
||||
|
||||
if ( ne->Id()->IsConst() )
|
||||
{
|
||||
auto v = ne->Eval(nullptr);
|
||||
|
||||
if ( v )
|
||||
Unref(exprs.replace(j, new ConstExpr(std::move(v))));
|
||||
}
|
||||
if ( v )
|
||||
Unref(exprs.replace(j, new ConstExpr(std::move(v))));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -48,17 +48,17 @@ TraversalCode trigger::TriggerTraversalCallback::PreExpr(const Expr* expr)
|
|||
switch ( expr->Tag() )
|
||||
{
|
||||
case EXPR_NAME:
|
||||
{
|
||||
const auto* e = static_cast<const NameExpr*>(expr);
|
||||
if ( e->Id()->IsGlobal() )
|
||||
trigger->Register(e->Id());
|
||||
{
|
||||
const auto* e = static_cast<const NameExpr*>(expr);
|
||||
if ( e->Id()->IsGlobal() )
|
||||
trigger->Register(e->Id());
|
||||
|
||||
Val* v = e->Id()->GetVal().get();
|
||||
Val* v = e->Id()->GetVal().get();
|
||||
|
||||
if ( v && v->Modifiable() )
|
||||
trigger->Register(v);
|
||||
break;
|
||||
};
|
||||
if ( v && v->Modifiable() )
|
||||
trigger->Register(v);
|
||||
break;
|
||||
};
|
||||
|
||||
default:
|
||||
// All others are uninteresting.
|
||||
|
|
583
src/Type.cc
583
src/Type.cc
|
@ -459,39 +459,39 @@ static bool is_supported_index_type(const TypePtr& t, const char** tname)
|
|||
return true;
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
auto rt = t->AsRecordType();
|
||||
{
|
||||
auto rt = t->AsRecordType();
|
||||
|
||||
for ( auto i = 0; i < rt->NumFields(); ++i )
|
||||
if ( ! is_supported_index_type(rt->GetFieldType(i), tname) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
for ( const auto& type : t->AsTypeList()->GetTypes() )
|
||||
if ( ! is_supported_index_type(type, tname) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto tt = t->AsTableType();
|
||||
|
||||
if ( ! is_supported_index_type(tt->GetIndices(), tname) )
|
||||
for ( auto i = 0; i < rt->NumFields(); ++i )
|
||||
if ( ! is_supported_index_type(rt->GetFieldType(i), tname) )
|
||||
return false;
|
||||
|
||||
const auto& yt = tt->Yield();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! yt )
|
||||
return true;
|
||||
case TYPE_LIST:
|
||||
{
|
||||
for ( const auto& type : t->AsTypeList()->GetTypes() )
|
||||
if ( ! is_supported_index_type(type, tname) )
|
||||
return false;
|
||||
|
||||
return is_supported_index_type(yt, tname);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto tt = t->AsTableType();
|
||||
|
||||
if ( ! is_supported_index_type(tt->GetIndices(), tname) )
|
||||
return false;
|
||||
|
||||
const auto& yt = tt->Yield();
|
||||
|
||||
if ( ! yt )
|
||||
return true;
|
||||
|
||||
return is_supported_index_type(yt, tname);
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
return is_supported_index_type(t->AsVectorType()->Yield(), tname);
|
||||
|
@ -1254,23 +1254,23 @@ void RecordType::Create(std::vector<std::optional<ZVal>>& r) const
|
|||
break;
|
||||
|
||||
case FieldInit::R_INIT_DEF:
|
||||
{
|
||||
auto v = init->def_expr->Eval(nullptr);
|
||||
if ( v )
|
||||
{
|
||||
auto v = init->def_expr->Eval(nullptr);
|
||||
if ( v )
|
||||
const auto& t = init->def_type;
|
||||
|
||||
if ( init->def_coerce )
|
||||
{
|
||||
const auto& t = init->def_type;
|
||||
|
||||
if ( init->def_coerce )
|
||||
{
|
||||
auto rt = cast_intrusive<RecordType>(t);
|
||||
v = v->AsRecordVal()->CoerceTo(rt);
|
||||
}
|
||||
|
||||
r_i = ZVal(v, t);
|
||||
auto rt = cast_intrusive<RecordType>(t);
|
||||
v = v->AsRecordVal()->CoerceTo(rt);
|
||||
}
|
||||
else
|
||||
reporter->Error("failed &default in record creation");
|
||||
|
||||
r_i = ZVal(v, t);
|
||||
}
|
||||
else
|
||||
reporter->Error("failed &default in record creation");
|
||||
}
|
||||
break;
|
||||
|
||||
case FieldInit::R_INIT_RECORD:
|
||||
|
@ -1904,81 +1904,81 @@ bool same_type(const Type& arg_t1, const Type& arg_t2, bool is_init, bool match_
|
|||
return true;
|
||||
|
||||
case TYPE_OPAQUE:
|
||||
{
|
||||
const OpaqueType* ot1 = (const OpaqueType*)t1;
|
||||
const OpaqueType* ot2 = (const OpaqueType*)t2;
|
||||
return ot1->Name() == ot2->Name();
|
||||
}
|
||||
{
|
||||
const OpaqueType* ot1 = (const OpaqueType*)t1;
|
||||
const OpaqueType* ot2 = (const OpaqueType*)t2;
|
||||
return ot1->Name() == ot2->Name();
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
const IndexType* it1 = (const IndexType*)t1;
|
||||
const IndexType* it2 = (const IndexType*)t2;
|
||||
{
|
||||
const IndexType* it1 = (const IndexType*)t1;
|
||||
const IndexType* it2 = (const IndexType*)t2;
|
||||
|
||||
const auto& tl1 = it1->GetIndices();
|
||||
const auto& tl2 = it2->GetIndices();
|
||||
const auto& tl1 = it1->GetIndices();
|
||||
const auto& tl2 = it2->GetIndices();
|
||||
|
||||
if ( (tl1 || tl2) && ! (tl1 && tl2) )
|
||||
return false;
|
||||
if ( (tl1 || tl2) && ! (tl1 && tl2) )
|
||||
return false;
|
||||
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
|
||||
if ( (y1 || y2) && ! (y1 && y2) )
|
||||
return false;
|
||||
if ( (y1 || y2) && ! (y1 && y2) )
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
const FuncType* ft1 = (const FuncType*)t1;
|
||||
const FuncType* ft2 = (const FuncType*)t2;
|
||||
{
|
||||
const FuncType* ft1 = (const FuncType*)t1;
|
||||
const FuncType* ft2 = (const FuncType*)t2;
|
||||
|
||||
if ( ft1->Flavor() != ft2->Flavor() )
|
||||
return false;
|
||||
if ( ft1->Flavor() != ft2->Flavor() )
|
||||
return false;
|
||||
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
if ( (y1 || y2) && ! (y1 && y2) )
|
||||
return false;
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
if ( (y1 || y2) && ! (y1 && y2) )
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
const RecordType* rt1 = (const RecordType*)t1;
|
||||
const RecordType* rt2 = (const RecordType*)t2;
|
||||
{
|
||||
const RecordType* rt1 = (const RecordType*)t1;
|
||||
const RecordType* rt2 = (const RecordType*)t2;
|
||||
|
||||
if ( rt1->NumFields() != rt2->NumFields() )
|
||||
if ( rt1->NumFields() != rt2->NumFields() )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < rt1->NumFields(); ++i )
|
||||
{
|
||||
const TypeDecl* td1 = rt1->FieldDecl(i);
|
||||
const TypeDecl* td2 = rt2->FieldDecl(i);
|
||||
|
||||
if ( match_record_field_names && ! util::streq(td1->id, td2->id) )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < rt1->NumFields(); ++i )
|
||||
{
|
||||
const TypeDecl* td1 = rt1->FieldDecl(i);
|
||||
const TypeDecl* td2 = rt2->FieldDecl(i);
|
||||
|
||||
if ( match_record_field_names && ! util::streq(td1->id, td2->id) )
|
||||
return false;
|
||||
|
||||
if ( ! same_attrs(td1->attrs.get(), td2->attrs.get()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
if ( ! same_attrs(td1->attrs.get(), td2->attrs.get()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
const auto& tl1 = t1->AsTypeList()->GetTypes();
|
||||
const auto& tl2 = t2->AsTypeList()->GetTypes();
|
||||
{
|
||||
const auto& tl1 = t1->AsTypeList()->GetTypes();
|
||||
const auto& tl2 = t2->AsTypeList()->GetTypes();
|
||||
|
||||
if ( tl1.size() != tl2.size() )
|
||||
return false;
|
||||
if ( tl1.size() != tl2.size() )
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_FILE:
|
||||
|
@ -2024,73 +2024,73 @@ bool same_type(const Type& arg_t1, const Type& arg_t2, bool is_init, bool match_
|
|||
switch ( t1->Tag() )
|
||||
{
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
const IndexType* it1 = (const IndexType*)t1;
|
||||
const IndexType* it2 = (const IndexType*)t2;
|
||||
|
||||
const auto& tl1 = it1->GetIndices();
|
||||
const auto& tl2 = it2->GetIndices();
|
||||
|
||||
if ( ! same_type(tl1, tl2, is_init, match_record_field_names) )
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
const IndexType* it1 = (const IndexType*)t1;
|
||||
const IndexType* it2 = (const IndexType*)t2;
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
|
||||
const auto& tl1 = it1->GetIndices();
|
||||
const auto& tl2 = it2->GetIndices();
|
||||
|
||||
if ( ! same_type(tl1, tl2, is_init, match_record_field_names) )
|
||||
result = false;
|
||||
else
|
||||
{
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
|
||||
result = same_type(y1, y2, is_init, match_record_field_names);
|
||||
}
|
||||
break;
|
||||
result = same_type(y1, y2, is_init, match_record_field_names);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
const FuncType* ft1 = (const FuncType*)t1;
|
||||
const FuncType* ft2 = (const FuncType*)t2;
|
||||
{
|
||||
const FuncType* ft1 = (const FuncType*)t1;
|
||||
const FuncType* ft2 = (const FuncType*)t2;
|
||||
|
||||
if ( ! same_type(t1->Yield(), t2->Yield(), is_init, match_record_field_names) )
|
||||
result = false;
|
||||
else
|
||||
result = ft1->CheckArgs(ft2->ParamList()->GetTypes(), is_init, false);
|
||||
break;
|
||||
}
|
||||
if ( ! same_type(t1->Yield(), t2->Yield(), is_init, match_record_field_names) )
|
||||
result = false;
|
||||
else
|
||||
result = ft1->CheckArgs(ft2->ParamList()->GetTypes(), is_init, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
const RecordType* rt1 = (const RecordType*)t1;
|
||||
const RecordType* rt2 = (const RecordType*)t2;
|
||||
|
||||
result = true;
|
||||
|
||||
for ( int i = 0; i < rt1->NumFields(); ++i )
|
||||
{
|
||||
const RecordType* rt1 = (const RecordType*)t1;
|
||||
const RecordType* rt2 = (const RecordType*)t2;
|
||||
const TypeDecl* td1 = rt1->FieldDecl(i);
|
||||
const TypeDecl* td2 = rt2->FieldDecl(i);
|
||||
|
||||
result = true;
|
||||
|
||||
for ( int i = 0; i < rt1->NumFields(); ++i )
|
||||
if ( ! same_type(td1->type, td2->type, is_init, match_record_field_names) )
|
||||
{
|
||||
const TypeDecl* td1 = rt1->FieldDecl(i);
|
||||
const TypeDecl* td2 = rt2->FieldDecl(i);
|
||||
|
||||
if ( ! same_type(td1->type, td2->type, is_init, match_record_field_names) )
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
const auto& tl1 = t1->AsTypeList()->GetTypes();
|
||||
const auto& tl2 = t2->AsTypeList()->GetTypes();
|
||||
{
|
||||
const auto& tl1 = t1->AsTypeList()->GetTypes();
|
||||
const auto& tl2 = t2->AsTypeList()->GetTypes();
|
||||
|
||||
result = true;
|
||||
result = true;
|
||||
|
||||
for ( auto i = 0u; i < tl1.size(); ++i )
|
||||
if ( ! same_type(tl1[i], tl2[i], is_init, match_record_field_names) )
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for ( auto i = 0u; i < tl1.size(); ++i )
|
||||
if ( ! same_type(tl1[i], tl2[i], is_init, match_record_field_names) )
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
case TYPE_FILE:
|
||||
|
@ -2098,13 +2098,12 @@ bool same_type(const Type& arg_t1, const Type& arg_t2, bool is_init, bool match_
|
|||
break;
|
||||
|
||||
case TYPE_TYPE:
|
||||
{
|
||||
auto tt1 = t1->AsTypeType();
|
||||
auto tt2 = t2->AsTypeType();
|
||||
result =
|
||||
same_type(tt1->GetType(), tt1->GetType(), is_init, match_record_field_names);
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto tt1 = t1->AsTypeType();
|
||||
auto tt2 = t2->AsTypeType();
|
||||
result = same_type(tt1->GetType(), tt1->GetType(), is_init, match_record_field_names);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
result = false;
|
||||
|
@ -2287,180 +2286,180 @@ TypePtr merge_types(const TypePtr& arg_t1, const TypePtr& arg_t2)
|
|||
return base_type(tg1);
|
||||
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
// Could compare pointers t1 == t2, but maybe there's someone out
|
||||
// there creating clones of the type, so safer to compare name.
|
||||
if ( t1->GetName() != t2->GetName() )
|
||||
{
|
||||
// Could compare pointers t1 == t2, but maybe there's someone out
|
||||
// there creating clones of the type, so safer to compare name.
|
||||
if ( t1->GetName() != t2->GetName() )
|
||||
{
|
||||
std::string msg = util::fmt("incompatible enum types: '%s' and '%s'",
|
||||
t1->GetName().data(), t2->GetName().data());
|
||||
std::string msg = util::fmt("incompatible enum types: '%s' and '%s'",
|
||||
t1->GetName().data(), t2->GetName().data());
|
||||
|
||||
t1->Error(msg.data(), t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Doing a lookup here as a roundabout way of ref-ing t1, without
|
||||
// changing the function params which has t1 as const and also
|
||||
// (potentially) avoiding a pitfall mentioned earlier about clones.
|
||||
const auto& id = detail::global_scope()->Find(t1->GetName());
|
||||
|
||||
if ( id && id->IsType() && id->GetType()->Tag() == TYPE_ENUM )
|
||||
// It should make most sense to return the real type here rather
|
||||
// than a copy since it may be redef'd later in parsing. If we
|
||||
// return a copy, then whoever is using this return value won't
|
||||
// actually see those changes from the redef.
|
||||
return id->GetType();
|
||||
|
||||
std::string msg =
|
||||
util::fmt("incompatible enum types: '%s' and '%s'"
|
||||
" ('%s' enum type ID is invalid)",
|
||||
t1->GetName().data(), t2->GetName().data(), t1->GetName().data());
|
||||
t1->Error(msg.data(), t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Doing a lookup here as a roundabout way of ref-ing t1, without
|
||||
// changing the function params which has t1 as const and also
|
||||
// (potentially) avoiding a pitfall mentioned earlier about clones.
|
||||
const auto& id = detail::global_scope()->Find(t1->GetName());
|
||||
|
||||
if ( id && id->IsType() && id->GetType()->Tag() == TYPE_ENUM )
|
||||
// It should make most sense to return the real type here rather
|
||||
// than a copy since it may be redef'd later in parsing. If we
|
||||
// return a copy, then whoever is using this return value won't
|
||||
// actually see those changes from the redef.
|
||||
return id->GetType();
|
||||
|
||||
std::string msg =
|
||||
util::fmt("incompatible enum types: '%s' and '%s'"
|
||||
" ('%s' enum type ID is invalid)",
|
||||
t1->GetName().data(), t2->GetName().data(), t1->GetName().data());
|
||||
t1->Error(msg.data(), t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
const IndexType* it1 = (const IndexType*)t1;
|
||||
const IndexType* it2 = (const IndexType*)t2;
|
||||
|
||||
const auto& tl1 = it1->GetIndexTypes();
|
||||
const auto& tl2 = it2->GetIndexTypes();
|
||||
TypeListPtr tl3;
|
||||
|
||||
if ( tl1.size() != tl2.size() )
|
||||
{
|
||||
const IndexType* it1 = (const IndexType*)t1;
|
||||
const IndexType* it2 = (const IndexType*)t2;
|
||||
t1->Error("incompatible types", t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& tl1 = it1->GetIndexTypes();
|
||||
const auto& tl2 = it2->GetIndexTypes();
|
||||
TypeListPtr tl3;
|
||||
tl3 = make_intrusive<TypeList>();
|
||||
|
||||
if ( tl1.size() != tl2.size() )
|
||||
for ( auto i = 0u; i < tl1.size(); ++i )
|
||||
{
|
||||
auto tl3_i = merge_types(tl1[i], tl2[i]);
|
||||
if ( ! tl3_i )
|
||||
return nullptr;
|
||||
|
||||
tl3->Append(std::move(tl3_i));
|
||||
}
|
||||
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
TypePtr y3;
|
||||
|
||||
if ( y1 || y2 )
|
||||
{
|
||||
if ( ! y1 || ! y2 )
|
||||
{
|
||||
t1->Error("incompatible types", t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tl3 = make_intrusive<TypeList>();
|
||||
|
||||
for ( auto i = 0u; i < tl1.size(); ++i )
|
||||
{
|
||||
auto tl3_i = merge_types(tl1[i], tl2[i]);
|
||||
if ( ! tl3_i )
|
||||
return nullptr;
|
||||
|
||||
tl3->Append(std::move(tl3_i));
|
||||
}
|
||||
|
||||
const auto& y1 = t1->Yield();
|
||||
const auto& y2 = t2->Yield();
|
||||
TypePtr y3;
|
||||
|
||||
if ( y1 || y2 )
|
||||
{
|
||||
if ( ! y1 || ! y2 )
|
||||
{
|
||||
t1->Error("incompatible types", t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
y3 = merge_types(y1, y2);
|
||||
if ( ! y3 )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( t1->IsSet() )
|
||||
return make_intrusive<SetType>(std::move(tl3), nullptr);
|
||||
else
|
||||
return make_intrusive<TableType>(std::move(tl3), std::move(y3));
|
||||
y3 = merge_types(y1, y2);
|
||||
if ( ! y3 )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( t1->IsSet() )
|
||||
return make_intrusive<SetType>(std::move(tl3), nullptr);
|
||||
else
|
||||
return make_intrusive<TableType>(std::move(tl3), std::move(y3));
|
||||
}
|
||||
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
if ( ! same_type(t1, t2) )
|
||||
{
|
||||
if ( ! same_type(t1, t2) )
|
||||
{
|
||||
t1->Error("incompatible types", t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const FuncType* ft1 = (const FuncType*)t1;
|
||||
const FuncType* ft2 = (const FuncType*)t1;
|
||||
auto args = cast_intrusive<RecordType>(merge_types(ft1->Params(), ft2->Params()));
|
||||
auto yield = t1->Yield() ? merge_types(t1->Yield(), t2->Yield()) : nullptr;
|
||||
|
||||
return make_intrusive<FuncType>(std::move(args), std::move(yield), ft1->Flavor());
|
||||
t1->Error("incompatible types", t2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const FuncType* ft1 = (const FuncType*)t1;
|
||||
const FuncType* ft2 = (const FuncType*)t1;
|
||||
auto args = cast_intrusive<RecordType>(merge_types(ft1->Params(), ft2->Params()));
|
||||
auto yield = t1->Yield() ? merge_types(t1->Yield(), t2->Yield()) : nullptr;
|
||||
|
||||
return make_intrusive<FuncType>(std::move(args), std::move(yield), ft1->Flavor());
|
||||
}
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
const RecordType* rt1 = (const RecordType*)t1;
|
||||
const RecordType* rt2 = (const RecordType*)t2;
|
||||
|
||||
if ( rt1->NumFields() != rt2->NumFields() )
|
||||
return nullptr;
|
||||
|
||||
type_decl_list* tdl3 = new type_decl_list(rt1->NumFields());
|
||||
|
||||
for ( int i = 0; i < rt1->NumFields(); ++i )
|
||||
{
|
||||
const RecordType* rt1 = (const RecordType*)t1;
|
||||
const RecordType* rt2 = (const RecordType*)t2;
|
||||
const TypeDecl* td1 = rt1->FieldDecl(i);
|
||||
const TypeDecl* td2 = rt2->FieldDecl(i);
|
||||
auto tdl3_i = merge_types(td1->type, td2->type);
|
||||
|
||||
if ( rt1->NumFields() != rt2->NumFields() )
|
||||
return nullptr;
|
||||
|
||||
type_decl_list* tdl3 = new type_decl_list(rt1->NumFields());
|
||||
|
||||
for ( int i = 0; i < rt1->NumFields(); ++i )
|
||||
if ( ! util::streq(td1->id, td2->id) || ! tdl3_i )
|
||||
{
|
||||
const TypeDecl* td1 = rt1->FieldDecl(i);
|
||||
const TypeDecl* td2 = rt2->FieldDecl(i);
|
||||
auto tdl3_i = merge_types(td1->type, td2->type);
|
||||
|
||||
if ( ! util::streq(td1->id, td2->id) || ! tdl3_i )
|
||||
{
|
||||
t1->Error("incompatible record fields", t2);
|
||||
delete tdl3;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tdl3->push_back(new TypeDecl(util::copy_string(td1->id), std::move(tdl3_i)));
|
||||
t1->Error("incompatible record fields", t2);
|
||||
delete tdl3;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return make_intrusive<RecordType>(tdl3);
|
||||
tdl3->push_back(new TypeDecl(util::copy_string(td1->id), std::move(tdl3_i)));
|
||||
}
|
||||
|
||||
return make_intrusive<RecordType>(tdl3);
|
||||
}
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
const TypeList* tl1 = t1->AsTypeList();
|
||||
const TypeList* tl2 = t2->AsTypeList();
|
||||
|
||||
if ( tl1->IsPure() != tl2->IsPure() )
|
||||
{
|
||||
const TypeList* tl1 = t1->AsTypeList();
|
||||
const TypeList* tl2 = t2->AsTypeList();
|
||||
|
||||
if ( tl1->IsPure() != tl2->IsPure() )
|
||||
{
|
||||
tl1->Error("incompatible lists", tl2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& l1 = tl1->GetTypes();
|
||||
const auto& l2 = tl2->GetTypes();
|
||||
|
||||
if ( l1.size() == 0 || l2.size() == 0 )
|
||||
{
|
||||
if ( l1.size() == 0 )
|
||||
tl1->Error("empty list");
|
||||
else
|
||||
tl2->Error("empty list");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( tl1->IsPure() )
|
||||
{
|
||||
// We will be expanding the pure list when converting
|
||||
// the initialization expression into a set of values.
|
||||
// So the merge type of the list is the type of one
|
||||
// of the elements, providing they're consistent.
|
||||
return merge_types(l1[0], l2[0]);
|
||||
}
|
||||
|
||||
// Impure lists - must have the same size and match element
|
||||
// by element.
|
||||
if ( l1.size() != l2.size() )
|
||||
{
|
||||
tl1->Error("different number of indices", tl2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto tl3 = make_intrusive<TypeList>();
|
||||
|
||||
for ( auto i = 0u; i < l1.size(); ++i )
|
||||
tl3->Append(merge_types(l1[i], l2[i]));
|
||||
|
||||
return tl3;
|
||||
tl1->Error("incompatible lists", tl2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& l1 = tl1->GetTypes();
|
||||
const auto& l2 = tl2->GetTypes();
|
||||
|
||||
if ( l1.size() == 0 || l2.size() == 0 )
|
||||
{
|
||||
if ( l1.size() == 0 )
|
||||
tl1->Error("empty list");
|
||||
else
|
||||
tl2->Error("empty list");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ( tl1->IsPure() )
|
||||
{
|
||||
// We will be expanding the pure list when converting
|
||||
// the initialization expression into a set of values.
|
||||
// So the merge type of the list is the type of one
|
||||
// of the elements, providing they're consistent.
|
||||
return merge_types(l1[0], l2[0]);
|
||||
}
|
||||
|
||||
// Impure lists - must have the same size and match element
|
||||
// by element.
|
||||
if ( l1.size() != l2.size() )
|
||||
{
|
||||
tl1->Error("different number of indices", tl2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto tl3 = make_intrusive<TypeList>();
|
||||
|
||||
for ( auto i = 0u; i < l1.size(); ++i )
|
||||
tl3->Append(merge_types(l1[i], l2[i]));
|
||||
|
||||
return tl3;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
if ( ! same_type(t1->Yield(), t2->Yield()) )
|
||||
{
|
||||
|
|
336
src/Val.cc
336
src/Val.cc
|
@ -444,161 +444,161 @@ static void BuildJSON(threading::formatter::JSON::NullDoubleWriter& writer, Val*
|
|||
break;
|
||||
|
||||
case TYPE_PORT:
|
||||
{
|
||||
auto* pval = val->AsPortVal();
|
||||
writer.StartObject();
|
||||
writer.Key("port");
|
||||
writer.Int64(pval->Port());
|
||||
writer.Key("proto");
|
||||
writer.String(pval->Protocol());
|
||||
writer.EndObject();
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto* pval = val->AsPortVal();
|
||||
writer.StartObject();
|
||||
writer.Key("port");
|
||||
writer.Int64(pval->Port());
|
||||
writer.Key("proto");
|
||||
writer.String(pval->Protocol());
|
||||
writer.EndObject();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_PATTERN:
|
||||
case TYPE_INTERVAL:
|
||||
case TYPE_ADDR:
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
ODesc d;
|
||||
d.SetStyle(RAW_STYLE);
|
||||
val->Describe(&d);
|
||||
writer.String(reinterpret_cast<const char*>(d.Bytes()), d.Len());
|
||||
break;
|
||||
}
|
||||
{
|
||||
ODesc d;
|
||||
d.SetStyle(RAW_STYLE);
|
||||
val->Describe(&d);
|
||||
writer.String(reinterpret_cast<const char*>(d.Bytes()), d.Len());
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_FILE:
|
||||
case TYPE_FUNC:
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRING:
|
||||
{
|
||||
ODesc d;
|
||||
d.SetStyle(RAW_STYLE);
|
||||
val->Describe(&d);
|
||||
writer.String(util::json_escape_utf8(
|
||||
std::string(reinterpret_cast<const char*>(d.Bytes()), d.Len())));
|
||||
break;
|
||||
}
|
||||
{
|
||||
ODesc d;
|
||||
d.SetStyle(RAW_STYLE);
|
||||
val->Describe(&d);
|
||||
writer.String(util::json_escape_utf8(
|
||||
std::string(reinterpret_cast<const char*>(d.Bytes()), d.Len())));
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto* table = val->AsTable();
|
||||
auto* tval = val->AsTableVal();
|
||||
|
||||
if ( tval->GetType()->IsSet() )
|
||||
writer.StartArray();
|
||||
else
|
||||
writer.StartObject();
|
||||
|
||||
std::unique_ptr<detail::HashKey> k;
|
||||
TableEntryVal* entry;
|
||||
|
||||
for ( const auto& te : *table )
|
||||
{
|
||||
auto* table = val->AsTable();
|
||||
auto* tval = val->AsTableVal();
|
||||
entry = te.GetValue<TableEntryVal*>();
|
||||
k = te.GetHashKey();
|
||||
|
||||
auto lv = tval->RecreateIndex(*k);
|
||||
Val* entry_key = lv->Length() == 1 ? lv->Idx(0).get() : lv.get();
|
||||
|
||||
if ( tval->GetType()->IsSet() )
|
||||
writer.StartArray();
|
||||
BuildJSON(writer, entry_key, only_loggable, re);
|
||||
else
|
||||
writer.StartObject();
|
||||
|
||||
std::unique_ptr<detail::HashKey> k;
|
||||
TableEntryVal* entry;
|
||||
|
||||
for ( const auto& te : *table )
|
||||
{
|
||||
entry = te.GetValue<TableEntryVal*>();
|
||||
k = te.GetHashKey();
|
||||
rapidjson::StringBuffer buffer;
|
||||
threading::formatter::JSON::NullDoubleWriter key_writer(buffer);
|
||||
BuildJSON(key_writer, entry_key, only_loggable, re);
|
||||
string key_str = buffer.GetString();
|
||||
|
||||
auto lv = tval->RecreateIndex(*k);
|
||||
Val* entry_key = lv->Length() == 1 ? lv->Idx(0).get() : lv.get();
|
||||
if ( key_str.length() >= 2 && key_str[0] == '"' &&
|
||||
key_str[key_str.length() - 1] == '"' )
|
||||
// Strip quotes.
|
||||
key_str = key_str.substr(1, key_str.length() - 2);
|
||||
|
||||
if ( tval->GetType()->IsSet() )
|
||||
BuildJSON(writer, entry_key, only_loggable, re);
|
||||
else
|
||||
{
|
||||
rapidjson::StringBuffer buffer;
|
||||
threading::formatter::JSON::NullDoubleWriter key_writer(buffer);
|
||||
BuildJSON(key_writer, entry_key, only_loggable, re);
|
||||
string key_str = buffer.GetString();
|
||||
|
||||
if ( key_str.length() >= 2 && key_str[0] == '"' &&
|
||||
key_str[key_str.length() - 1] == '"' )
|
||||
// Strip quotes.
|
||||
key_str = key_str.substr(1, key_str.length() - 2);
|
||||
|
||||
BuildJSON(writer, entry->GetVal().get(), only_loggable, re, key_str);
|
||||
}
|
||||
BuildJSON(writer, entry->GetVal().get(), only_loggable, re, key_str);
|
||||
}
|
||||
|
||||
if ( tval->GetType()->IsSet() )
|
||||
writer.EndArray();
|
||||
else
|
||||
writer.EndObject();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ( tval->GetType()->IsSet() )
|
||||
writer.EndArray();
|
||||
else
|
||||
writer.EndObject();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
writer.StartObject();
|
||||
|
||||
auto* rval = val->AsRecordVal();
|
||||
auto rt = rval->GetType()->AsRecordType();
|
||||
|
||||
for ( auto i = 0; i < rt->NumFields(); ++i )
|
||||
{
|
||||
writer.StartObject();
|
||||
auto value = rval->GetFieldOrDefault(i);
|
||||
|
||||
auto* rval = val->AsRecordVal();
|
||||
auto rt = rval->GetType()->AsRecordType();
|
||||
|
||||
for ( auto i = 0; i < rt->NumFields(); ++i )
|
||||
if ( value && (! only_loggable || rt->FieldHasAttr(i, detail::ATTR_LOG)) )
|
||||
{
|
||||
auto value = rval->GetFieldOrDefault(i);
|
||||
string key_str;
|
||||
auto field_name = rt->FieldName(i);
|
||||
|
||||
if ( value && (! only_loggable || rt->FieldHasAttr(i, detail::ATTR_LOG)) )
|
||||
if ( re && re->MatchAnywhere(field_name) != 0 )
|
||||
{
|
||||
string key_str;
|
||||
auto field_name = rt->FieldName(i);
|
||||
|
||||
if ( re && re->MatchAnywhere(field_name) != 0 )
|
||||
{
|
||||
auto blank = make_intrusive<StringVal>("");
|
||||
auto fn_val = make_intrusive<StringVal>(field_name);
|
||||
const auto& bs = *blank->AsString();
|
||||
auto key_val = fn_val->Replace(re, bs, false);
|
||||
key_str = key_val->ToStdString();
|
||||
}
|
||||
else
|
||||
key_str = field_name;
|
||||
|
||||
BuildJSON(writer, value.get(), only_loggable, re, key_str);
|
||||
auto blank = make_intrusive<StringVal>("");
|
||||
auto fn_val = make_intrusive<StringVal>(field_name);
|
||||
const auto& bs = *blank->AsString();
|
||||
auto key_val = fn_val->Replace(re, bs, false);
|
||||
key_str = key_val->ToStdString();
|
||||
}
|
||||
}
|
||||
else
|
||||
key_str = field_name;
|
||||
|
||||
writer.EndObject();
|
||||
break;
|
||||
BuildJSON(writer, value.get(), only_loggable, re, key_str);
|
||||
}
|
||||
}
|
||||
|
||||
writer.EndObject();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
writer.StartArray();
|
||||
{
|
||||
writer.StartArray();
|
||||
|
||||
auto* lval = val->AsListVal();
|
||||
size_t size = lval->Length();
|
||||
for ( size_t i = 0; i < size; i++ )
|
||||
BuildJSON(writer, lval->Idx(i).get(), only_loggable, re);
|
||||
auto* lval = val->AsListVal();
|
||||
size_t size = lval->Length();
|
||||
for ( size_t i = 0; i < size; i++ )
|
||||
BuildJSON(writer, lval->Idx(i).get(), only_loggable, re);
|
||||
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
writer.StartArray();
|
||||
{
|
||||
writer.StartArray();
|
||||
|
||||
auto* vval = val->AsVectorVal();
|
||||
size_t size = vval->SizeVal()->AsCount();
|
||||
for ( size_t i = 0; i < size; i++ )
|
||||
BuildJSON(writer, vval->ValAt(i).get(), only_loggable, re);
|
||||
auto* vval = val->AsVectorVal();
|
||||
size_t size = vval->SizeVal()->AsCount();
|
||||
for ( size_t i = 0; i < size; i++ )
|
||||
BuildJSON(writer, vval->ValAt(i).get(), only_loggable, re);
|
||||
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_OPAQUE:
|
||||
{
|
||||
writer.StartObject();
|
||||
{
|
||||
writer.StartObject();
|
||||
|
||||
writer.Key("opaque_type");
|
||||
auto* oval = val->AsOpaqueVal();
|
||||
writer.String(OpaqueMgr::mgr()->TypeID(oval));
|
||||
writer.Key("opaque_type");
|
||||
auto* oval = val->AsOpaqueVal();
|
||||
writer.String(OpaqueMgr::mgr()->TypeID(oval));
|
||||
|
||||
writer.EndObject();
|
||||
break;
|
||||
}
|
||||
writer.EndObject();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
writer.Null();
|
||||
|
@ -1369,23 +1369,23 @@ static void find_nested_record_types(const TypePtr& t, std::set<RecordType*>* fo
|
|||
switch ( t->Tag() )
|
||||
{
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
auto rt = t->AsRecordType();
|
||||
found->emplace(rt);
|
||||
{
|
||||
auto rt = t->AsRecordType();
|
||||
found->emplace(rt);
|
||||
|
||||
for ( auto i = 0; i < rt->NumFields(); ++i )
|
||||
find_nested_record_types(rt->FieldDecl(i)->type, found);
|
||||
}
|
||||
for ( auto i = 0; i < rt->NumFields(); ++i )
|
||||
find_nested_record_types(rt->FieldDecl(i)->type, found);
|
||||
}
|
||||
return;
|
||||
case TYPE_TABLE:
|
||||
find_nested_record_types(t->AsTableType()->GetIndices(), found);
|
||||
find_nested_record_types(t->AsTableType()->Yield(), found);
|
||||
return;
|
||||
case TYPE_LIST:
|
||||
{
|
||||
for ( const auto& type : t->AsTypeList()->GetTypes() )
|
||||
find_nested_record_types(type, found);
|
||||
}
|
||||
{
|
||||
for ( const auto& type : t->AsTypeList()->GetTypes() )
|
||||
find_nested_record_types(type, found);
|
||||
}
|
||||
return;
|
||||
case TYPE_FUNC:
|
||||
find_nested_record_types(t->AsFuncType()->Params(), found);
|
||||
|
@ -2145,63 +2145,63 @@ void TableVal::SendToStore(const Val* index, const TableEntryVal* new_entry_val,
|
|||
{
|
||||
case ELEMENT_NEW:
|
||||
case ELEMENT_CHANGED:
|
||||
{
|
||||
{
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
broker::optional<broker::timespan> expiry;
|
||||
broker::optional<broker::timespan> expiry;
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
auto expire_time = GetExpireTime();
|
||||
if ( expire_time == 0 )
|
||||
// Entry is set to immediately expire. Let's not forward it.
|
||||
break;
|
||||
|
||||
if ( expire_time > 0 )
|
||||
{
|
||||
if ( attrs->Find(detail::ATTR_EXPIRE_CREATE) )
|
||||
{
|
||||
// for create expiry, we have to substract the already elapsed time from
|
||||
// the expiry.
|
||||
auto e = expire_time -
|
||||
(run_state::network_time - new_entry_val->ExpireAccessTime());
|
||||
if ( e <= 0 )
|
||||
// element already expired? Let's not insert it.
|
||||
break;
|
||||
|
||||
expiry = Broker::detail::convert_expiry(e);
|
||||
}
|
||||
else
|
||||
expiry = Broker::detail::convert_expiry(expire_time);
|
||||
}
|
||||
|
||||
if ( table_type->IsSet() )
|
||||
handle->store.put(std::move(*broker_index), broker::data(), expiry);
|
||||
else
|
||||
{
|
||||
if ( ! new_entry_val )
|
||||
{
|
||||
emit_builtin_error(
|
||||
"did not receive new value for Broker datastore send operation");
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_value = new_entry_val->GetVal().get();
|
||||
auto broker_val = Broker::detail::val_to_data(new_value);
|
||||
if ( ! broker_val )
|
||||
{
|
||||
emit_builtin_error("invalid Broker data conversation for table value");
|
||||
return;
|
||||
}
|
||||
|
||||
handle->store.put(std::move(*broker_index), std::move(*broker_val), expiry);
|
||||
}
|
||||
auto expire_time = GetExpireTime();
|
||||
if ( expire_time == 0 )
|
||||
// Entry is set to immediately expire. Let's not forward it.
|
||||
break;
|
||||
|
||||
if ( expire_time > 0 )
|
||||
{
|
||||
if ( attrs->Find(detail::ATTR_EXPIRE_CREATE) )
|
||||
{
|
||||
// for create expiry, we have to substract the already elapsed time from
|
||||
// the expiry.
|
||||
auto e = expire_time -
|
||||
(run_state::network_time - new_entry_val->ExpireAccessTime());
|
||||
if ( e <= 0 )
|
||||
// element already expired? Let's not insert it.
|
||||
break;
|
||||
|
||||
expiry = Broker::detail::convert_expiry(e);
|
||||
}
|
||||
else
|
||||
expiry = Broker::detail::convert_expiry(expire_time);
|
||||
}
|
||||
|
||||
if ( table_type->IsSet() )
|
||||
handle->store.put(std::move(*broker_index), broker::data(), expiry);
|
||||
else
|
||||
{
|
||||
if ( ! new_entry_val )
|
||||
{
|
||||
emit_builtin_error(
|
||||
"did not receive new value for Broker datastore send operation");
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_value = new_entry_val->GetVal().get();
|
||||
auto broker_val = Broker::detail::val_to_data(new_value);
|
||||
if ( ! broker_val )
|
||||
{
|
||||
emit_builtin_error("invalid Broker data conversation for table value");
|
||||
return;
|
||||
}
|
||||
|
||||
handle->store.put(std::move(*broker_index), std::move(*broker_val), expiry);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ELEMENT_REMOVED:
|
||||
handle->store.erase(std::move(*broker_index));
|
||||
break;
|
||||
|
|
20
src/Var.cc
20
src/Var.cc
|
@ -223,19 +223,19 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
|
|||
switch ( init->Tag() )
|
||||
{
|
||||
case EXPR_TABLE_CONSTRUCTOR:
|
||||
{
|
||||
auto* ctor = static_cast<TableConstructorExpr*>(init.get());
|
||||
if ( ctor->GetAttrs() )
|
||||
id->AddAttrs(ctor->GetAttrs());
|
||||
}
|
||||
{
|
||||
auto* ctor = static_cast<TableConstructorExpr*>(init.get());
|
||||
if ( ctor->GetAttrs() )
|
||||
id->AddAttrs(ctor->GetAttrs());
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_SET_CONSTRUCTOR:
|
||||
{
|
||||
auto* ctor = static_cast<SetConstructorExpr*>(init.get());
|
||||
if ( ctor->GetAttrs() )
|
||||
id->AddAttrs(ctor->GetAttrs());
|
||||
}
|
||||
{
|
||||
auto* ctor = static_cast<SetConstructorExpr*>(init.get());
|
||||
if ( ctor->GetAttrs() )
|
||||
id->AddAttrs(ctor->GetAttrs());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -256,55 +256,55 @@ bool BitTorrentTracker_Analyzer::ParseRequest(char* line)
|
|||
switch ( req_state )
|
||||
{
|
||||
case detail::BTT_REQ_GET:
|
||||
{
|
||||
regmatch_t match[1];
|
||||
if ( regexec(&r_get, line, 1, match, 0) )
|
||||
{
|
||||
regmatch_t match[1];
|
||||
if ( regexec(&r_get, line, 1, match, 0) )
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP GET");
|
||||
stop_orig = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
regmatch_t match_end[1];
|
||||
if ( ! regexec(&r_get_end, line, 1, match_end, 0) )
|
||||
{
|
||||
if ( match_end[0].rm_so <= match[0].rm_eo )
|
||||
{
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP GET");
|
||||
stop_orig = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
regmatch_t match_end[1];
|
||||
if ( ! regexec(&r_get_end, line, 1, match_end, 0) )
|
||||
{
|
||||
if ( match_end[0].rm_so <= match[0].rm_eo )
|
||||
{
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP GET");
|
||||
stop_orig = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
keep_alive = (line[match_end[0].rm_eo - 1] == '1');
|
||||
line[match_end[0].rm_so] = 0;
|
||||
}
|
||||
|
||||
RequestGet(&line[match[0].rm_eo]);
|
||||
|
||||
req_state = detail::BTT_REQ_HEADER;
|
||||
keep_alive = (line[match_end[0].rm_eo - 1] == '1');
|
||||
line[match_end[0].rm_so] = 0;
|
||||
}
|
||||
|
||||
RequestGet(&line[match[0].rm_eo]);
|
||||
|
||||
req_state = detail::BTT_REQ_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case detail::BTT_REQ_HEADER:
|
||||
{
|
||||
if ( ! *line )
|
||||
{
|
||||
if ( ! *line )
|
||||
{
|
||||
EmitRequest();
|
||||
req_state = detail::BTT_REQ_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
regmatch_t match[1];
|
||||
if ( regexec(&r_hdr, line, 1, match, 0) )
|
||||
{
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP request header");
|
||||
stop_orig = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
*strchr(line, ':') = 0; // this cannot fail - see regex_hdr
|
||||
RequestHeader(line, &line[match[0].rm_eo]);
|
||||
EmitRequest();
|
||||
req_state = detail::BTT_REQ_DONE;
|
||||
break;
|
||||
}
|
||||
|
||||
regmatch_t match[1];
|
||||
if ( regexec(&r_hdr, line, 1, match, 0) )
|
||||
{
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP request header");
|
||||
stop_orig = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
*strchr(line, ':') = 0; // this cannot fail - see regex_hdr
|
||||
RequestHeader(line, &line[match[0].rm_eo]);
|
||||
}
|
||||
break;
|
||||
|
||||
case detail::BTT_REQ_DONE:
|
||||
|
@ -356,27 +356,27 @@ bool BitTorrentTracker_Analyzer::ParseResponse(char* line)
|
|||
switch ( res_state )
|
||||
{
|
||||
case detail::BTT_RES_STATUS:
|
||||
{
|
||||
if ( res_allow_blank_line && ! *line )
|
||||
{
|
||||
if ( res_allow_blank_line && ! *line )
|
||||
{
|
||||
// There may be an empty line after the bencoded
|
||||
// directory, if this is a keep-alive connection.
|
||||
// Ignore it.
|
||||
res_allow_blank_line = false;
|
||||
break;
|
||||
}
|
||||
|
||||
regmatch_t match[1];
|
||||
if ( regexec(&r_stat, line, 1, match, 0) )
|
||||
{
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP status");
|
||||
stop_resp = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ResponseStatus(&line[match[0].rm_eo]);
|
||||
res_state = detail::BTT_RES_HEADER;
|
||||
// There may be an empty line after the bencoded
|
||||
// directory, if this is a keep-alive connection.
|
||||
// Ignore it.
|
||||
res_allow_blank_line = false;
|
||||
break;
|
||||
}
|
||||
|
||||
regmatch_t match[1];
|
||||
if ( regexec(&r_stat, line, 1, match, 0) )
|
||||
{
|
||||
ProtocolViolation("BitTorrentTracker: invalid HTTP status");
|
||||
stop_resp = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
ResponseStatus(&line[match[0].rm_eo]);
|
||||
res_state = detail::BTT_RES_HEADER;
|
||||
}
|
||||
break;
|
||||
|
||||
case detail::BTT_RES_HEADER:
|
||||
|
@ -523,127 +523,122 @@ int BitTorrentTracker_Analyzer::ResponseParseBenc(void)
|
|||
switch ( benc_state )
|
||||
{
|
||||
case detail::BENC_STATE_EMPTY:
|
||||
{
|
||||
switch ( res_buf_pos[0] )
|
||||
{
|
||||
switch ( res_buf_pos[0] )
|
||||
{
|
||||
case 'd':
|
||||
switch ( benc_stack.size() )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
benc_raw = res_buf_pos;
|
||||
benc_raw_type = detail::BENC_TYPE_DIR;
|
||||
/* fall through */
|
||||
default:
|
||||
VIOLATION_IF(benc_stack.back() == 'd' &&
|
||||
! (benc_count.back() % 2),
|
||||
"BitTorrentTracker: directory key is not a string "
|
||||
"but a directory")
|
||||
++benc_raw_len;
|
||||
}
|
||||
|
||||
benc_stack.push_back('d');
|
||||
benc_count.push_back(0);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
switch ( benc_stack.size() )
|
||||
{
|
||||
case 0:
|
||||
VIOLATION_IF(1, "BitTorrentTracker: not a bencoded directory "
|
||||
"(first char: l)")
|
||||
/* fall through */
|
||||
|
||||
case 1:
|
||||
benc_raw = res_buf_pos;
|
||||
benc_raw_type = detail::BENC_TYPE_LIST;
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
VIOLATION_IF(benc_stack.back() == 'd' &&
|
||||
! (benc_count.back() % 2),
|
||||
"BitTorrentTracker: directory key is not a string "
|
||||
"but a list")
|
||||
++benc_raw_len;
|
||||
}
|
||||
|
||||
benc_stack.push_back('l');
|
||||
benc_count.push_back(0);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
VIOLATION_IF(
|
||||
! benc_stack.size(),
|
||||
"BitTorrentTracker: not a bencoded directory (first char: i)")
|
||||
VIOLATION_IF(
|
||||
benc_stack.back() == 'd' && ! (benc_count.back() % 2),
|
||||
"BitTorrentTracker: directory key is not a string but an int")
|
||||
|
||||
if ( benc_raw_type != detail::BENC_TYPE_NONE )
|
||||
case 'd':
|
||||
switch ( benc_stack.size() )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
benc_raw = res_buf_pos;
|
||||
benc_raw_type = detail::BENC_TYPE_DIR;
|
||||
/* fall through */
|
||||
default:
|
||||
VIOLATION_IF(benc_stack.back() == 'd' && ! (benc_count.back() % 2),
|
||||
"BitTorrentTracker: directory key is not a string "
|
||||
"but a directory")
|
||||
++benc_raw_len;
|
||||
}
|
||||
|
||||
benc_state = detail::BENC_STATE_INT1;
|
||||
break;
|
||||
benc_stack.push_back('d');
|
||||
benc_count.push_back(0);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
VIOLATION_IF(
|
||||
! benc_stack.size(),
|
||||
"BitTorrentTracker: not a bencoded directory (first char: e)")
|
||||
VIOLATION_IF(benc_stack.back() == 'd' && benc_count.back() % 2,
|
||||
"BitTorrentTracker: directory has an odd count of members")
|
||||
case 'l':
|
||||
switch ( benc_stack.size() )
|
||||
{
|
||||
case 0:
|
||||
VIOLATION_IF(1, "BitTorrentTracker: not a bencoded directory "
|
||||
"(first char: l)")
|
||||
/* fall through */
|
||||
|
||||
if ( benc_raw_type != detail::BENC_TYPE_NONE )
|
||||
case 1:
|
||||
benc_raw = res_buf_pos;
|
||||
benc_raw_type = detail::BENC_TYPE_LIST;
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
VIOLATION_IF(benc_stack.back() == 'd' && ! (benc_count.back() % 2),
|
||||
"BitTorrentTracker: directory key is not a string "
|
||||
"but a list")
|
||||
++benc_raw_len;
|
||||
}
|
||||
|
||||
if ( benc_stack.size() == 2 )
|
||||
{ // coming back to level 1
|
||||
ResponseBenc(benc_key_len, benc_key, benc_raw_type, benc_raw_len,
|
||||
benc_raw);
|
||||
benc_key = nullptr;
|
||||
benc_key_len = 0;
|
||||
benc_raw = nullptr;
|
||||
benc_raw_len = 0;
|
||||
benc_raw_type = detail::BENC_TYPE_NONE;
|
||||
}
|
||||
benc_stack.push_back('l');
|
||||
benc_count.push_back(0);
|
||||
break;
|
||||
|
||||
benc_stack.pop_back();
|
||||
benc_count.pop_back();
|
||||
case 'i':
|
||||
VIOLATION_IF(! benc_stack.size(),
|
||||
"BitTorrentTracker: not a bencoded directory (first char: i)")
|
||||
VIOLATION_IF(benc_stack.back() == 'd' && ! (benc_count.back() % 2),
|
||||
"BitTorrentTracker: directory key is not a string but an int")
|
||||
|
||||
if ( benc_stack.size() )
|
||||
INC_COUNT
|
||||
else
|
||||
{ // benc parsing successful
|
||||
++res_buf_pos;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
if ( benc_raw_type != detail::BENC_TYPE_NONE )
|
||||
++benc_raw_len;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
VIOLATION_IF(
|
||||
! benc_stack.size(),
|
||||
"BitTorrentTracker: not a bencoded directory (first char: [0-9])")
|
||||
benc_state = detail::BENC_STATE_INT1;
|
||||
break;
|
||||
|
||||
if ( benc_raw_type != detail::BENC_TYPE_NONE )
|
||||
++benc_raw_len;
|
||||
case 'e':
|
||||
VIOLATION_IF(! benc_stack.size(),
|
||||
"BitTorrentTracker: not a bencoded directory (first char: e)")
|
||||
VIOLATION_IF(benc_stack.back() == 'd' && benc_count.back() % 2,
|
||||
"BitTorrentTracker: directory has an odd count of members")
|
||||
|
||||
benc_strlen = res_buf_pos;
|
||||
benc_state = detail::BENC_STATE_STR1;
|
||||
break;
|
||||
if ( benc_raw_type != detail::BENC_TYPE_NONE )
|
||||
++benc_raw_len;
|
||||
|
||||
default:
|
||||
VIOLATION_IF(1, "BitTorrentTracker: no valid bencoding")
|
||||
}
|
||||
if ( benc_stack.size() == 2 )
|
||||
{ // coming back to level 1
|
||||
ResponseBenc(benc_key_len, benc_key, benc_raw_type, benc_raw_len,
|
||||
benc_raw);
|
||||
benc_key = nullptr;
|
||||
benc_key_len = 0;
|
||||
benc_raw = nullptr;
|
||||
benc_raw_len = 0;
|
||||
benc_raw_type = detail::BENC_TYPE_NONE;
|
||||
}
|
||||
|
||||
benc_stack.pop_back();
|
||||
benc_count.pop_back();
|
||||
|
||||
if ( benc_stack.size() )
|
||||
INC_COUNT
|
||||
else
|
||||
{ // benc parsing successful
|
||||
++res_buf_pos;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
VIOLATION_IF(
|
||||
! benc_stack.size(),
|
||||
"BitTorrentTracker: not a bencoded directory (first char: [0-9])")
|
||||
|
||||
if ( benc_raw_type != detail::BENC_TYPE_NONE )
|
||||
++benc_raw_len;
|
||||
|
||||
benc_strlen = res_buf_pos;
|
||||
benc_state = detail::BENC_STATE_STR1;
|
||||
break;
|
||||
|
||||
default:
|
||||
VIOLATION_IF(1, "BitTorrentTracker: no valid bencoding")
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case detail::BENC_STATE_INT1:
|
||||
|
|
|
@ -698,190 +698,188 @@ bool DNS_Interpreter::ParseRR_EDNS(detail::DNS_MsgInfo* msg, const u_char*& data
|
|||
switch ( option_code )
|
||||
{
|
||||
case detail::TYPE_ECS:
|
||||
{
|
||||
// must be 4 bytes + variable number of octets for address
|
||||
if ( option_len <= 4 )
|
||||
{
|
||||
// must be 4 bytes + variable number of octets for address
|
||||
if ( option_len <= 4 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_option_len");
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
detail::EDNS_ECS opt{};
|
||||
uint16_t ecs_family = ExtractShort(data, option_len);
|
||||
uint16_t source_scope = ExtractShort(data, option_len);
|
||||
opt.ecs_src_pfx_len = (source_scope >> 8) & 0xff;
|
||||
opt.ecs_scp_pfx_len = source_scope & 0xff;
|
||||
|
||||
// ADDRESS, variable number of octets, contains either an IPv4 or
|
||||
// IPv6 address, depending on FAMILY, which MUST be truncated to the
|
||||
// number of bits indicated by the SOURCE PREFIX-LENGTH field,
|
||||
// padding with 0 bits to pad to the end of the last octet needed.
|
||||
if ( ecs_family == L3_IPV4 )
|
||||
{
|
||||
if ( opt.ecs_src_pfx_len > 32 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v4_prefix",
|
||||
util::fmt("%" PRIu16 " bits", opt.ecs_src_pfx_len));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt.ecs_src_pfx_len > option_len * 8 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v4",
|
||||
util::fmt("need %" PRIu16 " bits, have %d bits",
|
||||
opt.ecs_src_pfx_len, option_len * 8));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
opt.ecs_family = make_intrusive<StringVal>("v4");
|
||||
uint32_t addr = 0;
|
||||
uint16_t shift_factor = 3;
|
||||
int bits_left = opt.ecs_src_pfx_len;
|
||||
|
||||
while ( bits_left > 0 )
|
||||
{
|
||||
addr |= data[0] << (shift_factor * 8);
|
||||
data++;
|
||||
shift_factor--;
|
||||
option_len--;
|
||||
bits_left -= 8;
|
||||
}
|
||||
|
||||
addr = htonl(addr);
|
||||
opt.ecs_addr = make_intrusive<AddrVal>(addr);
|
||||
}
|
||||
else if ( ecs_family == L3_IPV6 )
|
||||
{
|
||||
if ( opt.ecs_src_pfx_len > 128 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v6_prefix",
|
||||
util::fmt("%" PRIu16 " bits", opt.ecs_src_pfx_len));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt.ecs_src_pfx_len > option_len * 8 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v6",
|
||||
util::fmt("need %" PRIu16 " bits, have %d bits",
|
||||
opt.ecs_src_pfx_len, option_len * 8));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
opt.ecs_family = make_intrusive<StringVal>("v6");
|
||||
uint32_t addr[4] = {0};
|
||||
uint16_t shift_factor = 15;
|
||||
int bits_left = opt.ecs_src_pfx_len;
|
||||
int i = 0;
|
||||
|
||||
while ( bits_left > 0 )
|
||||
{
|
||||
addr[i / 4] |= data[0] << ((shift_factor % 4) * 8);
|
||||
data++;
|
||||
i++;
|
||||
shift_factor--;
|
||||
option_len--;
|
||||
bits_left -= 8;
|
||||
}
|
||||
|
||||
for ( uint8_t i = 0; i < 4; i++ )
|
||||
{
|
||||
addr[i] = htonl(addr[i]);
|
||||
}
|
||||
opt.ecs_addr = make_intrusive<AddrVal>(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// non ipv4/ipv6 family address
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
analyzer->EnqueueConnEvent(dns_EDNS_ecs, analyzer->ConnVal(),
|
||||
msg->BuildHdrVal(), msg->BuildEDNS_ECS_Val(&opt));
|
||||
data += option_len;
|
||||
break;
|
||||
} // END EDNS ECS
|
||||
|
||||
case TYPE_TCP_KA:
|
||||
{
|
||||
EDNS_TCP_KEEPALIVE edns_tcp_keepalive{.keepalive_timeout_omitted = true,
|
||||
.keepalive_timeout = 0};
|
||||
if ( option_len == 0 || option_len == 2 )
|
||||
{
|
||||
// 0 bytes is permitted by RFC 7828, showing that the timeout value is
|
||||
// omitted.
|
||||
if ( option_len == 2 )
|
||||
{
|
||||
edns_tcp_keepalive.keepalive_timeout = ExtractShort(data, option_len);
|
||||
edns_tcp_keepalive.keepalive_timeout_omitted = false;
|
||||
}
|
||||
|
||||
if ( analyzer->Conn()->ConnTransport() == TRANSPORT_UDP )
|
||||
{
|
||||
/*
|
||||
* Based on RFC 7828 (3.2.1/3.2.2), clients and servers MUST NOT
|
||||
* negotiate TCP Keepalive timeout in DNS-over-UDP.
|
||||
*/
|
||||
analyzer->Weird("EDNS_TCP_Keepalive_In_UDP");
|
||||
}
|
||||
|
||||
analyzer->EnqueueConnEvent(dns_EDNS_tcp_keepalive, analyzer->ConnVal(),
|
||||
msg->BuildHdrVal(),
|
||||
msg->BuildEDNS_TCP_KA_Val(&edns_tcp_keepalive));
|
||||
}
|
||||
else
|
||||
{
|
||||
// error. MUST BE 0 or 2 bytes. skip
|
||||
data += option_len;
|
||||
}
|
||||
break;
|
||||
} // END EDNS TCP KEEPALIVE
|
||||
|
||||
case TYPE_COOKIE:
|
||||
{
|
||||
EDNS_COOKIE cookie{};
|
||||
if ( option_len != 8 && ! (option_len >= 16 && option_len <= 40) )
|
||||
{
|
||||
/*
|
||||
* option length for DNS Cookie must be 8 bytes (with client cookie only)
|
||||
* OR
|
||||
* between 16 bytes to 40 bytes (with an 8 bytes client and an 8 to 32 bytes
|
||||
* server cookie)
|
||||
*/
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
int client_cookie_len = 8;
|
||||
int server_cookie_len = option_len - client_cookie_len;
|
||||
|
||||
cookie.client_cookie =
|
||||
ExtractStream(data, client_cookie_len, client_cookie_len);
|
||||
cookie.server_cookie = nullptr;
|
||||
|
||||
if ( server_cookie_len >= 8 )
|
||||
{
|
||||
cookie.server_cookie =
|
||||
ExtractStream(data, server_cookie_len, server_cookie_len);
|
||||
}
|
||||
|
||||
analyzer->EnqueueConnEvent(dns_EDNS_cookie, analyzer->ConnVal(),
|
||||
msg->BuildHdrVal(),
|
||||
msg->BuildEDNS_COOKIE_Val(&cookie));
|
||||
|
||||
break;
|
||||
} // END EDNS COOKIE
|
||||
|
||||
default:
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_option_len");
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
detail::EDNS_ECS opt{};
|
||||
uint16_t ecs_family = ExtractShort(data, option_len);
|
||||
uint16_t source_scope = ExtractShort(data, option_len);
|
||||
opt.ecs_src_pfx_len = (source_scope >> 8) & 0xff;
|
||||
opt.ecs_scp_pfx_len = source_scope & 0xff;
|
||||
|
||||
// ADDRESS, variable number of octets, contains either an IPv4 or
|
||||
// IPv6 address, depending on FAMILY, which MUST be truncated to the
|
||||
// number of bits indicated by the SOURCE PREFIX-LENGTH field,
|
||||
// padding with 0 bits to pad to the end of the last octet needed.
|
||||
if ( ecs_family == L3_IPV4 )
|
||||
{
|
||||
if ( opt.ecs_src_pfx_len > 32 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v4_prefix",
|
||||
util::fmt("%" PRIu16 " bits", opt.ecs_src_pfx_len));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt.ecs_src_pfx_len > option_len * 8 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v4",
|
||||
util::fmt("need %" PRIu16 " bits, have %d bits",
|
||||
opt.ecs_src_pfx_len, option_len * 8));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
opt.ecs_family = make_intrusive<StringVal>("v4");
|
||||
uint32_t addr = 0;
|
||||
uint16_t shift_factor = 3;
|
||||
int bits_left = opt.ecs_src_pfx_len;
|
||||
|
||||
while ( bits_left > 0 )
|
||||
{
|
||||
addr |= data[0] << (shift_factor * 8);
|
||||
data++;
|
||||
shift_factor--;
|
||||
option_len--;
|
||||
bits_left -= 8;
|
||||
}
|
||||
|
||||
addr = htonl(addr);
|
||||
opt.ecs_addr = make_intrusive<AddrVal>(addr);
|
||||
}
|
||||
else if ( ecs_family == L3_IPV6 )
|
||||
{
|
||||
if ( opt.ecs_src_pfx_len > 128 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v6_prefix",
|
||||
util::fmt("%" PRIu16 " bits", opt.ecs_src_pfx_len));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( opt.ecs_src_pfx_len > option_len * 8 )
|
||||
{
|
||||
analyzer->Weird("EDNS_ECS_invalid_addr_v6",
|
||||
util::fmt("need %" PRIu16 " bits, have %d bits",
|
||||
opt.ecs_src_pfx_len, option_len * 8));
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
opt.ecs_family = make_intrusive<StringVal>("v6");
|
||||
uint32_t addr[4] = {0};
|
||||
uint16_t shift_factor = 15;
|
||||
int bits_left = opt.ecs_src_pfx_len;
|
||||
int i = 0;
|
||||
|
||||
while ( bits_left > 0 )
|
||||
{
|
||||
addr[i / 4] |= data[0] << ((shift_factor % 4) * 8);
|
||||
data++;
|
||||
i++;
|
||||
shift_factor--;
|
||||
option_len--;
|
||||
bits_left -= 8;
|
||||
}
|
||||
|
||||
for ( uint8_t i = 0; i < 4; i++ )
|
||||
{
|
||||
addr[i] = htonl(addr[i]);
|
||||
}
|
||||
opt.ecs_addr = make_intrusive<AddrVal>(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// non ipv4/ipv6 family address
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
analyzer->EnqueueConnEvent(dns_EDNS_ecs, analyzer->ConnVal(), msg->BuildHdrVal(),
|
||||
msg->BuildEDNS_ECS_Val(&opt));
|
||||
data += option_len;
|
||||
break;
|
||||
} // END EDNS ECS
|
||||
|
||||
case TYPE_TCP_KA:
|
||||
{
|
||||
EDNS_TCP_KEEPALIVE edns_tcp_keepalive{.keepalive_timeout_omitted = true,
|
||||
.keepalive_timeout = 0};
|
||||
if ( option_len == 0 || option_len == 2 )
|
||||
{
|
||||
// 0 bytes is permitted by RFC 7828, showing that the timeout value is
|
||||
// omitted.
|
||||
if ( option_len == 2 )
|
||||
{
|
||||
edns_tcp_keepalive.keepalive_timeout = ExtractShort(data, option_len);
|
||||
edns_tcp_keepalive.keepalive_timeout_omitted = false;
|
||||
}
|
||||
|
||||
if ( analyzer->Conn()->ConnTransport() == TRANSPORT_UDP )
|
||||
{
|
||||
/*
|
||||
* Based on RFC 7828 (3.2.1/3.2.2), clients and servers MUST NOT
|
||||
* negotiate TCP Keepalive timeout in DNS-over-UDP.
|
||||
*/
|
||||
analyzer->Weird("EDNS_TCP_Keepalive_In_UDP");
|
||||
}
|
||||
|
||||
analyzer->EnqueueConnEvent(dns_EDNS_tcp_keepalive, analyzer->ConnVal(),
|
||||
msg->BuildHdrVal(),
|
||||
msg->BuildEDNS_TCP_KA_Val(&edns_tcp_keepalive));
|
||||
}
|
||||
else
|
||||
{
|
||||
// error. MUST BE 0 or 2 bytes. skip
|
||||
data += option_len;
|
||||
}
|
||||
break;
|
||||
} // END EDNS TCP KEEPALIVE
|
||||
|
||||
case TYPE_COOKIE:
|
||||
{
|
||||
EDNS_COOKIE cookie{};
|
||||
if ( option_len != 8 && ! (option_len >= 16 && option_len <= 40) )
|
||||
{
|
||||
/*
|
||||
* option length for DNS Cookie must be 8 bytes (with client cookie only)
|
||||
* OR
|
||||
* between 16 bytes to 40 bytes (with an 8 bytes client and an 8 to 32 bytes
|
||||
* server cookie)
|
||||
*/
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
|
||||
int client_cookie_len = 8;
|
||||
int server_cookie_len = option_len - client_cookie_len;
|
||||
|
||||
cookie.client_cookie = ExtractStream(data, client_cookie_len, client_cookie_len);
|
||||
cookie.server_cookie = nullptr;
|
||||
|
||||
if ( server_cookie_len >= 8 )
|
||||
{
|
||||
cookie.server_cookie =
|
||||
ExtractStream(data, server_cookie_len, server_cookie_len);
|
||||
}
|
||||
|
||||
analyzer->EnqueueConnEvent(dns_EDNS_cookie, analyzer->ConnVal(), msg->BuildHdrVal(),
|
||||
msg->BuildEDNS_COOKIE_Val(&cookie));
|
||||
|
||||
break;
|
||||
} // END EDNS COOKIE
|
||||
|
||||
default:
|
||||
{
|
||||
data += option_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -925,52 +925,51 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
|
|||
switch ( request_state )
|
||||
{
|
||||
case EXPECT_REQUEST_LINE:
|
||||
{
|
||||
int res = HTTP_RequestLine(line, end_of_line);
|
||||
|
||||
if ( res < 0 )
|
||||
return;
|
||||
|
||||
else if ( res > 0 )
|
||||
{
|
||||
int res = HTTP_RequestLine(line, end_of_line);
|
||||
++num_requests;
|
||||
|
||||
if ( res < 0 )
|
||||
return;
|
||||
if ( ! keep_alive && num_requests > 1 )
|
||||
Weird("unexpected_multiple_HTTP_requests");
|
||||
|
||||
else if ( res > 0 )
|
||||
{
|
||||
++num_requests;
|
||||
|
||||
if ( ! keep_alive && num_requests > 1 )
|
||||
Weird("unexpected_multiple_HTTP_requests");
|
||||
|
||||
request_state = EXPECT_REQUEST_MESSAGE;
|
||||
request_ongoing = 1;
|
||||
unanswered_requests.push(request_method);
|
||||
HTTP_Request();
|
||||
InitHTTPMessage(content_line, request_message, is_orig, HTTP_BODY_MAYBE,
|
||||
len);
|
||||
}
|
||||
request_state = EXPECT_REQUEST_MESSAGE;
|
||||
request_ongoing = 1;
|
||||
unanswered_requests.push(request_method);
|
||||
HTTP_Request();
|
||||
InitHTTPMessage(content_line, request_message, is_orig, HTTP_BODY_MAYBE, len);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if ( ! RequestExpected() )
|
||||
HTTP_Event("crud_trailing_HTTP_request",
|
||||
analyzer::mime::to_string_val(line, end_of_line));
|
||||
else
|
||||
{
|
||||
if ( ! RequestExpected() )
|
||||
HTTP_Event("crud_trailing_HTTP_request",
|
||||
analyzer::mime::to_string_val(line, end_of_line));
|
||||
// We do see HTTP requests with a
|
||||
// trailing EOL that's not accounted
|
||||
// for by the content-length. This
|
||||
// will lead to a call to this method
|
||||
// with len==0 while we are expecting
|
||||
// a new request. Since HTTP servers
|
||||
// handle such requests gracefully,
|
||||
// we should do so as well.
|
||||
if ( len == 0 )
|
||||
Weird("empty_http_request");
|
||||
else
|
||||
{
|
||||
// We do see HTTP requests with a
|
||||
// trailing EOL that's not accounted
|
||||
// for by the content-length. This
|
||||
// will lead to a call to this method
|
||||
// with len==0 while we are expecting
|
||||
// a new request. Since HTTP servers
|
||||
// handle such requests gracefully,
|
||||
// we should do so as well.
|
||||
if ( len == 0 )
|
||||
Weird("empty_http_request");
|
||||
else
|
||||
{
|
||||
ProtocolViolation("not a http request line");
|
||||
request_state = EXPECT_REQUEST_NOTHING;
|
||||
}
|
||||
ProtocolViolation("not a http request line");
|
||||
request_state = EXPECT_REQUEST_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPECT_REQUEST_MESSAGE:
|
||||
|
|
|
@ -279,7 +279,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig)
|
|||
make_intrusive<StringVal>(type.c_str()),
|
||||
make_intrusive<StringVal>(channel.c_str()), std::move(set));
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
// Count of users and services on this server.
|
||||
case 255:
|
||||
|
@ -456,38 +456,38 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig)
|
|||
|
||||
// RPL_TOPIC reply.
|
||||
case 332:
|
||||
{
|
||||
if ( ! irc_channel_topic )
|
||||
break;
|
||||
|
||||
vector<string> parts = SplitWords(params, ' ');
|
||||
if ( parts.size() < 4 )
|
||||
{
|
||||
Weird("irc_invalid_topic_reply");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int pos = params.find(':');
|
||||
if ( pos < params.size() )
|
||||
{
|
||||
string topic = params.substr(pos + 1);
|
||||
const char* t = topic.c_str();
|
||||
|
||||
if ( *t == ':' )
|
||||
++t;
|
||||
|
||||
EnqueueConnEvent(irc_channel_topic, ConnVal(), val_mgr->Bool(orig),
|
||||
make_intrusive<StringVal>(parts[1].c_str()),
|
||||
make_intrusive<StringVal>(t));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weird("irc_invalid_topic_reply");
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
if ( ! irc_channel_topic )
|
||||
break;
|
||||
|
||||
vector<string> parts = SplitWords(params, ' ');
|
||||
if ( parts.size() < 4 )
|
||||
{
|
||||
Weird("irc_invalid_topic_reply");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int pos = params.find(':');
|
||||
if ( pos < params.size() )
|
||||
{
|
||||
string topic = params.substr(pos + 1);
|
||||
const char* t = topic.c_str();
|
||||
|
||||
if ( *t == ':' )
|
||||
++t;
|
||||
|
||||
EnqueueConnEvent(irc_channel_topic, ConnVal(), val_mgr->Bool(orig),
|
||||
make_intrusive<StringVal>(parts[1].c_str()),
|
||||
make_intrusive<StringVal>(t));
|
||||
}
|
||||
else
|
||||
{
|
||||
Weird("irc_invalid_topic_reply");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// WHO reply line.
|
||||
case 352:
|
||||
{
|
||||
|
|
|
@ -208,20 +208,19 @@ void TelnetAuthenticateOption::RecvSubOption(u_char* data, int len)
|
|||
switch ( data[0] )
|
||||
{
|
||||
case HERE_IS_AUTHENTICATION:
|
||||
{
|
||||
TelnetAuthenticateOption* peer = (TelnetAuthenticateOption*)endp->FindPeerOption(code);
|
||||
|
||||
if ( ! peer )
|
||||
{
|
||||
TelnetAuthenticateOption* peer =
|
||||
(TelnetAuthenticateOption*)endp->FindPeerOption(code);
|
||||
|
||||
if ( ! peer )
|
||||
{
|
||||
reporter->AnalyzerError(
|
||||
endp, "option peer missing in TelnetAuthenticateOption::RecvSubOption");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! peer->DidRequestAuthentication() )
|
||||
InconsistentOption(0);
|
||||
reporter->AnalyzerError(
|
||||
endp, "option peer missing in TelnetAuthenticateOption::RecvSubOption");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! peer->DidRequestAuthentication() )
|
||||
InconsistentOption(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SEND_ME_AUTHENTICATION:
|
||||
|
@ -247,11 +246,11 @@ void TelnetAuthenticateOption::RecvSubOption(u_char* data, int len)
|
|||
break;
|
||||
|
||||
case AUTHENTICATION_NAME:
|
||||
{
|
||||
char* auth_name = new char[len];
|
||||
util::safe_strncpy(auth_name, (char*)data + 1, len);
|
||||
endp->SetAuthName(auth_name);
|
||||
}
|
||||
{
|
||||
char* auth_name = new char[len];
|
||||
util::safe_strncpy(auth_name, (char*)data + 1, len);
|
||||
endp->SetAuthName(auth_name);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -155,57 +155,57 @@ void POP3_Analyzer::ProcessRequest(int length, const char* line)
|
|||
break;
|
||||
|
||||
case detail::AUTH_PLAIN:
|
||||
{
|
||||
// Format: "authorization identity<NUL>authentication
|
||||
// identity<NUL>password"
|
||||
char* str = (char*)decoded->Bytes();
|
||||
int len = decoded->Len();
|
||||
char* end = str + len;
|
||||
char* s;
|
||||
char* e;
|
||||
|
||||
for ( s = str; s < end && *s; ++s )
|
||||
;
|
||||
++s;
|
||||
|
||||
for ( e = s; e < end && *e; ++e )
|
||||
;
|
||||
|
||||
if ( e >= end )
|
||||
{
|
||||
// Format: "authorization identity<NUL>authentication
|
||||
// identity<NUL>password"
|
||||
char* str = (char*)decoded->Bytes();
|
||||
int len = decoded->Len();
|
||||
char* end = str + len;
|
||||
char* s;
|
||||
char* e;
|
||||
|
||||
for ( s = str; s < end && *s; ++s )
|
||||
;
|
||||
++s;
|
||||
|
||||
for ( e = s; e < end && *e; ++e )
|
||||
;
|
||||
|
||||
if ( e >= end )
|
||||
{
|
||||
Weird("pop3_malformed_auth_plain");
|
||||
delete decoded;
|
||||
return;
|
||||
}
|
||||
|
||||
user = s;
|
||||
s = e + 1;
|
||||
|
||||
if ( s >= end )
|
||||
{
|
||||
Weird("pop3_malformed_auth_plain");
|
||||
delete decoded;
|
||||
return;
|
||||
}
|
||||
|
||||
password.assign(s, len - (s - str));
|
||||
|
||||
break;
|
||||
Weird("pop3_malformed_auth_plain");
|
||||
delete decoded;
|
||||
return;
|
||||
}
|
||||
|
||||
user = s;
|
||||
s = e + 1;
|
||||
|
||||
if ( s >= end )
|
||||
{
|
||||
Weird("pop3_malformed_auth_plain");
|
||||
delete decoded;
|
||||
return;
|
||||
}
|
||||
|
||||
password.assign(s, len - (s - str));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case detail::AUTH_CRAM_MD5:
|
||||
{ // Format: "user<space>password-hash"
|
||||
const char* s;
|
||||
const char* str = (char*)decoded->CheckString();
|
||||
{ // Format: "user<space>password-hash"
|
||||
const char* s;
|
||||
const char* str = (char*)decoded->CheckString();
|
||||
|
||||
for ( s = str; *s && *s != '\t' && *s != ' '; ++s )
|
||||
;
|
||||
for ( s = str; *s && *s != '\t' && *s != ' '; ++s )
|
||||
;
|
||||
|
||||
user = std::string(str, s);
|
||||
password = "";
|
||||
user = std::string(str, s);
|
||||
password = "";
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case detail::AUTH:
|
||||
break;
|
||||
|
@ -694,16 +694,16 @@ void POP3_Analyzer::ProcessReply(int length, const char* line)
|
|||
|
||||
case detail::TOP:
|
||||
case detail::RETR:
|
||||
{
|
||||
int data_len = end_of_line - line;
|
||||
if ( ! mail )
|
||||
// ProcessReply is only called if orig == false
|
||||
BeginData(false);
|
||||
ProcessData(data_len, line);
|
||||
if ( requestForMultiLine == true )
|
||||
multiLine = true;
|
||||
break;
|
||||
}
|
||||
{
|
||||
int data_len = end_of_line - line;
|
||||
if ( ! mail )
|
||||
// ProcessReply is only called if orig == false
|
||||
BeginData(false);
|
||||
ProcessData(data_len, line);
|
||||
if ( requestForMultiLine == true )
|
||||
multiLine = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case detail::CAPA:
|
||||
ProtocolConfirmation();
|
||||
|
|
|
@ -32,42 +32,42 @@ bool PortmapperInterp::RPC_BuildCall(RPC_CallInfo* c, const u_char*& buf, int& n
|
|||
break;
|
||||
|
||||
case PMAPPROC_SET:
|
||||
{
|
||||
auto m = ExtractMapping(buf, n);
|
||||
if ( ! m )
|
||||
return false;
|
||||
c->AddVal(std::move(m));
|
||||
}
|
||||
{
|
||||
auto m = ExtractMapping(buf, n);
|
||||
if ( ! m )
|
||||
return false;
|
||||
c->AddVal(std::move(m));
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_UNSET:
|
||||
{
|
||||
auto m = ExtractMapping(buf, n);
|
||||
if ( ! m )
|
||||
return false;
|
||||
c->AddVal(std::move(m));
|
||||
}
|
||||
{
|
||||
auto m = ExtractMapping(buf, n);
|
||||
if ( ! m )
|
||||
return false;
|
||||
c->AddVal(std::move(m));
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_GETPORT:
|
||||
{
|
||||
auto pr = ExtractPortRequest(buf, n);
|
||||
if ( ! pr )
|
||||
return false;
|
||||
c->AddVal(std::move(pr));
|
||||
}
|
||||
{
|
||||
auto pr = ExtractPortRequest(buf, n);
|
||||
if ( ! pr )
|
||||
return false;
|
||||
c->AddVal(std::move(pr));
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_DUMP:
|
||||
break;
|
||||
|
||||
case PMAPPROC_CALLIT:
|
||||
{
|
||||
auto call_it = ExtractCallItRequest(buf, n);
|
||||
if ( ! call_it )
|
||||
return false;
|
||||
c->AddVal(std::move(call_it));
|
||||
}
|
||||
{
|
||||
auto call_it = ExtractCallItRequest(buf, n);
|
||||
if ( ! call_it )
|
||||
return false;
|
||||
c->AddVal(std::move(call_it));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -636,75 +636,73 @@ void Contents_RPC::DeliverStream(int len, const u_char* data, bool orig)
|
|||
// no break. fall through
|
||||
|
||||
case WAIT_FOR_MARKER:
|
||||
{
|
||||
bool got_marker = marker_buf.ConsumeChunk(data, len);
|
||||
|
||||
if ( got_marker )
|
||||
{
|
||||
bool got_marker = marker_buf.ConsumeChunk(data, len);
|
||||
const u_char* dummy_p = marker_buf.GetBuf();
|
||||
int dummy_len = (int)marker_buf.GetFill();
|
||||
|
||||
if ( got_marker )
|
||||
// have full marker
|
||||
marker = extract_XDR_uint32(dummy_p, dummy_len);
|
||||
marker_buf.Init(4, 4);
|
||||
|
||||
if ( ! dummy_p )
|
||||
{
|
||||
const u_char* dummy_p = marker_buf.GetBuf();
|
||||
int dummy_len = (int)marker_buf.GetFill();
|
||||
|
||||
// have full marker
|
||||
marker = extract_XDR_uint32(dummy_p, dummy_len);
|
||||
marker_buf.Init(4, 4);
|
||||
|
||||
if ( ! dummy_p )
|
||||
{
|
||||
reporter->AnalyzerError(this,
|
||||
"inconsistent RPC record marker extraction");
|
||||
return;
|
||||
}
|
||||
|
||||
last_frag = (marker & 0x80000000) != 0;
|
||||
marker &= 0x7fffffff;
|
||||
// printf("%.6f %d marker= %u <> last_frag= %d <> expected=%llu <>
|
||||
// processed= %llu <> len = %d\n", run_state::network_time, IsOrig(),
|
||||
// marker,
|
||||
// last_frag, msg_buf.GetExpected(), msg_buf.GetProcessed(), len);
|
||||
|
||||
if ( ! msg_buf.AddToExpected(marker) )
|
||||
Conn()->Weird("RPC_message_too_long",
|
||||
util::fmt("%" PRId64, msg_buf.GetExpected()));
|
||||
|
||||
if ( last_frag )
|
||||
state = WAIT_FOR_LAST_DATA;
|
||||
else
|
||||
state = WAIT_FOR_DATA;
|
||||
reporter->AnalyzerError(this, "inconsistent RPC record marker extraction");
|
||||
return;
|
||||
}
|
||||
|
||||
last_frag = (marker & 0x80000000) != 0;
|
||||
marker &= 0x7fffffff;
|
||||
// printf("%.6f %d marker= %u <> last_frag= %d <> expected=%llu <>
|
||||
// processed= %llu <> len = %d\n", run_state::network_time, IsOrig(),
|
||||
// marker,
|
||||
// last_frag, msg_buf.GetExpected(), msg_buf.GetProcessed(), len);
|
||||
|
||||
if ( ! msg_buf.AddToExpected(marker) )
|
||||
Conn()->Weird("RPC_message_too_long",
|
||||
util::fmt("%" PRId64, msg_buf.GetExpected()));
|
||||
|
||||
if ( last_frag )
|
||||
state = WAIT_FOR_LAST_DATA;
|
||||
else
|
||||
state = WAIT_FOR_DATA;
|
||||
}
|
||||
}
|
||||
// Else remain in state. Haven't got the full 4 bytes
|
||||
// for the marker yet.
|
||||
break;
|
||||
|
||||
case WAIT_FOR_DATA:
|
||||
case WAIT_FOR_LAST_DATA:
|
||||
{
|
||||
bool got_all_data = msg_buf.ConsumeChunk(data, len);
|
||||
|
||||
if ( got_all_data )
|
||||
{
|
||||
bool got_all_data = msg_buf.ConsumeChunk(data, len);
|
||||
|
||||
if ( got_all_data )
|
||||
// Got all the data we expected. Now let's
|
||||
// see whether there is another fragment
|
||||
// coming or whether we just finished the
|
||||
// last fragment.
|
||||
if ( state == WAIT_FOR_LAST_DATA )
|
||||
{
|
||||
// Got all the data we expected. Now let's
|
||||
// see whether there is another fragment
|
||||
// coming or whether we just finished the
|
||||
// last fragment.
|
||||
if ( state == WAIT_FOR_LAST_DATA )
|
||||
{
|
||||
const u_char* dummy_p = msg_buf.GetBuf();
|
||||
int dummy_len = (int)msg_buf.GetFill();
|
||||
const u_char* dummy_p = msg_buf.GetBuf();
|
||||
int dummy_len = (int)msg_buf.GetFill();
|
||||
|
||||
if ( ! interp->DeliverRPC(dummy_p, dummy_len,
|
||||
(int)msg_buf.GetExpected(), IsOrig(),
|
||||
start_time, last_time) )
|
||||
Conn()->Weird("partial_RPC");
|
||||
if ( ! interp->DeliverRPC(dummy_p, dummy_len, (int)msg_buf.GetExpected(),
|
||||
IsOrig(), start_time, last_time) )
|
||||
Conn()->Weird("partial_RPC");
|
||||
|
||||
state = WAIT_FOR_MESSAGE;
|
||||
}
|
||||
else
|
||||
state = WAIT_FOR_MARKER;
|
||||
state = WAIT_FOR_MESSAGE;
|
||||
}
|
||||
// Else remain in state. Haven't read all the data
|
||||
// yet.
|
||||
else
|
||||
state = WAIT_FOR_MARKER;
|
||||
}
|
||||
// Else remain in state. Haven't read all the data
|
||||
// yet.
|
||||
}
|
||||
break;
|
||||
} // end switch
|
||||
} // end while
|
||||
|
|
|
@ -134,14 +134,14 @@ struct val_converter
|
|||
case TYPE_STRING:
|
||||
return make_intrusive<StringVal>(a.size(), a.data());
|
||||
case TYPE_FILE:
|
||||
{
|
||||
auto file = File::Get(a.data());
|
||||
{
|
||||
auto file = File::Get(a.data());
|
||||
|
||||
if ( file )
|
||||
return make_intrusive<FileVal>(std::move(file));
|
||||
if ( file )
|
||||
return make_intrusive<FileVal>(std::move(file));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -842,231 +842,231 @@ broker::expected<broker::data> val_to_data(const Val* v)
|
|||
case TYPE_COUNT:
|
||||
return {v->AsCount()};
|
||||
case TYPE_PORT:
|
||||
{
|
||||
auto p = v->AsPortVal();
|
||||
return {broker::port(p->Port(), to_broker_port_proto(p->PortType()))};
|
||||
}
|
||||
{
|
||||
auto p = v->AsPortVal();
|
||||
return {broker::port(p->Port(), to_broker_port_proto(p->PortType()))};
|
||||
}
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
auto a = v->AsAddr();
|
||||
in6_addr tmp;
|
||||
a.CopyIPv6(&tmp);
|
||||
return {broker::address(reinterpret_cast<const uint32_t*>(&tmp),
|
||||
broker::address::family::ipv6,
|
||||
broker::address::byte_order::network)};
|
||||
}
|
||||
{
|
||||
auto a = v->AsAddr();
|
||||
in6_addr tmp;
|
||||
a.CopyIPv6(&tmp);
|
||||
return {broker::address(reinterpret_cast<const uint32_t*>(&tmp),
|
||||
broker::address::family::ipv6,
|
||||
broker::address::byte_order::network)};
|
||||
}
|
||||
break;
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
auto s = v->AsSubNet();
|
||||
in6_addr tmp;
|
||||
s.Prefix().CopyIPv6(&tmp);
|
||||
auto a = broker::address(reinterpret_cast<const uint32_t*>(&tmp),
|
||||
broker::address::family::ipv6,
|
||||
broker::address::byte_order::network);
|
||||
return {broker::subnet(std::move(a), s.Length())};
|
||||
}
|
||||
{
|
||||
auto s = v->AsSubNet();
|
||||
in6_addr tmp;
|
||||
s.Prefix().CopyIPv6(&tmp);
|
||||
auto a = broker::address(reinterpret_cast<const uint32_t*>(&tmp),
|
||||
broker::address::family::ipv6,
|
||||
broker::address::byte_order::network);
|
||||
return {broker::subnet(std::move(a), s.Length())};
|
||||
}
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
return {v->AsDouble()};
|
||||
case TYPE_TIME:
|
||||
{
|
||||
auto secs = broker::fractional_seconds{v->AsTime()};
|
||||
auto since_epoch = std::chrono::duration_cast<broker::timespan>(secs);
|
||||
return {broker::timestamp{since_epoch}};
|
||||
}
|
||||
{
|
||||
auto secs = broker::fractional_seconds{v->AsTime()};
|
||||
auto since_epoch = std::chrono::duration_cast<broker::timespan>(secs);
|
||||
return {broker::timestamp{since_epoch}};
|
||||
}
|
||||
case TYPE_INTERVAL:
|
||||
{
|
||||
auto secs = broker::fractional_seconds{v->AsInterval()};
|
||||
return {std::chrono::duration_cast<broker::timespan>(secs)};
|
||||
}
|
||||
{
|
||||
auto secs = broker::fractional_seconds{v->AsInterval()};
|
||||
return {std::chrono::duration_cast<broker::timespan>(secs)};
|
||||
}
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
auto enum_type = v->GetType()->AsEnumType();
|
||||
auto enum_name = enum_type->Lookup(v->AsEnum());
|
||||
return {broker::enum_value(enum_name ? enum_name : "<unknown enum>")};
|
||||
}
|
||||
{
|
||||
auto enum_type = v->GetType()->AsEnumType();
|
||||
auto enum_name = enum_type->Lookup(v->AsEnum());
|
||||
return {broker::enum_value(enum_name ? enum_name : "<unknown enum>")};
|
||||
}
|
||||
case TYPE_STRING:
|
||||
{
|
||||
auto s = v->AsString();
|
||||
return {string(reinterpret_cast<const char*>(s->Bytes()), s->Len())};
|
||||
}
|
||||
{
|
||||
auto s = v->AsString();
|
||||
return {string(reinterpret_cast<const char*>(s->Bytes()), s->Len())};
|
||||
}
|
||||
case TYPE_FILE:
|
||||
return {string(v->AsFile()->Name())};
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
const Func* f = v->AsFunc();
|
||||
std::string name(f->Name());
|
||||
|
||||
broker::vector rval;
|
||||
rval.push_back(name);
|
||||
|
||||
if ( name.find("lambda_<") == 0 )
|
||||
{
|
||||
const Func* f = v->AsFunc();
|
||||
std::string name(f->Name());
|
||||
|
||||
broker::vector rval;
|
||||
rval.push_back(name);
|
||||
|
||||
if ( name.find("lambda_<") == 0 )
|
||||
// Only ScriptFuncs have closures.
|
||||
if ( auto b = dynamic_cast<const zeek::detail::ScriptFunc*>(f) )
|
||||
{
|
||||
// Only ScriptFuncs have closures.
|
||||
if ( auto b = dynamic_cast<const zeek::detail::ScriptFunc*>(f) )
|
||||
{
|
||||
auto bc = b->SerializeClosure();
|
||||
if ( ! bc )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
rval.emplace_back(std::move(*bc));
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->InternalWarning("Closure with non-ScriptFunc");
|
||||
auto bc = b->SerializeClosure();
|
||||
if ( ! bc )
|
||||
return broker::ec::invalid_data;
|
||||
}
|
||||
|
||||
rval.emplace_back(std::move(*bc));
|
||||
}
|
||||
else
|
||||
{
|
||||
reporter->InternalWarning("Closure with non-ScriptFunc");
|
||||
return broker::ec::invalid_data;
|
||||
}
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto is_set = v->GetType()->IsSet();
|
||||
auto table = v->AsTable();
|
||||
auto table_val = v->AsTableVal();
|
||||
broker::data rval;
|
||||
|
||||
if ( is_set )
|
||||
rval = broker::set();
|
||||
else
|
||||
rval = broker::table();
|
||||
|
||||
for ( const auto& te : *table )
|
||||
{
|
||||
auto hk = te.GetHashKey();
|
||||
auto* entry = te.GetValue<TableEntryVal*>();
|
||||
|
||||
auto vl = table_val->RecreateIndex(*hk);
|
||||
|
||||
broker::vector composite_key;
|
||||
composite_key.reserve(vl->Length());
|
||||
|
||||
for ( auto k = 0; k < vl->Length(); ++k )
|
||||
{
|
||||
auto key_part = val_to_data(vl->Idx(k).get());
|
||||
|
||||
if ( ! key_part )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
composite_key.emplace_back(move(*key_part));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto is_set = v->GetType()->IsSet();
|
||||
auto table = v->AsTable();
|
||||
auto table_val = v->AsTableVal();
|
||||
broker::data rval;
|
||||
broker::data key;
|
||||
|
||||
if ( composite_key.size() == 1 )
|
||||
key = move(composite_key[0]);
|
||||
else
|
||||
key = move(composite_key);
|
||||
|
||||
if ( is_set )
|
||||
rval = broker::set();
|
||||
caf::get<broker::set>(rval).emplace(move(key));
|
||||
else
|
||||
rval = broker::table();
|
||||
|
||||
for ( const auto& te : *table )
|
||||
{
|
||||
auto hk = te.GetHashKey();
|
||||
auto* entry = te.GetValue<TableEntryVal*>();
|
||||
auto val = val_to_data(entry->GetVal().get());
|
||||
|
||||
auto vl = table_val->RecreateIndex(*hk);
|
||||
if ( ! val )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
broker::vector composite_key;
|
||||
composite_key.reserve(vl->Length());
|
||||
|
||||
for ( auto k = 0; k < vl->Length(); ++k )
|
||||
{
|
||||
auto key_part = val_to_data(vl->Idx(k).get());
|
||||
|
||||
if ( ! key_part )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
composite_key.emplace_back(move(*key_part));
|
||||
}
|
||||
|
||||
broker::data key;
|
||||
|
||||
if ( composite_key.size() == 1 )
|
||||
key = move(composite_key[0]);
|
||||
else
|
||||
key = move(composite_key);
|
||||
|
||||
if ( is_set )
|
||||
caf::get<broker::set>(rval).emplace(move(key));
|
||||
else
|
||||
{
|
||||
auto val = val_to_data(entry->GetVal().get());
|
||||
|
||||
if ( ! val )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
caf::get<broker::table>(rval).emplace(move(key), move(*val));
|
||||
}
|
||||
caf::get<broker::table>(rval).emplace(move(key), move(*val));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
auto vec = v->AsVectorVal();
|
||||
broker::vector rval;
|
||||
rval.reserve(vec->Size());
|
||||
|
||||
for ( auto i = 0u; i < vec->Size(); ++i )
|
||||
{
|
||||
auto vec = v->AsVectorVal();
|
||||
broker::vector rval;
|
||||
rval.reserve(vec->Size());
|
||||
auto item_val = vec->ValAt(i);
|
||||
|
||||
for ( auto i = 0u; i < vec->Size(); ++i )
|
||||
{
|
||||
auto item_val = vec->ValAt(i);
|
||||
if ( ! item_val )
|
||||
continue;
|
||||
|
||||
if ( ! item_val )
|
||||
continue;
|
||||
auto item = val_to_data(item_val.get());
|
||||
|
||||
auto item = val_to_data(item_val.get());
|
||||
if ( ! item )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
if ( ! item )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
rval.emplace_back(move(*item));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
rval.emplace_back(move(*item));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_LIST:
|
||||
{
|
||||
// We don't really support lists on the broker side.
|
||||
// So we just pretend that it is a vector instead.
|
||||
auto list = v->AsListVal();
|
||||
broker::vector rval;
|
||||
rval.reserve(list->Length());
|
||||
|
||||
for ( auto i = 0; i < list->Length(); ++i )
|
||||
{
|
||||
// We don't really support lists on the broker side.
|
||||
// So we just pretend that it is a vector instead.
|
||||
auto list = v->AsListVal();
|
||||
broker::vector rval;
|
||||
rval.reserve(list->Length());
|
||||
const auto& item_val = list->Idx(i);
|
||||
|
||||
for ( auto i = 0; i < list->Length(); ++i )
|
||||
{
|
||||
const auto& item_val = list->Idx(i);
|
||||
if ( ! item_val )
|
||||
continue;
|
||||
|
||||
if ( ! item_val )
|
||||
continue;
|
||||
auto item = val_to_data(item_val.get());
|
||||
|
||||
auto item = val_to_data(item_val.get());
|
||||
if ( ! item )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
if ( ! item )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
rval.emplace_back(move(*item));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
rval.emplace_back(move(*item));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
auto rec = v->AsRecordVal();
|
||||
broker::vector rval;
|
||||
size_t num_fields = v->GetType()->AsRecordType()->NumFields();
|
||||
rval.reserve(num_fields);
|
||||
|
||||
for ( size_t i = 0; i < num_fields; ++i )
|
||||
{
|
||||
auto rec = v->AsRecordVal();
|
||||
broker::vector rval;
|
||||
size_t num_fields = v->GetType()->AsRecordType()->NumFields();
|
||||
rval.reserve(num_fields);
|
||||
auto item_val = rec->GetFieldOrDefault(i);
|
||||
|
||||
for ( size_t i = 0; i < num_fields; ++i )
|
||||
if ( ! item_val )
|
||||
{
|
||||
auto item_val = rec->GetFieldOrDefault(i);
|
||||
|
||||
if ( ! item_val )
|
||||
{
|
||||
rval.emplace_back(broker::nil);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto item = val_to_data(item_val.get());
|
||||
|
||||
if ( ! item )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
rval.emplace_back(move(*item));
|
||||
rval.emplace_back(broker::nil);
|
||||
continue;
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
auto item = val_to_data(item_val.get());
|
||||
|
||||
if ( ! item )
|
||||
return broker::ec::invalid_data;
|
||||
|
||||
rval.emplace_back(move(*item));
|
||||
}
|
||||
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
const RE_Matcher* p = v->AsPattern();
|
||||
broker::vector rval = {p->PatternText(), p->AnywherePatternText()};
|
||||
return {std::move(rval)};
|
||||
}
|
||||
{
|
||||
const RE_Matcher* p = v->AsPattern();
|
||||
broker::vector rval = {p->PatternText(), p->AnywherePatternText()};
|
||||
return {std::move(rval)};
|
||||
}
|
||||
case TYPE_OPAQUE:
|
||||
{
|
||||
auto c = v->AsOpaqueVal()->Serialize();
|
||||
if ( ! c )
|
||||
{
|
||||
auto c = v->AsOpaqueVal()->Serialize();
|
||||
if ( ! c )
|
||||
{
|
||||
reporter->Error("unsupported opaque type for serialization");
|
||||
break;
|
||||
}
|
||||
|
||||
return {c};
|
||||
reporter->Error("unsupported opaque type for serialization");
|
||||
break;
|
||||
}
|
||||
|
||||
return {c};
|
||||
}
|
||||
default:
|
||||
reporter->Error("unsupported Broker::Data type: %s", type_name(v->GetType()->Tag()));
|
||||
break;
|
||||
|
|
|
@ -1024,22 +1024,22 @@ void Manager::DispatchMessage(const broker::topic& topic, broker::data msg)
|
|||
break;
|
||||
|
||||
case broker::zeek::Message::Type::Batch:
|
||||
{
|
||||
broker::zeek::Batch batch(std::move(msg));
|
||||
|
||||
if ( ! batch.valid() )
|
||||
{
|
||||
broker::zeek::Batch batch(std::move(msg));
|
||||
|
||||
if ( ! batch.valid() )
|
||||
{
|
||||
reporter->Warning("received invalid broker Batch: %s",
|
||||
broker::to_string(batch).data());
|
||||
return;
|
||||
}
|
||||
|
||||
for ( auto& i : batch.batch() )
|
||||
DispatchMessage(topic, std::move(i));
|
||||
|
||||
break;
|
||||
reporter->Warning("received invalid broker Batch: %s",
|
||||
broker::to_string(batch).data());
|
||||
return;
|
||||
}
|
||||
|
||||
for ( auto& i : batch.batch() )
|
||||
DispatchMessage(topic, std::move(i));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// We ignore unknown types so that we could add more in the
|
||||
// future if we had too.
|
||||
|
|
|
@ -69,11 +69,10 @@ broker::backend_options to_backend_options(broker::backend backend, RecordVal* o
|
|||
switch ( backend )
|
||||
{
|
||||
case broker::backend::sqlite:
|
||||
{
|
||||
auto path =
|
||||
options->GetFieldAs<RecordVal>(0)->GetFieldAs<StringVal>(0)->CheckString();
|
||||
return {{"path", path}};
|
||||
}
|
||||
{
|
||||
auto path = options->GetFieldAs<RecordVal>(0)->GetFieldAs<StringVal>(0)->CheckString();
|
||||
return {{"path", path}};
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -493,32 +493,32 @@ unsigned int X509::KeyLength(EVP_PKEY* key)
|
|||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
case EVP_PKEY_EC:
|
||||
{
|
||||
BIGNUM* ec_order = BN_new();
|
||||
if ( ! ec_order )
|
||||
// could not malloc bignum?
|
||||
return 0;
|
||||
|
||||
const EC_GROUP* group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key));
|
||||
|
||||
if ( ! group )
|
||||
{
|
||||
BIGNUM* ec_order = BN_new();
|
||||
if ( ! ec_order )
|
||||
// could not malloc bignum?
|
||||
return 0;
|
||||
|
||||
const EC_GROUP* group = EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key));
|
||||
|
||||
if ( ! group )
|
||||
{
|
||||
// unknown ex-group
|
||||
BN_free(ec_order);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ! EC_GROUP_get_order(group, ec_order, NULL) )
|
||||
{
|
||||
// could not get ec-group-order
|
||||
BN_free(ec_order);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int length = BN_num_bits(ec_order);
|
||||
// unknown ex-group
|
||||
BN_free(ec_order);
|
||||
return length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ! EC_GROUP_get_order(group, ec_order, NULL) )
|
||||
{
|
||||
// could not get ec-group-order
|
||||
BN_free(ec_order);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int length = BN_num_bits(ec_order);
|
||||
BN_free(ec_order);
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return 0; // unknown public key type
|
||||
|
|
|
@ -841,28 +841,28 @@ bool Manager::IsCompatibleType(Type* t, bool atomic_only)
|
|||
return ! atomic_only;
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
|
||||
if ( ! t->IsSet() )
|
||||
return false;
|
||||
if ( ! t->IsSet() )
|
||||
return false;
|
||||
|
||||
const auto& indices = t->AsSetType()->GetIndices();
|
||||
const auto& indices = t->AsSetType()->GetIndices();
|
||||
|
||||
if ( indices->GetTypes().size() != 1 )
|
||||
return false;
|
||||
if ( indices->GetTypes().size() != 1 )
|
||||
return false;
|
||||
|
||||
return IsCompatibleType(indices->GetPureType().get(), true);
|
||||
}
|
||||
return IsCompatibleType(indices->GetPureType().get(), true);
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
|
||||
return IsCompatibleType(t->AsVectorType()->Yield().get(), true);
|
||||
}
|
||||
return IsCompatibleType(t->AsVectorType()->Yield().get(), true);
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -1999,65 +1999,65 @@ int Manager::GetValueLength(const Value* val) const
|
|||
|
||||
case TYPE_STRING:
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
length += val->val.string_val.length + 1;
|
||||
break;
|
||||
}
|
||||
{
|
||||
length += val->val.string_val.length + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
case IPv4:
|
||||
length += sizeof(val->val.addr_val.in.in4);
|
||||
break;
|
||||
case IPv6:
|
||||
length += sizeof(val->val.addr_val.in.in6);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
case IPv4:
|
||||
length += sizeof(val->val.addr_val.in.in4);
|
||||
break;
|
||||
case IPv6:
|
||||
length += sizeof(val->val.addr_val.in.in6);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
case IPv4:
|
||||
length += sizeof(val->val.subnet_val.prefix.in.in4) +
|
||||
sizeof(val->val.subnet_val.length);
|
||||
break;
|
||||
case IPv6:
|
||||
length += sizeof(val->val.subnet_val.prefix.in.in6) +
|
||||
sizeof(val->val.subnet_val.length);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
case IPv4:
|
||||
length += sizeof(val->val.subnet_val.prefix.in.in4) +
|
||||
sizeof(val->val.subnet_val.length);
|
||||
break;
|
||||
case IPv6:
|
||||
length += sizeof(val->val.subnet_val.prefix.in.in6) +
|
||||
sizeof(val->val.subnet_val.length);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
length += strlen(val->val.pattern_text_val) + 1;
|
||||
break;
|
||||
}
|
||||
{
|
||||
length += strlen(val->val.pattern_text_val) + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
for ( int i = 0; i < val->val.set_val.size; i++ )
|
||||
length += GetValueLength(val->val.set_val.vals[i]);
|
||||
break;
|
||||
}
|
||||
{
|
||||
for ( int i = 0; i < val->val.set_val.size; i++ )
|
||||
length += GetValueLength(val->val.set_val.vals[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
int j = val->val.vector_val.size;
|
||||
for ( int i = 0; i < j; i++ )
|
||||
length += GetValueLength(val->val.vector_val.vals[i]);
|
||||
break;
|
||||
}
|
||||
{
|
||||
int j = val->val.vector_val.size;
|
||||
for ( int i = 0; i < j; i++ )
|
||||
length += GetValueLength(val->val.vector_val.vals[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("unsupported type %d for GetValueLength", val->type);
|
||||
|
@ -2084,16 +2084,16 @@ int Manager::CopyValue(char* data, const int startpos, const Value* val) const
|
|||
return sizeof(val->val.uint_val);
|
||||
|
||||
case TYPE_PORT:
|
||||
{
|
||||
int length = 0;
|
||||
memcpy(data + startpos, (const void*)&(val->val.port_val.port),
|
||||
sizeof(val->val.port_val.port));
|
||||
length += sizeof(val->val.port_val.port);
|
||||
memcpy(data + startpos + length, (const void*)&(val->val.port_val.proto),
|
||||
sizeof(val->val.port_val.proto));
|
||||
length += sizeof(val->val.port_val.proto);
|
||||
return length;
|
||||
}
|
||||
{
|
||||
int length = 0;
|
||||
memcpy(data + startpos, (const void*)&(val->val.port_val.port),
|
||||
sizeof(val->val.port_val.port));
|
||||
length += sizeof(val->val.port_val.port);
|
||||
memcpy(data + startpos + length, (const void*)&(val->val.port_val.proto),
|
||||
sizeof(val->val.port_val.proto));
|
||||
length += sizeof(val->val.port_val.proto);
|
||||
return length;
|
||||
}
|
||||
|
||||
case TYPE_DOUBLE:
|
||||
case TYPE_TIME:
|
||||
|
@ -2104,92 +2104,92 @@ int Manager::CopyValue(char* data, const int startpos, const Value* val) const
|
|||
|
||||
case TYPE_STRING:
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
memcpy(data + startpos, val->val.string_val.data, val->val.string_val.length);
|
||||
// Add a \0 to the end. To be able to hash zero-length
|
||||
// strings and differentiate from !present.
|
||||
memset(data + startpos + val->val.string_val.length, 0, 1);
|
||||
return val->val.string_val.length + 1;
|
||||
}
|
||||
{
|
||||
memcpy(data + startpos, val->val.string_val.data, val->val.string_val.length);
|
||||
// Add a \0 to the end. To be able to hash zero-length
|
||||
// strings and differentiate from !present.
|
||||
memset(data + startpos + val->val.string_val.length, 0, 1);
|
||||
return val->val.string_val.length + 1;
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
int length = 0;
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
int length = 0;
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
case IPv4:
|
||||
length = sizeof(val->val.addr_val.in.in4);
|
||||
memcpy(data + startpos, (const char*)&(val->val.addr_val.in.in4), length);
|
||||
break;
|
||||
case IPv4:
|
||||
length = sizeof(val->val.addr_val.in.in4);
|
||||
memcpy(data + startpos, (const char*)&(val->val.addr_val.in.in4), length);
|
||||
break;
|
||||
|
||||
case IPv6:
|
||||
length = sizeof(val->val.addr_val.in.in6);
|
||||
memcpy(data + startpos, (const char*)&(val->val.addr_val.in.in6), length);
|
||||
break;
|
||||
case IPv6:
|
||||
length = sizeof(val->val.addr_val.in.in6);
|
||||
memcpy(data + startpos, (const char*)&(val->val.addr_val.in.in6), length);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return length;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
int length = 0;
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
int length = 0;
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
case IPv4:
|
||||
length = sizeof(val->val.addr_val.in.in4);
|
||||
memcpy(data + startpos, (const char*)&(val->val.subnet_val.prefix.in.in4),
|
||||
length);
|
||||
break;
|
||||
case IPv4:
|
||||
length = sizeof(val->val.addr_val.in.in4);
|
||||
memcpy(data + startpos, (const char*)&(val->val.subnet_val.prefix.in.in4),
|
||||
length);
|
||||
break;
|
||||
|
||||
case IPv6:
|
||||
length = sizeof(val->val.addr_val.in.in6);
|
||||
memcpy(data + startpos, (const char*)&(val->val.subnet_val.prefix.in.in6),
|
||||
length);
|
||||
break;
|
||||
case IPv6:
|
||||
length = sizeof(val->val.addr_val.in.in6);
|
||||
memcpy(data + startpos, (const char*)&(val->val.subnet_val.prefix.in.in6),
|
||||
length);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
int lengthlength = sizeof(val->val.subnet_val.length);
|
||||
memcpy(data + startpos + length, (const char*)&(val->val.subnet_val.length),
|
||||
lengthlength);
|
||||
length += lengthlength;
|
||||
|
||||
return length;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
int lengthlength = sizeof(val->val.subnet_val.length);
|
||||
memcpy(data + startpos + length, (const char*)&(val->val.subnet_val.length),
|
||||
lengthlength);
|
||||
length += lengthlength;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
// include null-terminator
|
||||
int length = strlen(val->val.pattern_text_val) + 1;
|
||||
memcpy(data + startpos, val->val.pattern_text_val, length);
|
||||
return length;
|
||||
}
|
||||
{
|
||||
// include null-terminator
|
||||
int length = strlen(val->val.pattern_text_val) + 1;
|
||||
memcpy(data + startpos, val->val.pattern_text_val, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
int length = 0;
|
||||
int j = val->val.set_val.size;
|
||||
for ( int i = 0; i < j; i++ )
|
||||
length += CopyValue(data, startpos + length, val->val.set_val.vals[i]);
|
||||
{
|
||||
int length = 0;
|
||||
int j = val->val.set_val.size;
|
||||
for ( int i = 0; i < j; i++ )
|
||||
length += CopyValue(data, startpos + length, val->val.set_val.vals[i]);
|
||||
|
||||
return length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
int length = 0;
|
||||
int j = val->val.vector_val.size;
|
||||
for ( int i = 0; i < j; i++ )
|
||||
length += CopyValue(data, startpos + length, val->val.vector_val.vals[i]);
|
||||
{
|
||||
int length = 0;
|
||||
int j = val->val.vector_val.size;
|
||||
for ( int i = 0; i < j; i++ )
|
||||
length += CopyValue(data, startpos + length, val->val.vector_val.vals[i]);
|
||||
|
||||
return length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("unsupported type %d for CopyValue", val->type);
|
||||
|
@ -2284,134 +2284,133 @@ Val* Manager::ValueToVal(const Stream* i, const Value* val, Type* request_type,
|
|||
return new IntervalVal(val->val.double_val);
|
||||
|
||||
case TYPE_STRING:
|
||||
{
|
||||
String* s = new String((const u_char*)val->val.string_val.data,
|
||||
val->val.string_val.length, true);
|
||||
return new StringVal(s);
|
||||
}
|
||||
{
|
||||
String* s = new String((const u_char*)val->val.string_val.data,
|
||||
val->val.string_val.length, true);
|
||||
return new StringVal(s);
|
||||
}
|
||||
|
||||
case TYPE_PORT:
|
||||
return val_mgr->Port(val->val.port_val.port, val->val.port_val.proto)->Ref();
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.addr_val.in.in4);
|
||||
break;
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.addr_val.in.in4);
|
||||
break;
|
||||
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.addr_val.in.in6);
|
||||
break;
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.addr_val.in.in6);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* addrval = new AddrVal(*addr);
|
||||
delete addr;
|
||||
return addrval;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* addrval = new AddrVal(*addr);
|
||||
delete addr;
|
||||
return addrval;
|
||||
}
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in4);
|
||||
break;
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in4);
|
||||
break;
|
||||
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in6);
|
||||
break;
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in6);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* subnetval = new SubNetVal(*addr, val->val.subnet_val.length);
|
||||
delete addr;
|
||||
return subnetval;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* subnetval = new SubNetVal(*addr, val->val.subnet_val.length);
|
||||
delete addr;
|
||||
return subnetval;
|
||||
}
|
||||
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
auto* re = new RE_Matcher(val->val.pattern_text_val);
|
||||
re->Compile();
|
||||
return new PatternVal(re);
|
||||
}
|
||||
{
|
||||
auto* re = new RE_Matcher(val->val.pattern_text_val);
|
||||
re->Compile();
|
||||
return new PatternVal(re);
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
// all entries have to have the same type...
|
||||
const auto& type = request_type->AsTableType()->GetIndices()->GetPureType();
|
||||
auto set_index = make_intrusive<TypeList>(type);
|
||||
set_index->Append(type);
|
||||
auto s = make_intrusive<SetType>(std::move(set_index), nullptr);
|
||||
auto t = make_intrusive<TableVal>(std::move(s));
|
||||
for ( int j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
// all entries have to have the same type...
|
||||
const auto& type = request_type->AsTableType()->GetIndices()->GetPureType();
|
||||
auto set_index = make_intrusive<TypeList>(type);
|
||||
set_index->Append(type);
|
||||
auto s = make_intrusive<SetType>(std::move(set_index), nullptr);
|
||||
auto t = make_intrusive<TableVal>(std::move(s));
|
||||
for ( int j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
Val* assignval =
|
||||
ValueToVal(i, val->val.set_val.vals[j], type.get(), have_error);
|
||||
Val* assignval = ValueToVal(i, val->val.set_val.vals[j], type.get(), have_error);
|
||||
|
||||
if ( have_error )
|
||||
return nullptr;
|
||||
if ( have_error )
|
||||
return nullptr;
|
||||
|
||||
t->Assign({AdoptRef{}, assignval}, nullptr);
|
||||
}
|
||||
|
||||
return t.release();
|
||||
t->Assign({AdoptRef{}, assignval}, nullptr);
|
||||
}
|
||||
|
||||
return t.release();
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
// all entries have to have the same type...
|
||||
const auto& type = request_type->AsVectorType()->Yield();
|
||||
auto vt = make_intrusive<VectorType>(type);
|
||||
auto v = make_intrusive<VectorVal>(std::move(vt));
|
||||
|
||||
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
// all entries have to have the same type...
|
||||
const auto& type = request_type->AsVectorType()->Yield();
|
||||
auto vt = make_intrusive<VectorType>(type);
|
||||
auto v = make_intrusive<VectorVal>(std::move(vt));
|
||||
auto el = ValueToVal(i, val->val.vector_val.vals[j], type.get(), have_error);
|
||||
|
||||
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
auto el = ValueToVal(i, val->val.vector_val.vals[j], type.get(), have_error);
|
||||
if ( have_error )
|
||||
return nullptr;
|
||||
|
||||
if ( have_error )
|
||||
return nullptr;
|
||||
|
||||
v->Assign(j, {AdoptRef{}, el});
|
||||
}
|
||||
|
||||
return v.release();
|
||||
v->Assign(j, {AdoptRef{}, el});
|
||||
}
|
||||
|
||||
return v.release();
|
||||
}
|
||||
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
// Convert to string first to not have to deal with missing
|
||||
// \0's...
|
||||
string enum_string(val->val.string_val.data, val->val.string_val.length);
|
||||
|
||||
string module = zeek::detail::extract_module_name(enum_string.c_str());
|
||||
string var = zeek::detail::extract_var_name(enum_string.c_str());
|
||||
|
||||
// Well, this is kind of stupid, because EnumType just
|
||||
// mangles the module name and the var name together again...
|
||||
// but well.
|
||||
bro_int_t index = request_type->AsEnumType()->Lookup(module, var.c_str());
|
||||
if ( index == -1 )
|
||||
{
|
||||
// Convert to string first to not have to deal with missing
|
||||
// \0's...
|
||||
string enum_string(val->val.string_val.data, val->val.string_val.length);
|
||||
Warning(i, "Value '%s' for stream '%s' is not a valid enum.", enum_string.c_str(),
|
||||
i->name.c_str());
|
||||
|
||||
string module = zeek::detail::extract_module_name(enum_string.c_str());
|
||||
string var = zeek::detail::extract_var_name(enum_string.c_str());
|
||||
|
||||
// Well, this is kind of stupid, because EnumType just
|
||||
// mangles the module name and the var name together again...
|
||||
// but well.
|
||||
bro_int_t index = request_type->AsEnumType()->Lookup(module, var.c_str());
|
||||
if ( index == -1 )
|
||||
{
|
||||
Warning(i, "Value '%s' for stream '%s' is not a valid enum.",
|
||||
enum_string.c_str(), i->name.c_str());
|
||||
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto rval = request_type->AsEnumType()->GetEnumVal(index);
|
||||
return rval.release();
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto rval = request_type->AsEnumType()->GetEnumVal(index);
|
||||
return rval.release();
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("Unsupported type for input_read in stream %s",
|
||||
i->name.c_str());
|
||||
|
|
|
@ -281,59 +281,59 @@ bool Ascii::DoUpdate()
|
|||
switch ( Info().mode )
|
||||
{
|
||||
case MODE_REREAD:
|
||||
{
|
||||
// check if the file has changed
|
||||
struct stat sb;
|
||||
if ( stat(fname.c_str(), &sb) == -1 )
|
||||
{
|
||||
// check if the file has changed
|
||||
struct stat sb;
|
||||
if ( stat(fname.c_str(), &sb) == -1 )
|
||||
{
|
||||
FailWarn(fail_on_file_problem, Fmt("Could not get stat for %s", fname.c_str()),
|
||||
true);
|
||||
FailWarn(fail_on_file_problem, Fmt("Could not get stat for %s", fname.c_str()),
|
||||
true);
|
||||
|
||||
file.close();
|
||||
return ! fail_on_file_problem;
|
||||
}
|
||||
|
||||
if ( sb.st_ino == ino && sb.st_mtime == mtime )
|
||||
// no change
|
||||
return true;
|
||||
|
||||
// Warn again in case of trouble if the file changes. The comparison to 0
|
||||
// is to suppress an extra warning that we'd otherwise get on the initial
|
||||
// inode assignment.
|
||||
if ( ino != 0 )
|
||||
StopWarningSuppression();
|
||||
|
||||
mtime = sb.st_mtime;
|
||||
ino = sb.st_ino;
|
||||
// File changed. Fall through to re-read.
|
||||
file.close();
|
||||
return ! fail_on_file_problem;
|
||||
}
|
||||
|
||||
if ( sb.st_ino == ino && sb.st_mtime == mtime )
|
||||
// no change
|
||||
return true;
|
||||
|
||||
// Warn again in case of trouble if the file changes. The comparison to 0
|
||||
// is to suppress an extra warning that we'd otherwise get on the initial
|
||||
// inode assignment.
|
||||
if ( ino != 0 )
|
||||
StopWarningSuppression();
|
||||
|
||||
mtime = sb.st_mtime;
|
||||
ino = sb.st_ino;
|
||||
// File changed. Fall through to re-read.
|
||||
}
|
||||
|
||||
case MODE_MANUAL:
|
||||
case MODE_STREAM:
|
||||
{
|
||||
// dirty, fix me. (well, apparently after trying seeking, etc
|
||||
// - this is not that bad)
|
||||
if ( file.is_open() )
|
||||
{
|
||||
// dirty, fix me. (well, apparently after trying seeking, etc
|
||||
// - this is not that bad)
|
||||
if ( file.is_open() )
|
||||
if ( Info().mode == MODE_STREAM )
|
||||
{
|
||||
if ( Info().mode == MODE_STREAM )
|
||||
file.clear(); // remove end of file evil bits
|
||||
if ( ! ReadHeader(true) )
|
||||
{
|
||||
file.clear(); // remove end of file evil bits
|
||||
if ( ! ReadHeader(true) )
|
||||
{
|
||||
return ! fail_on_file_problem; // header reading failed
|
||||
}
|
||||
|
||||
break;
|
||||
return ! fail_on_file_problem; // header reading failed
|
||||
}
|
||||
|
||||
file.close();
|
||||
break;
|
||||
}
|
||||
|
||||
OpenFile();
|
||||
|
||||
break;
|
||||
file.close();
|
||||
}
|
||||
|
||||
OpenFile();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
|
|
@ -134,12 +134,12 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype)
|
|||
assert(false); // no enums, please.
|
||||
|
||||
case TYPE_STRING:
|
||||
{
|
||||
std::string rnd = RandomString(10);
|
||||
val->val.string_val.data = util::copy_string(rnd.c_str());
|
||||
val->val.string_val.length = rnd.size();
|
||||
break;
|
||||
}
|
||||
{
|
||||
std::string rnd = RandomString(10);
|
||||
val->val.string_val.data = util::copy_string(rnd.c_str());
|
||||
val->val.string_val.length = rnd.size();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_BOOL:
|
||||
val->val.int_val = 1; // we never lie.
|
||||
|
@ -168,10 +168,10 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype)
|
|||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
val->val.subnet_val.prefix = ascii->ParseAddr("192.168.17.1");
|
||||
val->val.subnet_val.length = 16;
|
||||
}
|
||||
{
|
||||
val->val.subnet_val.prefix = ascii->ParseAddr("192.168.17.1");
|
||||
val->val.subnet_val.length = 16;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_ADDR:
|
||||
|
|
|
@ -199,20 +199,20 @@ bool Binary::DoUpdate()
|
|||
switch ( Info().mode )
|
||||
{
|
||||
case MODE_REREAD:
|
||||
{
|
||||
switch ( UpdateModificationTime() )
|
||||
{
|
||||
switch ( UpdateModificationTime() )
|
||||
{
|
||||
case -1:
|
||||
return false; // error
|
||||
case 0:
|
||||
return true; // no change
|
||||
case 1:
|
||||
break; // file changed. reread.
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
// fallthrough
|
||||
case -1:
|
||||
return false; // error
|
||||
case 0:
|
||||
return true; // no change
|
||||
case 1:
|
||||
break; // file changed. reread.
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
// fallthrough
|
||||
}
|
||||
|
||||
case MODE_MANUAL:
|
||||
case MODE_STREAM:
|
||||
|
|
|
@ -118,54 +118,54 @@ bool Config::DoUpdate()
|
|||
switch ( Info().mode )
|
||||
{
|
||||
case MODE_REREAD:
|
||||
{
|
||||
// check if the file has changed
|
||||
struct stat sb;
|
||||
if ( stat(Info().source, &sb) == -1 )
|
||||
{
|
||||
// check if the file has changed
|
||||
struct stat sb;
|
||||
if ( stat(Info().source, &sb) == -1 )
|
||||
{
|
||||
FailWarn(fail_on_file_problem, Fmt("Could not get stat for %s", Info().source),
|
||||
true);
|
||||
FailWarn(fail_on_file_problem, Fmt("Could not get stat for %s", Info().source),
|
||||
true);
|
||||
|
||||
file.close();
|
||||
return ! fail_on_file_problem;
|
||||
}
|
||||
|
||||
if ( sb.st_ino == ino && sb.st_mtime == mtime )
|
||||
// no change
|
||||
return true;
|
||||
|
||||
// Warn again in case of trouble if the file changes. The comparison to 0
|
||||
// is to suppress an extra warning that we'd otherwise get on the initial
|
||||
// inode assignment.
|
||||
if ( ino != 0 )
|
||||
StopWarningSuppression();
|
||||
|
||||
mtime = sb.st_mtime;
|
||||
ino = sb.st_ino;
|
||||
// File changed. Fall through to re-read.
|
||||
file.close();
|
||||
return ! fail_on_file_problem;
|
||||
}
|
||||
|
||||
if ( sb.st_ino == ino && sb.st_mtime == mtime )
|
||||
// no change
|
||||
return true;
|
||||
|
||||
// Warn again in case of trouble if the file changes. The comparison to 0
|
||||
// is to suppress an extra warning that we'd otherwise get on the initial
|
||||
// inode assignment.
|
||||
if ( ino != 0 )
|
||||
StopWarningSuppression();
|
||||
|
||||
mtime = sb.st_mtime;
|
||||
ino = sb.st_ino;
|
||||
// File changed. Fall through to re-read.
|
||||
}
|
||||
|
||||
case MODE_MANUAL:
|
||||
case MODE_STREAM:
|
||||
{
|
||||
// dirty, fix me. (well, apparently after trying seeking, etc
|
||||
// - this is not that bad)
|
||||
if ( file.is_open() )
|
||||
{
|
||||
// dirty, fix me. (well, apparently after trying seeking, etc
|
||||
// - this is not that bad)
|
||||
if ( file.is_open() )
|
||||
if ( Info().mode == MODE_STREAM )
|
||||
{
|
||||
if ( Info().mode == MODE_STREAM )
|
||||
{
|
||||
file.clear(); // remove end of file evil bits
|
||||
break;
|
||||
}
|
||||
|
||||
file.close();
|
||||
file.clear(); // remove end of file evil bits
|
||||
break;
|
||||
}
|
||||
|
||||
OpenFile();
|
||||
|
||||
break;
|
||||
file.close();
|
||||
}
|
||||
|
||||
OpenFile();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
|
|
@ -558,27 +558,27 @@ bool Raw::DoUpdate()
|
|||
switch ( Info().mode )
|
||||
{
|
||||
case MODE_REREAD:
|
||||
{
|
||||
assert(childpid == -1); // mode may not be used to execute child programs
|
||||
// check if the file has changed
|
||||
struct stat sb;
|
||||
if ( stat(fname.c_str(), &sb) == -1 )
|
||||
{
|
||||
assert(childpid == -1); // mode may not be used to execute child programs
|
||||
// check if the file has changed
|
||||
struct stat sb;
|
||||
if ( stat(fname.c_str(), &sb) == -1 )
|
||||
{
|
||||
Error(Fmt("Could not get stat for %s", fname.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( sb.st_ino == ino && sb.st_mtime == mtime )
|
||||
// no change
|
||||
return true;
|
||||
|
||||
mtime = sb.st_mtime;
|
||||
ino = sb.st_ino;
|
||||
// file changed. reread.
|
||||
//
|
||||
// fallthrough
|
||||
Error(Fmt("Could not get stat for %s", fname.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( sb.st_ino == ino && sb.st_mtime == mtime )
|
||||
// no change
|
||||
return true;
|
||||
|
||||
mtime = sb.st_mtime;
|
||||
ino = sb.st_ino;
|
||||
// file changed. reread.
|
||||
//
|
||||
// fallthrough
|
||||
}
|
||||
|
||||
case MODE_MANUAL:
|
||||
case MODE_STREAM:
|
||||
if ( Info().mode == MODE_STREAM && file )
|
||||
|
|
|
@ -136,40 +136,40 @@ Value* SQLite::EntryToVal(sqlite3_stmt* st, const threading::Field* field, int p
|
|||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRING:
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
int length = sqlite3_column_bytes(st, pos);
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
int length = sqlite3_column_bytes(st, pos);
|
||||
|
||||
char* out = new char[length];
|
||||
memcpy(out, text, length);
|
||||
char* out = new char[length];
|
||||
memcpy(out, text, length);
|
||||
|
||||
val->val.string_val.length = length;
|
||||
val->val.string_val.data = out;
|
||||
break;
|
||||
}
|
||||
val->val.string_val.length = length;
|
||||
val->val.string_val.data = out;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_BOOL:
|
||||
{
|
||||
if ( sqlite3_column_type(st, pos) != SQLITE_INTEGER )
|
||||
{
|
||||
if ( sqlite3_column_type(st, pos) != SQLITE_INTEGER )
|
||||
{
|
||||
Error("Invalid data type for boolean - expected Integer");
|
||||
delete val;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int res = sqlite3_column_int(st, pos);
|
||||
|
||||
if ( res == 0 || res == 1 )
|
||||
val->val.int_val = res;
|
||||
else
|
||||
{
|
||||
Error(Fmt("Invalid value for boolean: %d", res));
|
||||
delete val;
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
Error("Invalid data type for boolean - expected Integer");
|
||||
delete val;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int res = sqlite3_column_int(st, pos);
|
||||
|
||||
if ( res == 0 || res == 1 )
|
||||
val->val.int_val = res;
|
||||
else
|
||||
{
|
||||
Error(Fmt("Invalid value for boolean: %d", res));
|
||||
delete val;
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INT:
|
||||
val->val.int_val = sqlite3_column_int64(st, pos);
|
||||
break;
|
||||
|
@ -185,54 +185,54 @@ Value* SQLite::EntryToVal(sqlite3_stmt* st, const threading::Field* field, int p
|
|||
break;
|
||||
|
||||
case TYPE_PORT:
|
||||
{
|
||||
val->val.port_val.port = sqlite3_column_int(st, pos);
|
||||
val->val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
if ( subpos != -1 )
|
||||
{
|
||||
val->val.port_val.port = sqlite3_column_int(st, pos);
|
||||
val->val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
if ( subpos != -1 )
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, subpos);
|
||||
const char* text = (const char*)sqlite3_column_text(st, subpos);
|
||||
|
||||
if ( text == 0 )
|
||||
Error("Port protocol definition did not contain text");
|
||||
else
|
||||
{
|
||||
std::string s(text, sqlite3_column_bytes(st, subpos));
|
||||
val->val.port_val.proto = io->ParseProto(s);
|
||||
}
|
||||
if ( text == 0 )
|
||||
Error("Port protocol definition did not contain text");
|
||||
else
|
||||
{
|
||||
std::string s(text, sqlite3_column_bytes(st, subpos));
|
||||
val->val.port_val.proto = io->ParseProto(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
std::string s(text, sqlite3_column_bytes(st, pos));
|
||||
int pos = s.find('/');
|
||||
int width = atoi(s.substr(pos + 1).c_str());
|
||||
std::string addr = s.substr(0, pos);
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
std::string s(text, sqlite3_column_bytes(st, pos));
|
||||
int pos = s.find('/');
|
||||
int width = atoi(s.substr(pos + 1).c_str());
|
||||
std::string addr = s.substr(0, pos);
|
||||
|
||||
val->val.subnet_val.prefix = io->ParseAddr(addr);
|
||||
val->val.subnet_val.length = width;
|
||||
break;
|
||||
}
|
||||
val->val.subnet_val.prefix = io->ParseAddr(addr);
|
||||
val->val.subnet_val.length = width;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
std::string s(text, sqlite3_column_bytes(st, pos));
|
||||
val->val.addr_val = io->ParseAddr(s);
|
||||
break;
|
||||
}
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
std::string s(text, sqlite3_column_bytes(st, pos));
|
||||
val->val.addr_val = io->ParseAddr(s);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
std::string s(text, sqlite3_column_bytes(st, pos));
|
||||
delete val;
|
||||
val = io->ParseValue(s, "", field->type, field->subtype);
|
||||
break;
|
||||
}
|
||||
{
|
||||
const char* text = (const char*)sqlite3_column_text(st, pos);
|
||||
std::string s(text, sqlite3_column_bytes(st, pos));
|
||||
delete val;
|
||||
val = io->ParseValue(s, "", field->type, field->subtype);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Error(Fmt("unsupported field format %d", field->type));
|
||||
|
|
|
@ -952,24 +952,24 @@ threading::Value* Manager::ValToLogVal(Val* val, Type* ty)
|
|||
break;
|
||||
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
const char* s = val->GetType()->AsEnumType()->Lookup(val->InternalInt());
|
||||
|
||||
if ( s )
|
||||
{
|
||||
const char* s = val->GetType()->AsEnumType()->Lookup(val->InternalInt());
|
||||
|
||||
if ( s )
|
||||
{
|
||||
lval->val.string_val.data = util::copy_string(s);
|
||||
lval->val.string_val.length = strlen(s);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
val->GetType()->Error("enum type does not contain value", val);
|
||||
lval->val.string_val.data = util::copy_string("");
|
||||
lval->val.string_val.length = 0;
|
||||
}
|
||||
break;
|
||||
lval->val.string_val.data = util::copy_string(s);
|
||||
lval->val.string_val.length = strlen(s);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
val->GetType()->Error("enum type does not contain value", val);
|
||||
lval->val.string_val.data = util::copy_string("");
|
||||
lval->val.string_val.length = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_COUNT:
|
||||
lval->val.uint_val = val->InternalUnsigned();
|
||||
break;
|
||||
|
@ -994,68 +994,68 @@ threading::Value* Manager::ValToLogVal(Val* val, Type* ty)
|
|||
break;
|
||||
|
||||
case TYPE_STRING:
|
||||
{
|
||||
const String* s = val->AsString();
|
||||
char* buf = new char[s->Len()];
|
||||
memcpy(buf, s->Bytes(), s->Len());
|
||||
{
|
||||
const String* s = val->AsString();
|
||||
char* buf = new char[s->Len()];
|
||||
memcpy(buf, s->Bytes(), s->Len());
|
||||
|
||||
lval->val.string_val.data = buf;
|
||||
lval->val.string_val.length = s->Len();
|
||||
break;
|
||||
}
|
||||
lval->val.string_val.data = buf;
|
||||
lval->val.string_val.length = s->Len();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_FILE:
|
||||
{
|
||||
const File* f = val->AsFile();
|
||||
string s = f->Name();
|
||||
lval->val.string_val.data = util::copy_string(s.c_str());
|
||||
lval->val.string_val.length = s.size();
|
||||
break;
|
||||
}
|
||||
{
|
||||
const File* f = val->AsFile();
|
||||
string s = f->Name();
|
||||
lval->val.string_val.data = util::copy_string(s.c_str());
|
||||
lval->val.string_val.length = s.size();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
ODesc d;
|
||||
const Func* f = val->AsFunc();
|
||||
f->Describe(&d);
|
||||
const char* s = d.Description();
|
||||
lval->val.string_val.data = util::copy_string(s);
|
||||
lval->val.string_val.length = strlen(s);
|
||||
break;
|
||||
}
|
||||
{
|
||||
ODesc d;
|
||||
const Func* f = val->AsFunc();
|
||||
f->Describe(&d);
|
||||
const char* s = d.Description();
|
||||
lval->val.string_val.data = util::copy_string(s);
|
||||
lval->val.string_val.length = strlen(s);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto set = val->AsTableVal()->ToPureListVal();
|
||||
if ( ! set )
|
||||
// ToPureListVal has reported an internal warning
|
||||
// already. Just keep going by making something up.
|
||||
set = make_intrusive<ListVal>(TYPE_INT);
|
||||
{
|
||||
auto set = val->AsTableVal()->ToPureListVal();
|
||||
if ( ! set )
|
||||
// ToPureListVal has reported an internal warning
|
||||
// already. Just keep going by making something up.
|
||||
set = make_intrusive<ListVal>(TYPE_INT);
|
||||
|
||||
lval->val.set_val.size = set->Length();
|
||||
lval->val.set_val.vals = new threading::Value*[lval->val.set_val.size];
|
||||
lval->val.set_val.size = set->Length();
|
||||
lval->val.set_val.vals = new threading::Value*[lval->val.set_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < lval->val.set_val.size; i++ )
|
||||
lval->val.set_val.vals[i] = ValToLogVal(set->Idx(i).get());
|
||||
for ( bro_int_t i = 0; i < lval->val.set_val.size; i++ )
|
||||
lval->val.set_val.vals[i] = ValToLogVal(set->Idx(i).get());
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
VectorVal* vec = val->AsVectorVal();
|
||||
lval->val.vector_val.size = vec->Size();
|
||||
lval->val.vector_val.vals = new threading::Value*[lval->val.vector_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < lval->val.vector_val.size; i++ )
|
||||
{
|
||||
VectorVal* vec = val->AsVectorVal();
|
||||
lval->val.vector_val.size = vec->Size();
|
||||
lval->val.vector_val.vals = new threading::Value*[lval->val.vector_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < lval->val.vector_val.size; i++ )
|
||||
{
|
||||
lval->val.vector_val.vals[i] =
|
||||
ValToLogVal(vec->ValAt(i).get(), vec->GetType()->Yield().get());
|
||||
}
|
||||
|
||||
break;
|
||||
lval->val.vector_val.vals[i] =
|
||||
ValToLogVal(vec->ValAt(i).get(), vec->GetType()->Yield().get());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("unsupported type %s for log_write", type_name(lval->type));
|
||||
}
|
||||
|
|
|
@ -254,16 +254,16 @@ int SQLite::AddParams(Value* val, int pos)
|
|||
return sqlite3_bind_int(st, pos, val->val.port_val.port);
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
string out = io->Render(val->val.subnet_val);
|
||||
return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT);
|
||||
}
|
||||
{
|
||||
string out = io->Render(val->val.subnet_val);
|
||||
return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
string out = io->Render(val->val.addr_val);
|
||||
return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT);
|
||||
}
|
||||
{
|
||||
string out = io->Render(val->val.addr_val);
|
||||
return sqlite3_bind_text(st, pos, out.data(), out.size(), SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
case TYPE_TIME:
|
||||
case TYPE_INTERVAL:
|
||||
|
@ -274,59 +274,59 @@ int SQLite::AddParams(Value* val, int pos)
|
|||
case TYPE_STRING:
|
||||
case TYPE_FILE:
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
if ( ! val->val.string_val.length || val->val.string_val.length == 0 )
|
||||
return sqlite3_bind_null(st, pos);
|
||||
{
|
||||
if ( ! val->val.string_val.length || val->val.string_val.length == 0 )
|
||||
return sqlite3_bind_null(st, pos);
|
||||
|
||||
return sqlite3_bind_text(st, pos, val->val.string_val.data,
|
||||
val->val.string_val.length, SQLITE_TRANSIENT);
|
||||
}
|
||||
return sqlite3_bind_text(st, pos, val->val.string_val.data, val->val.string_val.length,
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
ODesc desc;
|
||||
desc.Clear();
|
||||
desc.EnableEscaping();
|
||||
desc.AddEscapeSequence(set_separator);
|
||||
{
|
||||
ODesc desc;
|
||||
desc.Clear();
|
||||
desc.EnableEscaping();
|
||||
desc.AddEscapeSequence(set_separator);
|
||||
|
||||
if ( ! val->val.set_val.size )
|
||||
desc.Add(empty_field);
|
||||
else
|
||||
for ( bro_int_t j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc.AddRaw(set_separator);
|
||||
if ( ! val->val.set_val.size )
|
||||
desc.Add(empty_field);
|
||||
else
|
||||
for ( bro_int_t j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc.AddRaw(set_separator);
|
||||
|
||||
io->Describe(&desc, val->val.set_val.vals[j], fields[pos - 1]->name);
|
||||
}
|
||||
io->Describe(&desc, val->val.set_val.vals[j], fields[pos - 1]->name);
|
||||
}
|
||||
|
||||
desc.RemoveEscapeSequence(set_separator);
|
||||
return sqlite3_bind_text(st, pos, (const char*)desc.Bytes(), desc.Len(),
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
desc.RemoveEscapeSequence(set_separator);
|
||||
return sqlite3_bind_text(st, pos, (const char*)desc.Bytes(), desc.Len(),
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
ODesc desc;
|
||||
desc.Clear();
|
||||
desc.EnableEscaping();
|
||||
desc.AddEscapeSequence(set_separator);
|
||||
{
|
||||
ODesc desc;
|
||||
desc.Clear();
|
||||
desc.EnableEscaping();
|
||||
desc.AddEscapeSequence(set_separator);
|
||||
|
||||
if ( ! val->val.vector_val.size )
|
||||
desc.Add(empty_field);
|
||||
else
|
||||
for ( bro_int_t j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc.AddRaw(set_separator);
|
||||
if ( ! val->val.vector_val.size )
|
||||
desc.Add(empty_field);
|
||||
else
|
||||
for ( bro_int_t j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc.AddRaw(set_separator);
|
||||
|
||||
io->Describe(&desc, val->val.vector_val.vals[j], fields[pos - 1]->name);
|
||||
}
|
||||
io->Describe(&desc, val->val.vector_val.vals[j], fields[pos - 1]->name);
|
||||
}
|
||||
|
||||
desc.RemoveEscapeSequence(set_separator);
|
||||
return sqlite3_bind_text(st, pos, (const char*)desc.Bytes(), desc.Len(),
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
desc.RemoveEscapeSequence(set_separator);
|
||||
return sqlite3_bind_text(st, pos, (const char*)desc.Bytes(), desc.Len(),
|
||||
SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
default:
|
||||
Error(Fmt("unsupported field format %d", val->type));
|
||||
|
|
|
@ -115,11 +115,11 @@ bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// don't know how to proceed
|
||||
BadARPEvent(ah, "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
// don't know how to proceed
|
||||
BadARPEvent(ah, "unknown-arp-hw-address (hrd=%i)", ntohs(ah->ar_hrd));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: We don't support IPv6 addresses.
|
||||
|
@ -136,11 +136,11 @@ bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// don't know how to proceed
|
||||
BadARPEvent(ah, "unknown-arp-proto-address (pro=%i)", ntohs(ah->ar_pro));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
// don't know how to proceed
|
||||
BadARPEvent(ah, "unknown-arp-proto-address (pro=%i)", ntohs(ah->ar_pro));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check MAC src address = ARP sender MAC address.
|
||||
|
@ -167,18 +167,18 @@ bool ARPAnalyzer::AnalyzePacket(size_t len, const uint8_t* data, Packet* packet)
|
|||
case ARPOP_REVREPLY:
|
||||
case ARPOP_INVREQUEST:
|
||||
case ARPOP_INVREPLY:
|
||||
{
|
||||
// don't know how to handle the opcode
|
||||
BadARPEvent(ah, "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
// don't know how to handle the opcode
|
||||
BadARPEvent(ah, "unimplemented-arp-opcode (%i)", ntohs(ah->ar_op));
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// invalid opcode
|
||||
BadARPEvent(ah, "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op));
|
||||
return false;
|
||||
}
|
||||
{
|
||||
// invalid opcode
|
||||
BadARPEvent(ah, "invalid-arp-opcode (opcode=%i)", ntohs(ah->ar_op));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Leave packet analyzer land
|
||||
|
|
|
@ -274,36 +274,36 @@ TransportProto ICMPAnalyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32_t*
|
|||
switch ( proto )
|
||||
{
|
||||
case TRANSPORT_ICMP:
|
||||
{
|
||||
const struct icmp* icmpp = (const struct icmp*)transport_hdr;
|
||||
bool is_one_way; // dummy
|
||||
*src_port = ntohs(icmpp->icmp_type);
|
||||
{
|
||||
const struct icmp* icmpp = (const struct icmp*)transport_hdr;
|
||||
bool is_one_way; // dummy
|
||||
*src_port = ntohs(icmpp->icmp_type);
|
||||
|
||||
if ( ip4 )
|
||||
*dst_port =
|
||||
ntohs(ICMP4_counterpart(icmpp->icmp_type, icmpp->icmp_code, is_one_way));
|
||||
else
|
||||
*dst_port =
|
||||
ntohs(ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, is_one_way));
|
||||
if ( ip4 )
|
||||
*dst_port =
|
||||
ntohs(ICMP4_counterpart(icmpp->icmp_type, icmpp->icmp_code, is_one_way));
|
||||
else
|
||||
*dst_port =
|
||||
ntohs(ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, is_one_way));
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_TCP:
|
||||
{
|
||||
const struct tcphdr* tp = (const struct tcphdr*)transport_hdr;
|
||||
*src_port = ntohs(tp->th_sport);
|
||||
*dst_port = ntohs(tp->th_dport);
|
||||
break;
|
||||
}
|
||||
{
|
||||
const struct tcphdr* tp = (const struct tcphdr*)transport_hdr;
|
||||
*src_port = ntohs(tp->th_sport);
|
||||
*dst_port = ntohs(tp->th_dport);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_UDP:
|
||||
{
|
||||
const struct udphdr* up = (const struct udphdr*)transport_hdr;
|
||||
*src_port = ntohs(up->uh_sport);
|
||||
*dst_port = ntohs(up->uh_dport);
|
||||
break;
|
||||
}
|
||||
{
|
||||
const struct udphdr* up = (const struct udphdr*)transport_hdr;
|
||||
*src_port = ntohs(up->uh_sport);
|
||||
*dst_port = ntohs(up->uh_dport);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
*src_port = *dst_port = ntohs(0);
|
||||
|
@ -749,10 +749,10 @@ zeek::VectorValPtr ICMPAnalyzer::BuildNDOptionsVal(int caplen, const u_char* dat
|
|||
}
|
||||
|
||||
default:
|
||||
{
|
||||
set_payload_field = true;
|
||||
break;
|
||||
}
|
||||
{
|
||||
set_payload_field = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( set_payload_field )
|
||||
|
|
|
@ -48,45 +48,45 @@ bool WrapperAnalyzer::Analyze(Packet* packet, const uint8_t*& data)
|
|||
// 802.1q / 802.1ad
|
||||
case 0x8100:
|
||||
case 0x9100:
|
||||
{
|
||||
if ( data + 4 >= end_of_data )
|
||||
{
|
||||
if ( data + 4 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header", packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& vlan_ref = saw_vlan ? packet->inner_vlan : packet->vlan;
|
||||
vlan_ref = ((data[0] << 8u) + data[1]) & 0xfff;
|
||||
protocol = ((data[2] << 8u) + data[3]);
|
||||
data += 4; // Skip the vlan header
|
||||
saw_vlan = true;
|
||||
packet->eth_type = protocol;
|
||||
Weird("truncated_link_header", packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& vlan_ref = saw_vlan ? packet->inner_vlan : packet->vlan;
|
||||
vlan_ref = ((data[0] << 8u) + data[1]) & 0xfff;
|
||||
protocol = ((data[2] << 8u) + data[3]);
|
||||
data += 4; // Skip the vlan header
|
||||
saw_vlan = true;
|
||||
packet->eth_type = protocol;
|
||||
}
|
||||
break;
|
||||
|
||||
// PPPoE carried over the ethernet frame.
|
||||
case 0x8864:
|
||||
{
|
||||
if ( data + 8 >= end_of_data )
|
||||
{
|
||||
if ( data + 8 >= end_of_data )
|
||||
{
|
||||
Weird("truncated_link_header", packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
protocol = (data[6] << 8u) + data[7];
|
||||
data += 8; // Skip the PPPoE session and PPP header
|
||||
|
||||
if ( protocol == 0x0021 )
|
||||
packet->l3_proto = L3_IPV4;
|
||||
else if ( protocol == 0x0057 )
|
||||
packet->l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("non_ip_packet_in_pppoe_encapsulation", packet);
|
||||
return false;
|
||||
}
|
||||
Weird("truncated_link_header", packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
protocol = (data[6] << 8u) + data[7];
|
||||
data += 8; // Skip the PPPoE session and PPP header
|
||||
|
||||
if ( protocol == 0x0021 )
|
||||
packet->l3_proto = L3_IPV4;
|
||||
else if ( protocol == 0x0057 )
|
||||
packet->l3_proto = L3_IPV6;
|
||||
else
|
||||
{
|
||||
// Neither IPv4 nor IPv6.
|
||||
Weird("non_ip_packet_in_pppoe_encapsulation", packet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,57 +168,57 @@ void HookArgument::Describe(ODesc* d) const
|
|||
break;
|
||||
|
||||
case WRITER_INFO:
|
||||
{
|
||||
d->Add(arg.winfo->path);
|
||||
d->Add("(");
|
||||
d->Add(arg.winfo->network_time);
|
||||
d->Add(",");
|
||||
d->Add(arg.winfo->rotation_interval);
|
||||
d->Add(",");
|
||||
d->Add(arg.winfo->rotation_base);
|
||||
|
||||
if ( arg.winfo->config.size() > 0 )
|
||||
{
|
||||
d->Add(arg.winfo->path);
|
||||
d->Add("(");
|
||||
d->Add(arg.winfo->network_time);
|
||||
d->Add(",");
|
||||
d->Add(arg.winfo->rotation_interval);
|
||||
d->Add(",");
|
||||
d->Add(arg.winfo->rotation_base);
|
||||
bool first = true;
|
||||
d->Add("config: {");
|
||||
|
||||
if ( arg.winfo->config.size() > 0 )
|
||||
for ( auto& v : arg.winfo->config )
|
||||
{
|
||||
bool first = true;
|
||||
d->Add("config: {");
|
||||
|
||||
for ( auto& v : arg.winfo->config )
|
||||
{
|
||||
if ( ! first )
|
||||
d->Add(", ");
|
||||
|
||||
d->Add(v.first);
|
||||
d->Add(": ");
|
||||
d->Add(v.second);
|
||||
first = false;
|
||||
}
|
||||
|
||||
d->Add("}");
|
||||
}
|
||||
|
||||
d->Add(")");
|
||||
}
|
||||
break;
|
||||
|
||||
case THREAD_FIELDS:
|
||||
{
|
||||
d->Add("{");
|
||||
|
||||
for ( int i = 0; i < tfields.first; i++ )
|
||||
{
|
||||
const threading::Field* f = tfields.second[i];
|
||||
|
||||
if ( i > 0 )
|
||||
if ( ! first )
|
||||
d->Add(", ");
|
||||
|
||||
d->Add(f->name);
|
||||
d->Add(" (");
|
||||
d->Add(f->TypeName());
|
||||
d->Add(")");
|
||||
d->Add(v.first);
|
||||
d->Add(": ");
|
||||
d->Add(v.second);
|
||||
first = false;
|
||||
}
|
||||
|
||||
d->Add("}");
|
||||
}
|
||||
|
||||
d->Add(")");
|
||||
}
|
||||
break;
|
||||
|
||||
case THREAD_FIELDS:
|
||||
{
|
||||
d->Add("{");
|
||||
|
||||
for ( int i = 0; i < tfields.first; i++ )
|
||||
{
|
||||
const threading::Field* f = tfields.second[i];
|
||||
|
||||
if ( i > 0 )
|
||||
d->Add(", ");
|
||||
|
||||
d->Add(f->name);
|
||||
d->Add(" (");
|
||||
d->Add(f->TypeName());
|
||||
d->Add(")");
|
||||
}
|
||||
|
||||
d->Add("}");
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCATION:
|
||||
|
|
|
@ -127,17 +127,17 @@ bool CPPCompile::AddConstant(const ValPtr& vp)
|
|||
|
||||
case TYPE_ADDR:
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
auto prefix = (tag == TYPE_ADDR) ? "Addr" : "SubNet";
|
||||
{
|
||||
auto prefix = (tag == TYPE_ADDR) ? "Addr" : "SubNet";
|
||||
|
||||
Emit("%sValPtr %s;", prefix, const_name);
|
||||
Emit("%sValPtr %s;", prefix, const_name);
|
||||
|
||||
ODesc d;
|
||||
v->Describe(&d);
|
||||
ODesc d;
|
||||
v->Describe(&d);
|
||||
|
||||
AddInit(v, const_name,
|
||||
string("make_intrusive<") + prefix + "Val>(\"" + d.Description() + "\")");
|
||||
}
|
||||
AddInit(v, const_name,
|
||||
string("make_intrusive<") + prefix + "Val>(\"" + d.Description() + "\")");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_FUNC:
|
||||
|
@ -151,15 +151,15 @@ bool CPPCompile::AddConstant(const ValPtr& vp)
|
|||
break;
|
||||
|
||||
case TYPE_FILE:
|
||||
{
|
||||
Emit("FileValPtr %s;", const_name);
|
||||
{
|
||||
Emit("FileValPtr %s;", const_name);
|
||||
|
||||
auto f = cast_intrusive<FileVal>(vp)->Get();
|
||||
auto f = cast_intrusive<FileVal>(vp)->Get();
|
||||
|
||||
AddInit(v, const_name,
|
||||
string("make_intrusive<FileVal>(") + "make_intrusive<File>(\"" + f->Name() +
|
||||
"\", \"w\"))");
|
||||
}
|
||||
AddInit(v, const_name,
|
||||
string("make_intrusive<FileVal>(") + "make_intrusive<File>(\"" + f->Name() +
|
||||
"\", \"w\"))");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -79,17 +79,17 @@ bool CPPCompile::IsSimpleInitExpr(const ExprPtr& e) const
|
|||
return true;
|
||||
|
||||
case EXPR_RECORD_COERCE:
|
||||
{ // look for coercion of empty record
|
||||
auto op = e->GetOp1();
|
||||
{ // look for coercion of empty record
|
||||
auto op = e->GetOp1();
|
||||
|
||||
if ( op->Tag() != EXPR_RECORD_CONSTRUCTOR )
|
||||
return false;
|
||||
if ( op->Tag() != EXPR_RECORD_CONSTRUCTOR )
|
||||
return false;
|
||||
|
||||
auto rc = static_cast<const RecordConstructorExpr*>(op.get());
|
||||
const auto& exprs = rc->Op()->AsListExpr()->Exprs();
|
||||
auto rc = static_cast<const RecordConstructorExpr*>(op.get());
|
||||
const auto& exprs = rc->Op()->AsListExpr()->Exprs();
|
||||
|
||||
return exprs.length() == 0;
|
||||
}
|
||||
return exprs.length() == 0;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -235,16 +235,16 @@ void CPPCompile::GenPreInit(const Type* t)
|
|||
break;
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
string name;
|
||||
{
|
||||
string name;
|
||||
|
||||
if ( t->GetName() != "" )
|
||||
name = string("\"") + t->GetName() + string("\"");
|
||||
else
|
||||
name = "nullptr";
|
||||
if ( t->GetName() != "" )
|
||||
name = string("\"") + t->GetName() + string("\"");
|
||||
else
|
||||
name = "nullptr";
|
||||
|
||||
pre_init = string("get_record_type__CPP(") + name + ")";
|
||||
}
|
||||
pre_init = string("get_record_type__CPP(") + name + ")";
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_LIST:
|
||||
|
|
|
@ -66,16 +66,16 @@ static VectorTypePtr base_vector_type__CPP(const VectorTypePtr& vt)
|
|||
switch ( vt->Yield()->InternalType() ) \
|
||||
{ \
|
||||
case TYPE_INTERNAL_INT: \
|
||||
{ \
|
||||
VEC_OP1_KERNEL(AsInt, IntVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
VEC_OP1_KERNEL(AsInt, IntVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case TYPE_INTERNAL_UNSIGNED: \
|
||||
{ \
|
||||
VEC_OP1_KERNEL(AsCount, CountVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
VEC_OP1_KERNEL(AsCount, CountVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
double_kernel \
|
||||
\
|
||||
|
@ -126,19 +126,19 @@ VEC_OP1(comp, ~, )
|
|||
switch ( vt->Yield()->InternalType() ) \
|
||||
{ \
|
||||
case TYPE_INTERNAL_INT: \
|
||||
{ \
|
||||
if ( vt->Yield()->Tag() == TYPE_BOOL ) \
|
||||
VEC_OP2_KERNEL(AsBool, BoolVal, op) \
|
||||
else \
|
||||
VEC_OP2_KERNEL(AsInt, IntVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
if ( vt->Yield()->Tag() == TYPE_BOOL ) \
|
||||
VEC_OP2_KERNEL(AsBool, BoolVal, op) \
|
||||
else \
|
||||
VEC_OP2_KERNEL(AsInt, IntVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case TYPE_INTERNAL_UNSIGNED: \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsCount, CountVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsCount, CountVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
double_kernel \
|
||||
\
|
||||
|
@ -184,22 +184,22 @@ VEC_OP2(oror, ||, )
|
|||
switch ( vt->Yield()->InternalType() ) \
|
||||
{ \
|
||||
case TYPE_INTERNAL_INT: \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsInt, BoolVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsInt, BoolVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case TYPE_INTERNAL_UNSIGNED: \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsCount, BoolVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsCount, BoolVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
case TYPE_INTERNAL_DOUBLE: \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsDouble, BoolVal, op) \
|
||||
break; \
|
||||
} \
|
||||
{ \
|
||||
VEC_OP2_KERNEL(AsDouble, BoolVal, op) \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
default: \
|
||||
break; \
|
||||
|
|
|
@ -18,15 +18,15 @@ void CPPCompile::GenStmt(const Stmt* s)
|
|||
break;
|
||||
|
||||
case STMT_LIST:
|
||||
{
|
||||
// These always occur in contexts surrounded by {}'s,
|
||||
// so no need to add them explicitly.
|
||||
auto sl = s->AsStmtList();
|
||||
const auto& stmts = sl->Stmts();
|
||||
{
|
||||
// These always occur in contexts surrounded by {}'s,
|
||||
// so no need to add them explicitly.
|
||||
auto sl = s->AsStmtList();
|
||||
const auto& stmts = sl->Stmts();
|
||||
|
||||
for ( const auto& stmt : stmts )
|
||||
GenStmt(stmt);
|
||||
}
|
||||
for ( const auto& stmt : stmts )
|
||||
GenStmt(stmt);
|
||||
}
|
||||
break;
|
||||
|
||||
case STMT_EXPR:
|
||||
|
@ -82,10 +82,10 @@ void CPPCompile::GenStmt(const Stmt* s)
|
|||
break;
|
||||
|
||||
case STMT_PRINT:
|
||||
{
|
||||
auto el = static_cast<const ExprListStmt*>(s)->ExprList();
|
||||
Emit("do_print_stmt({%s});", GenExpr(el, GEN_VAL_PTR));
|
||||
}
|
||||
{
|
||||
auto el = static_cast<const ExprListStmt*>(s)->ExprList();
|
||||
Emit("do_print_stmt({%s});", GenExpr(el, GEN_VAL_PTR));
|
||||
}
|
||||
break;
|
||||
|
||||
case STMT_FALLTHROUGH:
|
||||
|
|
|
@ -466,19 +466,19 @@ void CPPCompile::RegisterType(const TypePtr& tp)
|
|||
break;
|
||||
|
||||
case TYPE_TYPE:
|
||||
{
|
||||
const auto& tt = t->AsTypeType()->GetType();
|
||||
NoteNonRecordInitDependency(t, tt);
|
||||
RegisterType(tt);
|
||||
}
|
||||
{
|
||||
const auto& tt = t->AsTypeType()->GetType();
|
||||
NoteNonRecordInitDependency(t, tt);
|
||||
RegisterType(tt);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
const auto& yield = t->AsVectorType()->Yield();
|
||||
NoteNonRecordInitDependency(t, yield);
|
||||
RegisterType(yield);
|
||||
}
|
||||
{
|
||||
const auto& yield = t->AsVectorType()->Yield();
|
||||
NoteNonRecordInitDependency(t, yield);
|
||||
RegisterType(yield);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_LIST:
|
||||
|
|
|
@ -189,28 +189,28 @@ bool Expr::IsReducedConditional(Reducer* c) const
|
|||
return IsReduced(c);
|
||||
|
||||
case EXPR_IN:
|
||||
{
|
||||
auto op1 = GetOp1();
|
||||
auto op2 = GetOp2();
|
||||
|
||||
if ( op1->Tag() != EXPR_NAME && op1->Tag() != EXPR_LIST )
|
||||
return NonReduced(this);
|
||||
|
||||
if ( op2->GetType()->Tag() != TYPE_TABLE || ! op2->IsReduced(c) )
|
||||
return NonReduced(this);
|
||||
|
||||
if ( op1->Tag() == EXPR_LIST )
|
||||
{
|
||||
auto op1 = GetOp1();
|
||||
auto op2 = GetOp2();
|
||||
auto l1 = op1->AsListExpr();
|
||||
auto& l1_e = l1->Exprs();
|
||||
|
||||
if ( op1->Tag() != EXPR_NAME && op1->Tag() != EXPR_LIST )
|
||||
if ( l1_e.length() < 1 || l1_e.length() > 2 )
|
||||
return NonReduced(this);
|
||||
|
||||
if ( op2->GetType()->Tag() != TYPE_TABLE || ! op2->IsReduced(c) )
|
||||
return NonReduced(this);
|
||||
|
||||
if ( op1->Tag() == EXPR_LIST )
|
||||
{
|
||||
auto l1 = op1->AsListExpr();
|
||||
auto& l1_e = l1->Exprs();
|
||||
|
||||
if ( l1_e.length() < 1 || l1_e.length() > 2 )
|
||||
return NonReduced(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case EXPR_EQ:
|
||||
case EXPR_NE:
|
||||
case EXPR_LE:
|
||||
|
@ -324,41 +324,41 @@ ExprPtr Expr::ReduceToConditional(Reducer* c, StmtPtr& red_stmt)
|
|||
return Reduce(c, red_stmt);
|
||||
|
||||
case EXPR_IN:
|
||||
{
|
||||
// This is complicated because there are lots of forms
|
||||
// of "in" expressions, and we're only interested in
|
||||
// those with 1 or 2 indices, into a table.
|
||||
auto op1 = GetOp1();
|
||||
auto op2 = GetOp2();
|
||||
|
||||
if ( c->Optimizing() )
|
||||
return Reduce(c, red_stmt);
|
||||
|
||||
if ( op2->GetType()->Tag() != TYPE_TABLE )
|
||||
// Not a table de-reference.
|
||||
return Reduce(c, red_stmt);
|
||||
|
||||
if ( op1->Tag() == EXPR_LIST )
|
||||
{
|
||||
// This is complicated because there are lots of forms
|
||||
// of "in" expressions, and we're only interested in
|
||||
// those with 1 or 2 indices, into a table.
|
||||
auto op1 = GetOp1();
|
||||
auto op2 = GetOp2();
|
||||
auto l1 = op1->AsListExpr();
|
||||
auto& l1_e = l1->Exprs();
|
||||
|
||||
if ( c->Optimizing() )
|
||||
if ( l1_e.length() < 1 || l1_e.length() > 2 )
|
||||
// Wrong number of indices.
|
||||
return Reduce(c, red_stmt);
|
||||
|
||||
if ( op2->GetType()->Tag() != TYPE_TABLE )
|
||||
// Not a table de-reference.
|
||||
return Reduce(c, red_stmt);
|
||||
|
||||
if ( op1->Tag() == EXPR_LIST )
|
||||
{
|
||||
auto l1 = op1->AsListExpr();
|
||||
auto& l1_e = l1->Exprs();
|
||||
|
||||
if ( l1_e.length() < 1 || l1_e.length() > 2 )
|
||||
// Wrong number of indices.
|
||||
return Reduce(c, red_stmt);
|
||||
}
|
||||
|
||||
if ( ! op1->IsReduced(c) || ! op2->IsReduced(c) )
|
||||
{
|
||||
auto red2_stmt = ReduceToSingletons(c);
|
||||
auto res = ReduceToConditional(c, red_stmt);
|
||||
red_stmt = MergeStmts(red2_stmt, red_stmt);
|
||||
return res;
|
||||
}
|
||||
|
||||
return ThisPtr();
|
||||
}
|
||||
|
||||
if ( ! op1->IsReduced(c) || ! op2->IsReduced(c) )
|
||||
{
|
||||
auto red2_stmt = ReduceToSingletons(c);
|
||||
auto res = ReduceToConditional(c, red_stmt);
|
||||
red_stmt = MergeStmts(red2_stmt, red_stmt);
|
||||
return res;
|
||||
}
|
||||
|
||||
return ThisPtr();
|
||||
}
|
||||
|
||||
case EXPR_EQ:
|
||||
case EXPR_NE:
|
||||
case EXPR_LE:
|
||||
|
@ -1489,10 +1489,10 @@ bool RefExpr::HasReducedOps(Reducer* c) const
|
|||
return op->AsFieldExpr()->Op()->IsReduced(c);
|
||||
|
||||
case EXPR_INDEX:
|
||||
{
|
||||
auto ind = op->AsIndexExpr();
|
||||
return ind->Op1()->IsReduced(c) && ind->Op2()->IsReduced(c);
|
||||
}
|
||||
{
|
||||
auto ind = op->AsIndexExpr();
|
||||
return ind->Op1()->IsReduced(c) && ind->Op2()->IsReduced(c);
|
||||
}
|
||||
|
||||
case EXPR_LIST:
|
||||
return op->IsReduced(c);
|
||||
|
|
|
@ -67,140 +67,140 @@ TraversalCode GenIDDefs::PreStmt(const Stmt* s)
|
|||
switch ( s->Tag() )
|
||||
{
|
||||
case STMT_CATCH_RETURN:
|
||||
{
|
||||
auto cr = s->AsCatchReturnStmt();
|
||||
auto block = cr->Block();
|
||||
{
|
||||
auto cr = s->AsCatchReturnStmt();
|
||||
auto block = cr->Block();
|
||||
|
||||
StartConfluenceBlock(s);
|
||||
block->Traverse(this);
|
||||
EndConfluenceBlock();
|
||||
StartConfluenceBlock(s);
|
||||
block->Traverse(this);
|
||||
EndConfluenceBlock();
|
||||
|
||||
auto retvar = cr->RetVar();
|
||||
if ( retvar )
|
||||
TrackID(retvar->Id());
|
||||
auto retvar = cr->RetVar();
|
||||
if ( retvar )
|
||||
TrackID(retvar->Id());
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case STMT_IF:
|
||||
{
|
||||
auto i = s->AsIfStmt();
|
||||
auto cond = i->StmtExpr();
|
||||
auto t_branch = i->TrueBranch();
|
||||
auto f_branch = i->FalseBranch();
|
||||
{
|
||||
auto i = s->AsIfStmt();
|
||||
auto cond = i->StmtExpr();
|
||||
auto t_branch = i->TrueBranch();
|
||||
auto f_branch = i->FalseBranch();
|
||||
|
||||
cond->Traverse(this);
|
||||
cond->Traverse(this);
|
||||
|
||||
StartConfluenceBlock(s);
|
||||
StartConfluenceBlock(s);
|
||||
|
||||
t_branch->Traverse(this);
|
||||
if ( ! t_branch->NoFlowAfter(false) )
|
||||
BranchBeyond(curr_stmt, s, true);
|
||||
t_branch->Traverse(this);
|
||||
if ( ! t_branch->NoFlowAfter(false) )
|
||||
BranchBeyond(curr_stmt, s, true);
|
||||
|
||||
f_branch->Traverse(this);
|
||||
if ( ! f_branch->NoFlowAfter(false) )
|
||||
BranchBeyond(curr_stmt, s, true);
|
||||
f_branch->Traverse(this);
|
||||
if ( ! f_branch->NoFlowAfter(false) )
|
||||
BranchBeyond(curr_stmt, s, true);
|
||||
|
||||
EndConfluenceBlock(true);
|
||||
EndConfluenceBlock(true);
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case STMT_SWITCH:
|
||||
{
|
||||
auto sw = s->AsSwitchStmt();
|
||||
auto e = sw->StmtExpr();
|
||||
|
||||
e->Traverse(this);
|
||||
|
||||
StartConfluenceBlock(sw);
|
||||
|
||||
for ( const auto& c : *sw->Cases() )
|
||||
{
|
||||
auto sw = s->AsSwitchStmt();
|
||||
auto e = sw->StmtExpr();
|
||||
auto body = c->Body();
|
||||
|
||||
e->Traverse(this);
|
||||
auto exprs = c->ExprCases();
|
||||
if ( exprs )
|
||||
exprs->Traverse(this);
|
||||
|
||||
StartConfluenceBlock(sw);
|
||||
|
||||
for ( const auto& c : *sw->Cases() )
|
||||
auto type_ids = c->TypeCases();
|
||||
if ( type_ids )
|
||||
{
|
||||
auto body = c->Body();
|
||||
|
||||
auto exprs = c->ExprCases();
|
||||
if ( exprs )
|
||||
exprs->Traverse(this);
|
||||
|
||||
auto type_ids = c->TypeCases();
|
||||
if ( type_ids )
|
||||
{
|
||||
for ( const auto& id : *type_ids )
|
||||
if ( id->Name() )
|
||||
TrackID(id);
|
||||
}
|
||||
|
||||
body->Traverse(this);
|
||||
for ( const auto& id : *type_ids )
|
||||
if ( id->Name() )
|
||||
TrackID(id);
|
||||
}
|
||||
|
||||
EndConfluenceBlock(sw->HasDefault());
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
body->Traverse(this);
|
||||
}
|
||||
|
||||
EndConfluenceBlock(sw->HasDefault());
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case STMT_FOR:
|
||||
{
|
||||
auto f = s->AsForStmt();
|
||||
{
|
||||
auto f = s->AsForStmt();
|
||||
|
||||
auto ids = f->LoopVars();
|
||||
auto e = f->LoopExpr();
|
||||
auto body = f->LoopBody();
|
||||
auto val_var = f->ValueVar();
|
||||
auto ids = f->LoopVars();
|
||||
auto e = f->LoopExpr();
|
||||
auto body = f->LoopBody();
|
||||
auto val_var = f->ValueVar();
|
||||
|
||||
e->Traverse(this);
|
||||
e->Traverse(this);
|
||||
|
||||
for ( const auto& id : *ids )
|
||||
TrackID(id);
|
||||
for ( const auto& id : *ids )
|
||||
TrackID(id);
|
||||
|
||||
if ( val_var )
|
||||
TrackID(val_var);
|
||||
if ( val_var )
|
||||
TrackID(val_var);
|
||||
|
||||
StartConfluenceBlock(s);
|
||||
body->Traverse(this);
|
||||
StartConfluenceBlock(s);
|
||||
body->Traverse(this);
|
||||
|
||||
if ( ! body->NoFlowAfter(false) )
|
||||
BranchBackTo(curr_stmt, s, true);
|
||||
if ( ! body->NoFlowAfter(false) )
|
||||
BranchBackTo(curr_stmt, s, true);
|
||||
|
||||
EndConfluenceBlock();
|
||||
EndConfluenceBlock();
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case STMT_WHILE:
|
||||
{
|
||||
auto w = s->AsWhileStmt();
|
||||
{
|
||||
auto w = s->AsWhileStmt();
|
||||
|
||||
StartConfluenceBlock(s);
|
||||
StartConfluenceBlock(s);
|
||||
|
||||
auto cond_pred_stmt = w->CondPredStmt();
|
||||
if ( cond_pred_stmt )
|
||||
cond_pred_stmt->Traverse(this);
|
||||
auto cond_pred_stmt = w->CondPredStmt();
|
||||
if ( cond_pred_stmt )
|
||||
cond_pred_stmt->Traverse(this);
|
||||
|
||||
// Important to traverse the condition in its version
|
||||
// interpreted as a statement, so that when evaluating
|
||||
// its variable usage, that's done in the context of
|
||||
// *after* cond_pred_stmt executes, rather than as
|
||||
// part of that execution.
|
||||
auto cond_stmt = w->ConditionAsStmt();
|
||||
cond_stmt->Traverse(this);
|
||||
// Important to traverse the condition in its version
|
||||
// interpreted as a statement, so that when evaluating
|
||||
// its variable usage, that's done in the context of
|
||||
// *after* cond_pred_stmt executes, rather than as
|
||||
// part of that execution.
|
||||
auto cond_stmt = w->ConditionAsStmt();
|
||||
cond_stmt->Traverse(this);
|
||||
|
||||
auto body = w->Body();
|
||||
body->Traverse(this);
|
||||
auto body = w->Body();
|
||||
body->Traverse(this);
|
||||
|
||||
if ( ! body->NoFlowAfter(false) )
|
||||
BranchBackTo(curr_stmt, s, true);
|
||||
if ( ! body->NoFlowAfter(false) )
|
||||
BranchBackTo(curr_stmt, s, true);
|
||||
|
||||
EndConfluenceBlock();
|
||||
EndConfluenceBlock();
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case STMT_WHEN:
|
||||
{
|
||||
// ### punt on these for now, need to reflect on bindings.
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
{
|
||||
// ### punt on these for now, need to reflect on bindings.
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
default:
|
||||
return TC_CONTINUE;
|
||||
|
@ -212,22 +212,22 @@ TraversalCode GenIDDefs::PostStmt(const Stmt* s)
|
|||
switch ( s->Tag() )
|
||||
{
|
||||
case STMT_INIT:
|
||||
{
|
||||
auto init = s->AsInitStmt();
|
||||
auto& inits = init->Inits();
|
||||
|
||||
for ( const auto& id : inits )
|
||||
{
|
||||
auto init = s->AsInitStmt();
|
||||
auto& inits = init->Inits();
|
||||
auto id_t = id->GetType();
|
||||
|
||||
for ( const auto& id : inits )
|
||||
{
|
||||
auto id_t = id->GetType();
|
||||
|
||||
// Only aggregates get initialized.
|
||||
if ( zeek::IsAggr(id->GetType()->Tag()) )
|
||||
TrackID(id);
|
||||
}
|
||||
|
||||
break;
|
||||
// Only aggregates get initialized.
|
||||
if ( zeek::IsAggr(id->GetType()->Tag()) )
|
||||
TrackID(id);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case STMT_RETURN:
|
||||
ReturnAt(s);
|
||||
break;
|
||||
|
@ -237,21 +237,21 @@ TraversalCode GenIDDefs::PostStmt(const Stmt* s)
|
|||
break;
|
||||
|
||||
case STMT_BREAK:
|
||||
{
|
||||
auto target = FindBreakTarget();
|
||||
|
||||
if ( target )
|
||||
BranchBeyond(s, target, false);
|
||||
|
||||
else
|
||||
{
|
||||
auto target = FindBreakTarget();
|
||||
|
||||
if ( target )
|
||||
BranchBeyond(s, target, false);
|
||||
|
||||
else
|
||||
{
|
||||
ASSERT(func_flavor == FUNC_FLAVOR_HOOK);
|
||||
ReturnAt(s);
|
||||
}
|
||||
|
||||
break;
|
||||
ASSERT(func_flavor == FUNC_FLAVOR_HOOK);
|
||||
ReturnAt(s);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case STMT_FALLTHROUGH:
|
||||
// No need to do anything, the work all occurs
|
||||
// with NoFlowAfter.
|
||||
|
@ -275,29 +275,29 @@ TraversalCode GenIDDefs::PreExpr(const Expr* e)
|
|||
break;
|
||||
|
||||
case EXPR_ASSIGN:
|
||||
{
|
||||
auto lhs = e->GetOp1();
|
||||
auto op2 = e->GetOp2();
|
||||
|
||||
if ( lhs->Tag() == EXPR_LIST && op2->GetType()->Tag() != TYPE_ANY )
|
||||
{
|
||||
auto lhs = e->GetOp1();
|
||||
auto op2 = e->GetOp2();
|
||||
|
||||
if ( lhs->Tag() == EXPR_LIST && op2->GetType()->Tag() != TYPE_ANY )
|
||||
{
|
||||
// This combination occurs only for assignments used
|
||||
// to initialize table entries. Treat it as references
|
||||
// to both the lhs and the rhs, not as an assignment.
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
op2->Traverse(this);
|
||||
|
||||
if ( ! CheckLHS(lhs, op2) )
|
||||
// Not a simple assignment (or group of assignments),
|
||||
// so analyze the accesses to check for use of
|
||||
// possibly undefined values.
|
||||
lhs->Traverse(this);
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
// This combination occurs only for assignments used
|
||||
// to initialize table entries. Treat it as references
|
||||
// to both the lhs and the rhs, not as an assignment.
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
op2->Traverse(this);
|
||||
|
||||
if ( ! CheckLHS(lhs, op2) )
|
||||
// Not a simple assignment (or group of assignments),
|
||||
// so analyze the accesses to check for use of
|
||||
// possibly undefined values.
|
||||
lhs->Traverse(this);
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case EXPR_COND:
|
||||
// Special hack. We turn off checking for usage issues
|
||||
// inside conditionals. This is because we use them heavily
|
||||
|
@ -314,17 +314,17 @@ TraversalCode GenIDDefs::PreExpr(const Expr* e)
|
|||
return TC_ABORTSTMT;
|
||||
|
||||
case EXPR_LAMBDA:
|
||||
{
|
||||
auto l = static_cast<const LambdaExpr*>(e);
|
||||
const auto& ids = l->OuterIDs();
|
||||
{
|
||||
auto l = static_cast<const LambdaExpr*>(e);
|
||||
const auto& ids = l->OuterIDs();
|
||||
|
||||
for ( auto& id : ids )
|
||||
CheckVarUsage(e, id);
|
||||
for ( auto& id : ids )
|
||||
CheckVarUsage(e, id);
|
||||
|
||||
// Don't descend into the lambda body - we'll analyze and
|
||||
// optimize it separately, as its own function.
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
// Don't descend into the lambda body - we'll analyze and
|
||||
// optimize it separately, as its own function.
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -360,29 +360,29 @@ bool GenIDDefs::CheckLHS(const ExprPtr& lhs, const ExprPtr& rhs)
|
|||
return CheckLHS(lhs->GetOp1(), rhs);
|
||||
|
||||
case EXPR_NAME:
|
||||
{
|
||||
auto n = lhs->AsNameExpr();
|
||||
TrackID(n->Id(), rhs);
|
||||
return true;
|
||||
}
|
||||
{
|
||||
auto n = lhs->AsNameExpr();
|
||||
TrackID(n->Id(), rhs);
|
||||
return true;
|
||||
}
|
||||
|
||||
case EXPR_LIST:
|
||||
{ // look for [a, b, c] = any_val
|
||||
auto l = lhs->AsListExpr();
|
||||
for ( const auto& expr : l->Exprs() )
|
||||
{
|
||||
if ( expr->Tag() != EXPR_NAME )
|
||||
// This will happen for table initializers,
|
||||
// for example.
|
||||
return false;
|
||||
{ // look for [a, b, c] = any_val
|
||||
auto l = lhs->AsListExpr();
|
||||
for ( const auto& expr : l->Exprs() )
|
||||
{
|
||||
if ( expr->Tag() != EXPR_NAME )
|
||||
// This will happen for table initializers,
|
||||
// for example.
|
||||
return false;
|
||||
|
||||
auto n = expr->AsNameExpr();
|
||||
TrackID(n->Id());
|
||||
}
|
||||
|
||||
return true;
|
||||
auto n = expr->AsNameExpr();
|
||||
TrackID(n->Id());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case EXPR_FIELD:
|
||||
// If we want to track record field initializations,
|
||||
// we'd handle that here.
|
||||
|
|
|
@ -129,49 +129,49 @@ TraversalCode ProfileFunc::PreStmt(const Stmt* s)
|
|||
break;
|
||||
|
||||
case STMT_FOR:
|
||||
{
|
||||
auto sf = s->AsForStmt();
|
||||
auto loop_vars = sf->LoopVars();
|
||||
auto value_var = sf->ValueVar();
|
||||
{
|
||||
auto sf = s->AsForStmt();
|
||||
auto loop_vars = sf->LoopVars();
|
||||
auto value_var = sf->ValueVar();
|
||||
|
||||
for ( auto id : *loop_vars )
|
||||
locals.insert(id);
|
||||
for ( auto id : *loop_vars )
|
||||
locals.insert(id);
|
||||
|
||||
if ( value_var )
|
||||
locals.insert(value_var.get());
|
||||
}
|
||||
if ( value_var )
|
||||
locals.insert(value_var.get());
|
||||
}
|
||||
break;
|
||||
|
||||
case STMT_SWITCH:
|
||||
{
|
||||
// If this is a type-case switch statement, then find the
|
||||
// identifiers created so we can add them to our list of
|
||||
// locals. Ideally this wouldn't be necessary since *surely*
|
||||
// if one bothers to define such an identifier then it'll be
|
||||
// subsequently used, and we'll pick up the local that way ...
|
||||
// but if for some reason it's not, then we would have an
|
||||
// incomplete list of locals that need to be tracked.
|
||||
|
||||
auto sw = s->AsSwitchStmt();
|
||||
bool is_type_switch = false;
|
||||
|
||||
for ( auto& c : *sw->Cases() )
|
||||
{
|
||||
// If this is a type-case switch statement, then find the
|
||||
// identifiers created so we can add them to our list of
|
||||
// locals. Ideally this wouldn't be necessary since *surely*
|
||||
// if one bothers to define such an identifier then it'll be
|
||||
// subsequently used, and we'll pick up the local that way ...
|
||||
// but if for some reason it's not, then we would have an
|
||||
// incomplete list of locals that need to be tracked.
|
||||
|
||||
auto sw = s->AsSwitchStmt();
|
||||
bool is_type_switch = false;
|
||||
|
||||
for ( auto& c : *sw->Cases() )
|
||||
auto idl = c->TypeCases();
|
||||
if ( idl )
|
||||
{
|
||||
auto idl = c->TypeCases();
|
||||
if ( idl )
|
||||
{
|
||||
for ( auto id : *idl )
|
||||
locals.insert(id);
|
||||
for ( auto id : *idl )
|
||||
locals.insert(id);
|
||||
|
||||
is_type_switch = true;
|
||||
}
|
||||
is_type_switch = true;
|
||||
}
|
||||
|
||||
if ( is_type_switch )
|
||||
type_switches.insert(sw);
|
||||
else
|
||||
expr_switches.insert(sw);
|
||||
}
|
||||
|
||||
if ( is_type_switch )
|
||||
type_switches.insert(sw);
|
||||
else
|
||||
expr_switches.insert(sw);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -194,46 +194,46 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e)
|
|||
break;
|
||||
|
||||
case EXPR_NAME:
|
||||
{
|
||||
auto n = e->AsNameExpr();
|
||||
auto id = n->Id();
|
||||
|
||||
if ( id->IsGlobal() )
|
||||
{
|
||||
auto n = e->AsNameExpr();
|
||||
auto id = n->Id();
|
||||
globals.insert(id);
|
||||
all_globals.insert(id);
|
||||
|
||||
if ( id->IsGlobal() )
|
||||
{
|
||||
globals.insert(id);
|
||||
all_globals.insert(id);
|
||||
|
||||
const auto& t = id->GetType();
|
||||
if ( t->Tag() == TYPE_FUNC && t->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT )
|
||||
events.insert(id->Name());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// This is a tad ugly. Unfortunately due to the
|
||||
// weird way that Zeek function *declarations* work,
|
||||
// there's no reliable way to get the list of
|
||||
// parameters for a function *definition*, since
|
||||
// they can have different names than what's present
|
||||
// in the declaration. So we identify them directly,
|
||||
// by knowing that they come at the beginning of the
|
||||
// frame ... and being careful to avoid misconfusing
|
||||
// a lambda capture with a low frame offset as a
|
||||
// parameter.
|
||||
if ( captures.count(id) == 0 && id->Offset() < num_params )
|
||||
params.insert(id);
|
||||
|
||||
locals.insert(id);
|
||||
}
|
||||
|
||||
// Turns out that NameExpr's can be constructed using a
|
||||
// different Type* than that of the identifier itself,
|
||||
// so be sure we track the latter too.
|
||||
TrackType(id->GetType());
|
||||
|
||||
break;
|
||||
const auto& t = id->GetType();
|
||||
if ( t->Tag() == TYPE_FUNC && t->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT )
|
||||
events.insert(id->Name());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// This is a tad ugly. Unfortunately due to the
|
||||
// weird way that Zeek function *declarations* work,
|
||||
// there's no reliable way to get the list of
|
||||
// parameters for a function *definition*, since
|
||||
// they can have different names than what's present
|
||||
// in the declaration. So we identify them directly,
|
||||
// by knowing that they come at the beginning of the
|
||||
// frame ... and being careful to avoid misconfusing
|
||||
// a lambda capture with a low frame offset as a
|
||||
// parameter.
|
||||
if ( captures.count(id) == 0 && id->Offset() < num_params )
|
||||
params.insert(id);
|
||||
|
||||
locals.insert(id);
|
||||
}
|
||||
|
||||
// Turns out that NameExpr's can be constructed using a
|
||||
// different Type* than that of the identifier itself,
|
||||
// so be sure we track the latter too.
|
||||
TrackType(id->GetType());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_FIELD:
|
||||
if ( abs_rec_fields )
|
||||
{
|
||||
|
@ -265,130 +265,130 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e)
|
|||
case EXPR_ADD_TO:
|
||||
case EXPR_REMOVE_FROM:
|
||||
case EXPR_ASSIGN:
|
||||
{
|
||||
if ( e->GetOp1()->Tag() == EXPR_REF )
|
||||
{
|
||||
if ( e->GetOp1()->Tag() == EXPR_REF )
|
||||
{
|
||||
auto lhs = e->GetOp1()->GetOp1();
|
||||
if ( lhs->Tag() == EXPR_NAME )
|
||||
TrackAssignment(lhs->AsNameExpr()->Id());
|
||||
}
|
||||
// else this isn't a direct assignment.
|
||||
break;
|
||||
auto lhs = e->GetOp1()->GetOp1();
|
||||
if ( lhs->Tag() == EXPR_NAME )
|
||||
TrackAssignment(lhs->AsNameExpr()->Id());
|
||||
}
|
||||
// else this isn't a direct assignment.
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_CALL:
|
||||
{
|
||||
auto c = e->AsCallExpr();
|
||||
auto f = c->Func();
|
||||
|
||||
if ( f->Tag() != EXPR_NAME )
|
||||
{
|
||||
auto c = e->AsCallExpr();
|
||||
auto f = c->Func();
|
||||
does_indirect_calls = true;
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
if ( f->Tag() != EXPR_NAME )
|
||||
auto n = f->AsNameExpr();
|
||||
auto func = n->Id();
|
||||
|
||||
if ( ! func->IsGlobal() )
|
||||
{
|
||||
does_indirect_calls = true;
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
all_globals.insert(func);
|
||||
|
||||
auto func_v = func->GetVal();
|
||||
if ( func_v )
|
||||
{
|
||||
auto func_vf = func_v->AsFunc();
|
||||
|
||||
if ( func_vf->GetKind() == Func::SCRIPT_FUNC )
|
||||
{
|
||||
does_indirect_calls = true;
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
auto bf = static_cast<ScriptFunc*>(func_vf);
|
||||
script_calls.insert(bf);
|
||||
|
||||
auto n = f->AsNameExpr();
|
||||
auto func = n->Id();
|
||||
|
||||
if ( ! func->IsGlobal() )
|
||||
{
|
||||
does_indirect_calls = true;
|
||||
return TC_CONTINUE;
|
||||
}
|
||||
|
||||
all_globals.insert(func);
|
||||
|
||||
auto func_v = func->GetVal();
|
||||
if ( func_v )
|
||||
{
|
||||
auto func_vf = func_v->AsFunc();
|
||||
|
||||
if ( func_vf->GetKind() == Func::SCRIPT_FUNC )
|
||||
{
|
||||
auto bf = static_cast<ScriptFunc*>(func_vf);
|
||||
script_calls.insert(bf);
|
||||
|
||||
if ( in_when )
|
||||
when_calls.insert(bf);
|
||||
}
|
||||
else
|
||||
BiF_globals.insert(func);
|
||||
if ( in_when )
|
||||
when_calls.insert(bf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We could complain, but for now we don't, because
|
||||
// if we're invoked prior to full Zeek initialization,
|
||||
// the value might indeed not there yet.
|
||||
// printf("no function value for global %s\n", func->Name());
|
||||
}
|
||||
|
||||
// Recurse into the arguments.
|
||||
auto args = c->Args();
|
||||
args->Traverse(this);
|
||||
|
||||
// Do the following explicitly, since we won't be recursing
|
||||
// into the LHS global.
|
||||
|
||||
// Note that the type of the expression and the type of the
|
||||
// function can actually be *different* due to the NameExpr
|
||||
// being constructed based on a forward reference and then
|
||||
// the global getting a different (constructed) type when
|
||||
// the function is actually declared. Geez. So hedge our
|
||||
// bets.
|
||||
TrackType(n->GetType());
|
||||
TrackType(func->GetType());
|
||||
|
||||
TrackID(func);
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
BiF_globals.insert(func);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We could complain, but for now we don't, because
|
||||
// if we're invoked prior to full Zeek initialization,
|
||||
// the value might indeed not there yet.
|
||||
// printf("no function value for global %s\n", func->Name());
|
||||
}
|
||||
|
||||
// Recurse into the arguments.
|
||||
auto args = c->Args();
|
||||
args->Traverse(this);
|
||||
|
||||
// Do the following explicitly, since we won't be recursing
|
||||
// into the LHS global.
|
||||
|
||||
// Note that the type of the expression and the type of the
|
||||
// function can actually be *different* due to the NameExpr
|
||||
// being constructed based on a forward reference and then
|
||||
// the global getting a different (constructed) type when
|
||||
// the function is actually declared. Geez. So hedge our
|
||||
// bets.
|
||||
TrackType(n->GetType());
|
||||
TrackType(func->GetType());
|
||||
|
||||
TrackID(func);
|
||||
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case EXPR_EVENT:
|
||||
{
|
||||
auto ev = e->AsEventExpr()->Name();
|
||||
events.insert(ev);
|
||||
addl_hashes.push_back(p_hash(ev));
|
||||
}
|
||||
{
|
||||
auto ev = e->AsEventExpr()->Name();
|
||||
events.insert(ev);
|
||||
addl_hashes.push_back(p_hash(ev));
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_LAMBDA:
|
||||
{
|
||||
auto l = e->AsLambdaExpr();
|
||||
lambdas.push_back(l);
|
||||
|
||||
for ( const auto& i : l->OuterIDs() )
|
||||
{
|
||||
auto l = e->AsLambdaExpr();
|
||||
lambdas.push_back(l);
|
||||
locals.insert(i);
|
||||
TrackID(i);
|
||||
|
||||
for ( const auto& i : l->OuterIDs() )
|
||||
{
|
||||
locals.insert(i);
|
||||
TrackID(i);
|
||||
|
||||
// See above re EXPR_NAME regarding the following
|
||||
// logic.
|
||||
if ( captures.count(i) == 0 && i->Offset() < num_params )
|
||||
params.insert(i);
|
||||
}
|
||||
|
||||
// Avoid recursing into the body.
|
||||
return TC_ABORTSTMT;
|
||||
// See above re EXPR_NAME regarding the following
|
||||
// logic.
|
||||
if ( captures.count(i) == 0 && i->Offset() < num_params )
|
||||
params.insert(i);
|
||||
}
|
||||
|
||||
// Avoid recursing into the body.
|
||||
return TC_ABORTSTMT;
|
||||
}
|
||||
|
||||
case EXPR_SET_CONSTRUCTOR:
|
||||
{
|
||||
auto sc = static_cast<const SetConstructorExpr*>(e);
|
||||
const auto& attrs = sc->GetAttrs();
|
||||
{
|
||||
auto sc = static_cast<const SetConstructorExpr*>(e);
|
||||
const auto& attrs = sc->GetAttrs();
|
||||
|
||||
if ( attrs )
|
||||
constructor_attrs.insert(attrs.get());
|
||||
}
|
||||
if ( attrs )
|
||||
constructor_attrs.insert(attrs.get());
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_TABLE_CONSTRUCTOR:
|
||||
{
|
||||
auto tc = static_cast<const TableConstructorExpr*>(e);
|
||||
const auto& attrs = tc->GetAttrs();
|
||||
{
|
||||
auto tc = static_cast<const TableConstructorExpr*>(e);
|
||||
const auto& attrs = tc->GetAttrs();
|
||||
|
||||
if ( attrs )
|
||||
constructor_attrs.insert(attrs.get());
|
||||
}
|
||||
if ( attrs )
|
||||
constructor_attrs.insert(attrs.get());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -560,46 +560,46 @@ void ProfileFuncs::TraverseValue(const ValPtr& v)
|
|||
break;
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
auto r = cast_intrusive<RecordVal>(v);
|
||||
auto n = r->NumFields();
|
||||
{
|
||||
auto r = cast_intrusive<RecordVal>(v);
|
||||
auto n = r->NumFields();
|
||||
|
||||
for ( auto i = 0u; i < n; ++i )
|
||||
TraverseValue(r->GetField(i));
|
||||
}
|
||||
for ( auto i = 0u; i < n; ++i )
|
||||
TraverseValue(r->GetField(i));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto tv = cast_intrusive<TableVal>(v);
|
||||
auto tv_map = tv->ToMap();
|
||||
{
|
||||
auto tv = cast_intrusive<TableVal>(v);
|
||||
auto tv_map = tv->ToMap();
|
||||
|
||||
for ( auto& tv_i : tv_map )
|
||||
{
|
||||
TraverseValue(tv_i.first);
|
||||
TraverseValue(tv_i.second);
|
||||
}
|
||||
for ( auto& tv_i : tv_map )
|
||||
{
|
||||
TraverseValue(tv_i.first);
|
||||
TraverseValue(tv_i.second);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
auto lv = cast_intrusive<ListVal>(v);
|
||||
auto n = lv->Length();
|
||||
{
|
||||
auto lv = cast_intrusive<ListVal>(v);
|
||||
auto n = lv->Length();
|
||||
|
||||
for ( auto i = 0; i < n; ++i )
|
||||
TraverseValue(lv->Idx(i));
|
||||
}
|
||||
for ( auto i = 0; i < n; ++i )
|
||||
TraverseValue(lv->Idx(i));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
auto vv = cast_intrusive<VectorVal>(v);
|
||||
auto n = vv->Size();
|
||||
{
|
||||
auto vv = cast_intrusive<VectorVal>(v);
|
||||
auto n = vv->Size();
|
||||
|
||||
for ( auto i = 0u; i < n; ++i )
|
||||
TraverseValue(vv->ValAt(i));
|
||||
}
|
||||
for ( auto i = 0u; i < n; ++i )
|
||||
TraverseValue(vv->ValAt(i));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_TYPE:
|
||||
|
@ -759,82 +759,82 @@ p_hash_type ProfileFuncs::HashType(const Type* t)
|
|||
break;
|
||||
|
||||
case TYPE_RECORD:
|
||||
{
|
||||
const auto& ft = t->AsRecordType();
|
||||
auto n = ft->NumFields();
|
||||
auto orig_n = ft->NumOrigFields();
|
||||
|
||||
h = merge_p_hashes(h, p_hash("record"));
|
||||
|
||||
if ( full_record_hashes )
|
||||
h = merge_p_hashes(h, p_hash(n));
|
||||
else
|
||||
h = merge_p_hashes(h, p_hash(orig_n));
|
||||
|
||||
for ( auto i = 0; i < n; ++i )
|
||||
{
|
||||
const auto& ft = t->AsRecordType();
|
||||
auto n = ft->NumFields();
|
||||
auto orig_n = ft->NumOrigFields();
|
||||
bool do_hash = full_record_hashes;
|
||||
if ( ! do_hash )
|
||||
do_hash = (i < orig_n);
|
||||
|
||||
h = merge_p_hashes(h, p_hash("record"));
|
||||
const auto& f = ft->FieldDecl(i);
|
||||
auto type_h = HashType(f->type);
|
||||
|
||||
if ( full_record_hashes )
|
||||
h = merge_p_hashes(h, p_hash(n));
|
||||
else
|
||||
h = merge_p_hashes(h, p_hash(orig_n));
|
||||
|
||||
for ( auto i = 0; i < n; ++i )
|
||||
if ( do_hash )
|
||||
{
|
||||
bool do_hash = full_record_hashes;
|
||||
if ( ! do_hash )
|
||||
do_hash = (i < orig_n);
|
||||
|
||||
const auto& f = ft->FieldDecl(i);
|
||||
auto type_h = HashType(f->type);
|
||||
|
||||
if ( do_hash )
|
||||
{
|
||||
h = merge_p_hashes(h, p_hash(f->id));
|
||||
h = merge_p_hashes(h, type_h);
|
||||
}
|
||||
|
||||
h = merge_p_hashes(h, p_hash(f->id));
|
||||
h = merge_p_hashes(h, HashType(f->type));
|
||||
h = merge_p_hashes(h, type_h);
|
||||
}
|
||||
|
||||
// We don't hash the field name, as in some contexts
|
||||
// those are ignored.
|
||||
h = merge_p_hashes(h, p_hash(f->id));
|
||||
h = merge_p_hashes(h, HashType(f->type));
|
||||
|
||||
if ( f->attrs )
|
||||
{
|
||||
if ( do_hash )
|
||||
h = merge_p_hashes(h, HashAttrs(f->attrs));
|
||||
AnalyzeAttrs(f->attrs.get());
|
||||
}
|
||||
// We don't hash the field name, as in some contexts
|
||||
// those are ignored.
|
||||
|
||||
if ( f->attrs )
|
||||
{
|
||||
if ( do_hash )
|
||||
h = merge_p_hashes(h, HashAttrs(f->attrs));
|
||||
AnalyzeAttrs(f->attrs.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
auto tbl = t->AsTableType();
|
||||
h = merge_p_hashes(h, p_hash("table"));
|
||||
h = merge_p_hashes(h, p_hash("indices"));
|
||||
h = merge_p_hashes(h, HashType(tbl->GetIndices()));
|
||||
h = merge_p_hashes(h, p_hash("tbl-yield"));
|
||||
h = merge_p_hashes(h, HashType(tbl->Yield()));
|
||||
}
|
||||
{
|
||||
auto tbl = t->AsTableType();
|
||||
h = merge_p_hashes(h, p_hash("table"));
|
||||
h = merge_p_hashes(h, p_hash("indices"));
|
||||
h = merge_p_hashes(h, HashType(tbl->GetIndices()));
|
||||
h = merge_p_hashes(h, p_hash("tbl-yield"));
|
||||
h = merge_p_hashes(h, HashType(tbl->Yield()));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
auto ft = t->AsFuncType();
|
||||
auto flv = ft->FlavorString();
|
||||
h = merge_p_hashes(h, p_hash(flv));
|
||||
h = merge_p_hashes(h, p_hash("params"));
|
||||
h = merge_p_hashes(h, HashType(ft->Params()));
|
||||
h = merge_p_hashes(h, p_hash("func-yield"));
|
||||
h = merge_p_hashes(h, HashType(ft->Yield()));
|
||||
}
|
||||
{
|
||||
auto ft = t->AsFuncType();
|
||||
auto flv = ft->FlavorString();
|
||||
h = merge_p_hashes(h, p_hash(flv));
|
||||
h = merge_p_hashes(h, p_hash("params"));
|
||||
h = merge_p_hashes(h, HashType(ft->Params()));
|
||||
h = merge_p_hashes(h, p_hash("func-yield"));
|
||||
h = merge_p_hashes(h, HashType(ft->Yield()));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_LIST:
|
||||
{
|
||||
auto& tl = t->AsTypeList()->GetTypes();
|
||||
{
|
||||
auto& tl = t->AsTypeList()->GetTypes();
|
||||
|
||||
h = merge_p_hashes(h, p_hash("list"));
|
||||
h = merge_p_hashes(h, p_hash(tl.size()));
|
||||
h = merge_p_hashes(h, p_hash("list"));
|
||||
h = merge_p_hashes(h, p_hash(tl.size()));
|
||||
|
||||
for ( const auto& tl_i : tl )
|
||||
h = merge_p_hashes(h, HashType(tl_i));
|
||||
}
|
||||
for ( const auto& tl_i : tl )
|
||||
h = merge_p_hashes(h, HashType(tl_i));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_VECTOR:
|
||||
|
|
|
@ -272,81 +272,81 @@ bool Reducer::SameExpr(const Expr* e1, const Expr* e2)
|
|||
reporter->InternalError("Unexpected tag in Reducer::SameExpr");
|
||||
|
||||
case EXPR_ANY_INDEX:
|
||||
{
|
||||
auto a1 = e1->AsAnyIndexExpr();
|
||||
auto a2 = e2->AsAnyIndexExpr();
|
||||
{
|
||||
auto a1 = e1->AsAnyIndexExpr();
|
||||
auto a2 = e2->AsAnyIndexExpr();
|
||||
|
||||
if ( a1->Index() != a2->Index() )
|
||||
return false;
|
||||
if ( a1->Index() != a2->Index() )
|
||||
return false;
|
||||
|
||||
return SameOp(a1->GetOp1(), a2->GetOp1());
|
||||
}
|
||||
return SameOp(a1->GetOp1(), a2->GetOp1());
|
||||
}
|
||||
|
||||
case EXPR_FIELD:
|
||||
{
|
||||
auto f1 = e1->AsFieldExpr();
|
||||
auto f2 = e2->AsFieldExpr();
|
||||
{
|
||||
auto f1 = e1->AsFieldExpr();
|
||||
auto f2 = e2->AsFieldExpr();
|
||||
|
||||
if ( f1->Field() != f2->Field() )
|
||||
return false;
|
||||
if ( f1->Field() != f2->Field() )
|
||||
return false;
|
||||
|
||||
return SameOp(f1->GetOp1(), f2->GetOp1());
|
||||
}
|
||||
return SameOp(f1->GetOp1(), f2->GetOp1());
|
||||
}
|
||||
|
||||
case EXPR_HAS_FIELD:
|
||||
{
|
||||
auto f1 = e1->AsHasFieldExpr();
|
||||
auto f2 = e2->AsHasFieldExpr();
|
||||
{
|
||||
auto f1 = e1->AsHasFieldExpr();
|
||||
auto f2 = e2->AsHasFieldExpr();
|
||||
|
||||
if ( f1->Field() != f2->Field() )
|
||||
return false;
|
||||
if ( f1->Field() != f2->Field() )
|
||||
return false;
|
||||
|
||||
return SameOp(f1->GetOp1(), f2->GetOp1());
|
||||
}
|
||||
return SameOp(f1->GetOp1(), f2->GetOp1());
|
||||
}
|
||||
|
||||
case EXPR_LIST:
|
||||
{
|
||||
auto l1 = e1->AsListExpr()->Exprs();
|
||||
auto l2 = e2->AsListExpr()->Exprs();
|
||||
{
|
||||
auto l1 = e1->AsListExpr()->Exprs();
|
||||
auto l2 = e2->AsListExpr()->Exprs();
|
||||
|
||||
ASSERT(l1.length() == l2.length());
|
||||
ASSERT(l1.length() == l2.length());
|
||||
|
||||
for ( int i = 0; i < l1.length(); ++i )
|
||||
if ( ! SameExpr(l1[i], l2[i]) )
|
||||
return false;
|
||||
for ( int i = 0; i < l1.length(); ++i )
|
||||
if ( ! SameExpr(l1[i], l2[i]) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case EXPR_CALL:
|
||||
{
|
||||
auto c1 = e1->AsCallExpr();
|
||||
auto c2 = e2->AsCallExpr();
|
||||
auto f1 = c1->Func();
|
||||
auto f2 = c2->Func();
|
||||
{
|
||||
auto c1 = e1->AsCallExpr();
|
||||
auto c2 = e2->AsCallExpr();
|
||||
auto f1 = c1->Func();
|
||||
auto f2 = c2->Func();
|
||||
|
||||
if ( f1 != f2 )
|
||||
return false;
|
||||
if ( f1 != f2 )
|
||||
return false;
|
||||
|
||||
if ( ! f1->IsPure() )
|
||||
return false;
|
||||
if ( ! f1->IsPure() )
|
||||
return false;
|
||||
|
||||
return SameExpr(c1->Args(), c2->Args());
|
||||
}
|
||||
return SameExpr(c1->Args(), c2->Args());
|
||||
}
|
||||
|
||||
case EXPR_LAMBDA:
|
||||
return false;
|
||||
|
||||
case EXPR_IS:
|
||||
{
|
||||
if ( ! SameOp(e1->GetOp1(), e2->GetOp1()) )
|
||||
return false;
|
||||
{
|
||||
if ( ! SameOp(e1->GetOp1(), e2->GetOp1()) )
|
||||
return false;
|
||||
|
||||
auto i1 = e1->AsIsExpr();
|
||||
auto i2 = e2->AsIsExpr();
|
||||
auto i1 = e1->AsIsExpr();
|
||||
auto i2 = e2->AsIsExpr();
|
||||
|
||||
return same_type(i1->TestType(), i2->TestType());
|
||||
}
|
||||
return same_type(i1->TestType(), i2->TestType());
|
||||
}
|
||||
|
||||
default:
|
||||
if ( ! e1->GetOp1() )
|
||||
|
@ -865,59 +865,59 @@ TraversalCode CSE_ValidityChecker::PreExpr(const Expr* e)
|
|||
switch ( t )
|
||||
{
|
||||
case EXPR_ASSIGN:
|
||||
{
|
||||
auto lhs_ref = e->GetOp1()->AsRefExprPtr();
|
||||
auto lhs = lhs_ref->GetOp1()->AsNameExpr();
|
||||
|
||||
if ( CheckID(ids, lhs->Id(), false) )
|
||||
{
|
||||
auto lhs_ref = e->GetOp1()->AsRefExprPtr();
|
||||
auto lhs = lhs_ref->GetOp1()->AsNameExpr();
|
||||
|
||||
if ( CheckID(ids, lhs->Id(), false) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
|
||||
// Note, we don't use CheckAggrMod() because this
|
||||
// is a plain assignment. It might be changing a variable's
|
||||
// binding to an aggregate, but it's not changing the
|
||||
// aggregate itself.
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
|
||||
// Note, we don't use CheckAggrMod() because this
|
||||
// is a plain assignment. It might be changing a variable's
|
||||
// binding to an aggregate, but it's not changing the
|
||||
// aggregate itself.
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_INDEX_ASSIGN:
|
||||
{
|
||||
auto lhs_aggr = e->GetOp1();
|
||||
auto lhs_aggr_id = lhs_aggr->AsNameExpr()->Id();
|
||||
{
|
||||
auto lhs_aggr = e->GetOp1();
|
||||
auto lhs_aggr_id = lhs_aggr->AsNameExpr()->Id();
|
||||
|
||||
if ( CheckID(ids, lhs_aggr_id, true) || CheckAggrMod(ids, e) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
if ( CheckID(ids, lhs_aggr_id, true) || CheckAggrMod(ids, e) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_FIELD_LHS_ASSIGN:
|
||||
{
|
||||
auto lhs = e->GetOp1();
|
||||
auto lhs_aggr_id = lhs->AsNameExpr()->Id();
|
||||
auto lhs_field = e->AsFieldLHSAssignExpr()->Field();
|
||||
|
||||
if ( lhs_field == field && same_type(lhs_aggr_id->GetType(), field_type) )
|
||||
{
|
||||
auto lhs = e->GetOp1();
|
||||
auto lhs_aggr_id = lhs->AsNameExpr()->Id();
|
||||
auto lhs_field = e->AsFieldLHSAssignExpr()->Field();
|
||||
|
||||
if ( lhs_field == field && same_type(lhs_aggr_id->GetType(), field_type) )
|
||||
{
|
||||
// Potential assignment to the same field as for
|
||||
// our expression of interest. Even if the
|
||||
// identifier involved is not one we have our eye
|
||||
// on, due to aggregate aliasing this could be
|
||||
// altering the value of our expression, so bail.
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
|
||||
if ( CheckID(ids, lhs_aggr_id, true) || CheckAggrMod(ids, e) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
// Potential assignment to the same field as for
|
||||
// our expression of interest. Even if the
|
||||
// identifier involved is not one we have our eye
|
||||
// on, due to aggregate aliasing this could be
|
||||
// altering the value of our expression, so bail.
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
|
||||
if ( CheckID(ids, lhs_aggr_id, true) || CheckAggrMod(ids, e) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_APPEND_TO:
|
||||
|
@ -931,14 +931,14 @@ TraversalCode CSE_ValidityChecker::PreExpr(const Expr* e)
|
|||
break;
|
||||
|
||||
case EXPR_CALL:
|
||||
{
|
||||
for ( auto i : ids )
|
||||
if ( i->IsGlobal() || IsAggr(i->GetType()) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
}
|
||||
{
|
||||
for ( auto i : ids )
|
||||
if ( i->IsGlobal() || IsAggr(i->GetType()) )
|
||||
{
|
||||
is_valid = false;
|
||||
return TC_ABORTALL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -185,40 +185,40 @@ UDs UseDefs::PropagateUDs(const Stmt* s, UDs succ_UDs, const Stmt* succ_stmt, bo
|
|||
switch ( s->Tag() )
|
||||
{
|
||||
case STMT_LIST:
|
||||
{
|
||||
auto sl = s->AsStmtList();
|
||||
const auto& stmts = sl->Stmts();
|
||||
|
||||
for ( int i = stmts.length(); --i >= 0; )
|
||||
{
|
||||
auto sl = s->AsStmtList();
|
||||
const auto& stmts = sl->Stmts();
|
||||
auto s_i = stmts[i];
|
||||
|
||||
for ( int i = stmts.length(); --i >= 0; )
|
||||
{
|
||||
auto s_i = stmts[i];
|
||||
const Stmt* succ;
|
||||
|
||||
const Stmt* succ;
|
||||
|
||||
if ( i == stmts.length() - 1 )
|
||||
{ // Very last statement.
|
||||
succ = succ_stmt;
|
||||
if ( successor2.find(s) != successor2.end() )
|
||||
successor2[s_i] = successor2[s];
|
||||
}
|
||||
else
|
||||
succ = stmts[i + 1];
|
||||
|
||||
succ_UDs = PropagateUDs(s_i, succ_UDs, succ, second_pass);
|
||||
if ( i == stmts.length() - 1 )
|
||||
{ // Very last statement.
|
||||
succ = succ_stmt;
|
||||
if ( successor2.find(s) != successor2.end() )
|
||||
successor2[s_i] = successor2[s];
|
||||
}
|
||||
else
|
||||
succ = stmts[i + 1];
|
||||
|
||||
return UseUDs(s, succ_UDs);
|
||||
succ_UDs = PropagateUDs(s_i, succ_UDs, succ, second_pass);
|
||||
}
|
||||
|
||||
return UseUDs(s, succ_UDs);
|
||||
}
|
||||
|
||||
case STMT_CATCH_RETURN:
|
||||
{
|
||||
auto cr = s->AsCatchReturnStmt();
|
||||
auto block = cr->Block();
|
||||
{
|
||||
auto cr = s->AsCatchReturnStmt();
|
||||
auto block = cr->Block();
|
||||
|
||||
auto uds = PropagateUDs(block.get(), succ_UDs, succ_stmt, second_pass);
|
||||
auto uds = PropagateUDs(block.get(), succ_UDs, succ_stmt, second_pass);
|
||||
|
||||
return UseUDs(s, uds);
|
||||
}
|
||||
return UseUDs(s, uds);
|
||||
}
|
||||
|
||||
case STMT_NULL:
|
||||
case STMT_NEXT:
|
||||
|
@ -238,55 +238,55 @@ UDs UseDefs::PropagateUDs(const Stmt* s, UDs succ_UDs, const Stmt* succ_stmt, bo
|
|||
case STMT_ADD:
|
||||
case STMT_DELETE:
|
||||
case STMT_RETURN:
|
||||
{
|
||||
auto e = static_cast<const ExprStmt*>(s)->StmtExpr();
|
||||
{
|
||||
auto e = static_cast<const ExprStmt*>(s)->StmtExpr();
|
||||
|
||||
if ( e )
|
||||
return CreateExprUDs(s, e, succ_UDs);
|
||||
else
|
||||
return UseUDs(s, succ_UDs);
|
||||
}
|
||||
if ( e )
|
||||
return CreateExprUDs(s, e, succ_UDs);
|
||||
else
|
||||
return UseUDs(s, succ_UDs);
|
||||
}
|
||||
|
||||
case STMT_EXPR:
|
||||
{
|
||||
auto e = s->AsExprStmt()->StmtExpr();
|
||||
{
|
||||
auto e = s->AsExprStmt()->StmtExpr();
|
||||
|
||||
if ( e->Tag() != EXPR_ASSIGN )
|
||||
return CreateExprUDs(s, e, succ_UDs);
|
||||
if ( e->Tag() != EXPR_ASSIGN )
|
||||
return CreateExprUDs(s, e, succ_UDs);
|
||||
|
||||
// Change in use-defs as here we have a definition.
|
||||
auto a = e->AsAssignExpr();
|
||||
auto lhs_ref = a->GetOp1();
|
||||
// Change in use-defs as here we have a definition.
|
||||
auto a = e->AsAssignExpr();
|
||||
auto lhs_ref = a->GetOp1();
|
||||
|
||||
if ( lhs_ref->Tag() != EXPR_REF )
|
||||
// Since we're working on reduced form ...
|
||||
reporter->InternalError("lhs inconsistency in UseDefs::ExprUDs");
|
||||
if ( lhs_ref->Tag() != EXPR_REF )
|
||||
// Since we're working on reduced form ...
|
||||
reporter->InternalError("lhs inconsistency in UseDefs::ExprUDs");
|
||||
|
||||
auto lhs_var = lhs_ref->GetOp1();
|
||||
auto lhs_id = lhs_var->AsNameExpr()->Id();
|
||||
auto lhs_UDs = RemoveID(lhs_id, succ_UDs);
|
||||
auto rhs_UDs = ExprUDs(a->GetOp2().get());
|
||||
auto uds = UD_Union(lhs_UDs, rhs_UDs);
|
||||
auto lhs_var = lhs_ref->GetOp1();
|
||||
auto lhs_id = lhs_var->AsNameExpr()->Id();
|
||||
auto lhs_UDs = RemoveID(lhs_id, succ_UDs);
|
||||
auto rhs_UDs = ExprUDs(a->GetOp2().get());
|
||||
auto uds = UD_Union(lhs_UDs, rhs_UDs);
|
||||
|
||||
if ( ! second_pass )
|
||||
successor[s] = succ_stmt;
|
||||
if ( ! second_pass )
|
||||
successor[s] = succ_stmt;
|
||||
|
||||
return CreateUDs(s, uds);
|
||||
}
|
||||
return CreateUDs(s, uds);
|
||||
}
|
||||
|
||||
case STMT_IF:
|
||||
{
|
||||
auto i = s->AsIfStmt();
|
||||
auto cond = i->StmtExpr();
|
||||
{
|
||||
auto i = s->AsIfStmt();
|
||||
auto cond = i->StmtExpr();
|
||||
|
||||
auto cond_UDs = ExprUDs(cond);
|
||||
auto true_UDs = PropagateUDs(i->TrueBranch(), succ_UDs, succ_stmt, second_pass);
|
||||
auto false_UDs = PropagateUDs(i->FalseBranch(), succ_UDs, succ_stmt, second_pass);
|
||||
auto cond_UDs = ExprUDs(cond);
|
||||
auto true_UDs = PropagateUDs(i->TrueBranch(), succ_UDs, succ_stmt, second_pass);
|
||||
auto false_UDs = PropagateUDs(i->FalseBranch(), succ_UDs, succ_stmt, second_pass);
|
||||
|
||||
auto uds = CreateUDs(s, UD_Union(cond_UDs, true_UDs, false_UDs));
|
||||
auto uds = CreateUDs(s, UD_Union(cond_UDs, true_UDs, false_UDs));
|
||||
|
||||
return uds;
|
||||
}
|
||||
return uds;
|
||||
}
|
||||
|
||||
case STMT_INIT:
|
||||
if ( ! second_pass )
|
||||
|
@ -304,112 +304,112 @@ UDs UseDefs::PropagateUDs(const Stmt* s, UDs succ_UDs, const Stmt* succ_stmt, bo
|
|||
return UseUDs(s, succ_UDs);
|
||||
|
||||
case STMT_SWITCH:
|
||||
{
|
||||
auto sw_UDs = std::make_shared<UseDefSet>();
|
||||
|
||||
auto sw = s->AsSwitchStmt();
|
||||
auto cases = sw->Cases();
|
||||
|
||||
for ( const auto& c : *cases )
|
||||
{
|
||||
auto sw_UDs = std::make_shared<UseDefSet>();
|
||||
auto body = c->Body();
|
||||
auto uds = PropagateUDs(body, succ_UDs, succ_stmt, second_pass);
|
||||
|
||||
auto sw = s->AsSwitchStmt();
|
||||
auto cases = sw->Cases();
|
||||
|
||||
for ( const auto& c : *cases )
|
||||
auto exprs = c->ExprCases();
|
||||
if ( exprs )
|
||||
{
|
||||
auto body = c->Body();
|
||||
auto uds = PropagateUDs(body, succ_UDs, succ_stmt, second_pass);
|
||||
|
||||
auto exprs = c->ExprCases();
|
||||
if ( exprs )
|
||||
{
|
||||
auto e_UDs = ExprUDs(exprs);
|
||||
uds = UD_Union(uds, e_UDs);
|
||||
}
|
||||
|
||||
auto type_ids = c->TypeCases();
|
||||
if ( type_ids )
|
||||
for ( const auto& id : *type_ids )
|
||||
uds = RemoveID(id, uds);
|
||||
|
||||
FoldInUDs(sw_UDs, uds);
|
||||
auto e_UDs = ExprUDs(exprs);
|
||||
uds = UD_Union(uds, e_UDs);
|
||||
}
|
||||
|
||||
auto e_UDs = ExprUDs(sw->StmtExpr());
|
||||
auto type_ids = c->TypeCases();
|
||||
if ( type_ids )
|
||||
for ( const auto& id : *type_ids )
|
||||
uds = RemoveID(id, uds);
|
||||
|
||||
if ( sw->HasDefault() )
|
||||
FoldInUDs(sw_UDs, e_UDs);
|
||||
else
|
||||
// keep successor definitions in the mix
|
||||
FoldInUDs(sw_UDs, succ_UDs, e_UDs);
|
||||
|
||||
return CreateUDs(s, sw_UDs);
|
||||
FoldInUDs(sw_UDs, uds);
|
||||
}
|
||||
|
||||
auto e_UDs = ExprUDs(sw->StmtExpr());
|
||||
|
||||
if ( sw->HasDefault() )
|
||||
FoldInUDs(sw_UDs, e_UDs);
|
||||
else
|
||||
// keep successor definitions in the mix
|
||||
FoldInUDs(sw_UDs, succ_UDs, e_UDs);
|
||||
|
||||
return CreateUDs(s, sw_UDs);
|
||||
}
|
||||
|
||||
case STMT_FOR:
|
||||
{
|
||||
auto f = s->AsForStmt();
|
||||
auto body = f->LoopBody();
|
||||
{
|
||||
auto f = s->AsForStmt();
|
||||
auto body = f->LoopBody();
|
||||
|
||||
// The loop body has two potential successors, itself
|
||||
// and the successor of the entire "for" statement.
|
||||
successor2[body] = succ_stmt;
|
||||
auto body_UDs = PropagateUDs(body, succ_UDs, body, second_pass);
|
||||
// The loop body has two potential successors, itself
|
||||
// and the successor of the entire "for" statement.
|
||||
successor2[body] = succ_stmt;
|
||||
auto body_UDs = PropagateUDs(body, succ_UDs, body, second_pass);
|
||||
|
||||
auto e = f->LoopExpr();
|
||||
auto f_UDs = ExprUDs(e);
|
||||
FoldInUDs(f_UDs, body_UDs);
|
||||
auto e = f->LoopExpr();
|
||||
auto f_UDs = ExprUDs(e);
|
||||
FoldInUDs(f_UDs, body_UDs);
|
||||
|
||||
// Confluence: loop the top UDs back around to the bottom.
|
||||
auto bottom_UDs = UD_Union(f_UDs, succ_UDs);
|
||||
(void)PropagateUDs(body, bottom_UDs, body, true);
|
||||
// Confluence: loop the top UDs back around to the bottom.
|
||||
auto bottom_UDs = UD_Union(f_UDs, succ_UDs);
|
||||
(void)PropagateUDs(body, bottom_UDs, body, true);
|
||||
|
||||
auto ids = f->LoopVars();
|
||||
for ( const auto& id : *ids )
|
||||
RemoveUDFrom(f_UDs, id);
|
||||
auto ids = f->LoopVars();
|
||||
for ( const auto& id : *ids )
|
||||
RemoveUDFrom(f_UDs, id);
|
||||
|
||||
auto val_var = f->ValueVar();
|
||||
if ( val_var )
|
||||
RemoveUDFrom(f_UDs, val_var.get());
|
||||
auto val_var = f->ValueVar();
|
||||
if ( val_var )
|
||||
RemoveUDFrom(f_UDs, val_var.get());
|
||||
|
||||
// The loop might not execute at all.
|
||||
FoldInUDs(f_UDs, succ_UDs);
|
||||
// The loop might not execute at all.
|
||||
FoldInUDs(f_UDs, succ_UDs);
|
||||
|
||||
return CreateUDs(s, f_UDs);
|
||||
}
|
||||
return CreateUDs(s, f_UDs);
|
||||
}
|
||||
|
||||
case STMT_WHILE:
|
||||
{
|
||||
auto w = s->AsWhileStmt();
|
||||
auto body = w->Body();
|
||||
auto cond_stmt = w->CondPredStmt();
|
||||
|
||||
// See note above for STMT_FOR regarding propagating
|
||||
// around the loop.
|
||||
auto succ = cond_stmt ? cond_stmt : body;
|
||||
successor2[body.get()] = succ_stmt;
|
||||
auto body_UDs = PropagateUDs(body.get(), succ_UDs, succ.get(), second_pass);
|
||||
|
||||
const auto& cond = w->Condition();
|
||||
auto w_UDs = UD_Union(ExprUDs(cond.get()), body_UDs);
|
||||
FoldInUDs(w_UDs, body_UDs);
|
||||
|
||||
if ( cond_stmt )
|
||||
{
|
||||
auto w = s->AsWhileStmt();
|
||||
auto body = w->Body();
|
||||
auto cond_stmt = w->CondPredStmt();
|
||||
// Create a successor for the cond_stmt
|
||||
// that has the correct UDs associated with it.
|
||||
const auto& c_as_s = w->ConditionAsStmt();
|
||||
auto c_as_s_UDs = std::make_shared<UseDefSet>(w_UDs);
|
||||
CreateUDs(c_as_s.get(), c_as_s_UDs);
|
||||
|
||||
// See note above for STMT_FOR regarding propagating
|
||||
// around the loop.
|
||||
auto succ = cond_stmt ? cond_stmt : body;
|
||||
successor2[body.get()] = succ_stmt;
|
||||
auto body_UDs = PropagateUDs(body.get(), succ_UDs, succ.get(), second_pass);
|
||||
|
||||
const auto& cond = w->Condition();
|
||||
auto w_UDs = UD_Union(ExprUDs(cond.get()), body_UDs);
|
||||
FoldInUDs(w_UDs, body_UDs);
|
||||
|
||||
if ( cond_stmt )
|
||||
{
|
||||
// Create a successor for the cond_stmt
|
||||
// that has the correct UDs associated with it.
|
||||
const auto& c_as_s = w->ConditionAsStmt();
|
||||
auto c_as_s_UDs = std::make_shared<UseDefSet>(w_UDs);
|
||||
CreateUDs(c_as_s.get(), c_as_s_UDs);
|
||||
|
||||
w_UDs = PropagateUDs(cond_stmt, w_UDs, c_as_s, second_pass);
|
||||
}
|
||||
|
||||
// Confluence: loop the top UDs back around to the bottom.
|
||||
auto bottom_UDs = UD_Union(w_UDs, succ_UDs);
|
||||
(void)PropagateUDs(body, bottom_UDs, succ, true);
|
||||
|
||||
// The loop might not execute at all.
|
||||
FoldInUDs(w_UDs, succ_UDs);
|
||||
|
||||
return CreateUDs(s, w_UDs);
|
||||
w_UDs = PropagateUDs(cond_stmt, w_UDs, c_as_s, second_pass);
|
||||
}
|
||||
|
||||
// Confluence: loop the top UDs back around to the bottom.
|
||||
auto bottom_UDs = UD_Union(w_UDs, succ_UDs);
|
||||
(void)PropagateUDs(body, bottom_UDs, succ, true);
|
||||
|
||||
// The loop might not execute at all.
|
||||
FoldInUDs(w_UDs, succ_UDs);
|
||||
|
||||
return CreateUDs(s, w_UDs);
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("non-reduced statement in use-def analysis");
|
||||
}
|
||||
|
@ -454,12 +454,12 @@ UDs UseDefs::ExprUDs(const Expr* e)
|
|||
break;
|
||||
|
||||
case EXPR_FIELD_LHS_ASSIGN:
|
||||
{
|
||||
AddInExprUDs(uds, e->GetOp1().get());
|
||||
auto rhs_UDs = ExprUDs(e->GetOp2().get());
|
||||
uds = UD_Union(uds, rhs_UDs);
|
||||
break;
|
||||
}
|
||||
{
|
||||
AddInExprUDs(uds, e->GetOp1().get());
|
||||
auto rhs_UDs = ExprUDs(e->GetOp2().get());
|
||||
uds = UD_Union(uds, rhs_UDs);
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_INCR:
|
||||
case EXPR_DECR:
|
||||
|
@ -467,41 +467,41 @@ UDs UseDefs::ExprUDs(const Expr* e)
|
|||
break;
|
||||
|
||||
case EXPR_RECORD_CONSTRUCTOR:
|
||||
{
|
||||
auto r = static_cast<const RecordConstructorExpr*>(e);
|
||||
AddInExprUDs(uds, r->Op().get());
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto r = static_cast<const RecordConstructorExpr*>(e);
|
||||
AddInExprUDs(uds, r->Op().get());
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_CONST:
|
||||
break;
|
||||
|
||||
case EXPR_LAMBDA:
|
||||
{
|
||||
auto l = static_cast<const LambdaExpr*>(e);
|
||||
auto ids = l->OuterIDs();
|
||||
{
|
||||
auto l = static_cast<const LambdaExpr*>(e);
|
||||
auto ids = l->OuterIDs();
|
||||
|
||||
for ( const auto& id : ids )
|
||||
AddID(uds, id);
|
||||
break;
|
||||
}
|
||||
for ( const auto& id : ids )
|
||||
AddID(uds, id);
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_CALL:
|
||||
{
|
||||
auto c = e->AsCallExpr();
|
||||
AddInExprUDs(uds, c->Func());
|
||||
AddInExprUDs(uds, c->Args());
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto c = e->AsCallExpr();
|
||||
AddInExprUDs(uds, c->Func());
|
||||
AddInExprUDs(uds, c->Args());
|
||||
break;
|
||||
}
|
||||
|
||||
case EXPR_LIST:
|
||||
{
|
||||
auto l = e->AsListExpr();
|
||||
for ( const auto& l_e : l->Exprs() )
|
||||
AddInExprUDs(uds, l_e);
|
||||
{
|
||||
auto l = e->AsListExpr();
|
||||
for ( const auto& l_e : l->Exprs() )
|
||||
AddInExprUDs(uds, l_e);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
auto op1 = e->GetOp1();
|
||||
|
@ -532,11 +532,11 @@ void UseDefs::AddInExprUDs(UDs uds, const Expr* e)
|
|||
break;
|
||||
|
||||
case EXPR_LIST:
|
||||
{
|
||||
auto l = e->AsListExpr();
|
||||
for ( const auto& l_e : l->Exprs() )
|
||||
AddInExprUDs(uds, l_e);
|
||||
}
|
||||
{
|
||||
auto l = e->AsListExpr();
|
||||
for ( const auto& l_e : l->Exprs() )
|
||||
AddInExprUDs(uds, l_e);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXPR_EVENT:
|
||||
|
|
|
@ -362,43 +362,43 @@ void ZAMCompiler::ComputeFrameLifetimes()
|
|||
{
|
||||
case OP_NEXT_TABLE_ITER_VV:
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_VVV:
|
||||
{
|
||||
// These assign to an arbitrary long list of variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
auto depth = inst->loop_depth;
|
||||
|
||||
for ( auto v : iter_vars )
|
||||
{
|
||||
// These assign to an arbitrary long list of variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
auto depth = inst->loop_depth;
|
||||
CheckSlotAssignment(v, inst);
|
||||
|
||||
for ( auto v : iter_vars )
|
||||
{
|
||||
CheckSlotAssignment(v, inst);
|
||||
|
||||
// Also mark it as usage throughout the
|
||||
// loop. Otherwise, we risk pruning the
|
||||
// variable if it happens to not be used
|
||||
// (which will mess up the iteration logic)
|
||||
// or doubling it up with some other value
|
||||
// inside the loop (which will fail when
|
||||
// the loop var has memory management
|
||||
// associated with it).
|
||||
ExtendLifetime(v, EndOfLoop(inst, depth));
|
||||
}
|
||||
|
||||
// No need to check the additional "var" associated
|
||||
// with OP_NEXT_TABLE_ITER_VAL_VAR_VVV as that's
|
||||
// a slot-1 assignment. However, similar to other
|
||||
// loop variables, mark this as a usage.
|
||||
if ( inst->op == OP_NEXT_TABLE_ITER_VAL_VAR_VVV )
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
// Also mark it as usage throughout the
|
||||
// loop. Otherwise, we risk pruning the
|
||||
// variable if it happens to not be used
|
||||
// (which will mess up the iteration logic)
|
||||
// or doubling it up with some other value
|
||||
// inside the loop (which will fail when
|
||||
// the loop var has memory management
|
||||
// associated with it).
|
||||
ExtendLifetime(v, EndOfLoop(inst, depth));
|
||||
}
|
||||
|
||||
// No need to check the additional "var" associated
|
||||
// with OP_NEXT_TABLE_ITER_VAL_VAR_VVV as that's
|
||||
// a slot-1 assignment. However, similar to other
|
||||
// loop variables, mark this as a usage.
|
||||
if ( inst->op == OP_NEXT_TABLE_ITER_VAL_VAR_VVV )
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_NEXT_TABLE_ITER_NO_VARS_VV:
|
||||
break;
|
||||
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_NO_VARS_VVV:
|
||||
{
|
||||
auto depth = inst->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
{
|
||||
auto depth = inst->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(inst, depth));
|
||||
}
|
||||
break;
|
||||
|
||||
case OP_NEXT_VECTOR_ITER_VVV:
|
||||
|
@ -417,30 +417,30 @@ void ZAMCompiler::ComputeFrameLifetimes()
|
|||
case OP_INIT_TABLE_LOOP_VV:
|
||||
case OP_INIT_VECTOR_LOOP_VV:
|
||||
case OP_INIT_STRING_LOOP_VV:
|
||||
{
|
||||
// For all of these, the scope of the aggregate being
|
||||
// looped over is the entire loop, even if it doesn't
|
||||
// directly appear in it, and not just the initializer.
|
||||
// For all three, the aggregate is in v1.
|
||||
ASSERT(i < insts1.size() - 1);
|
||||
auto succ = insts1[i + 1];
|
||||
ASSERT(succ->live);
|
||||
auto depth = succ->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(succ, depth));
|
||||
{
|
||||
// For all of these, the scope of the aggregate being
|
||||
// looped over is the entire loop, even if it doesn't
|
||||
// directly appear in it, and not just the initializer.
|
||||
// For all three, the aggregate is in v1.
|
||||
ASSERT(i < insts1.size() - 1);
|
||||
auto succ = insts1[i + 1];
|
||||
ASSERT(succ->live);
|
||||
auto depth = succ->loop_depth;
|
||||
ExtendLifetime(inst->v1, EndOfLoop(succ, depth));
|
||||
|
||||
// Important: we skip the usual UsesSlots analysis
|
||||
// below since we've already set it, and don't want
|
||||
// to perturb ExtendLifetime's consistency check.
|
||||
continue;
|
||||
}
|
||||
// Important: we skip the usual UsesSlots analysis
|
||||
// below since we've already set it, and don't want
|
||||
// to perturb ExtendLifetime's consistency check.
|
||||
continue;
|
||||
}
|
||||
|
||||
case OP_STORE_GLOBAL_V:
|
||||
{
|
||||
// Use of the global goes to here.
|
||||
auto slot = frame_layout1[globalsI[inst->v1].id.get()];
|
||||
ExtendLifetime(slot, EndOfLoop(inst, 1));
|
||||
break;
|
||||
}
|
||||
{
|
||||
// Use of the global goes to here.
|
||||
auto slot = frame_layout1[globalsI[inst->v1].id.get()];
|
||||
ExtendLifetime(slot, EndOfLoop(inst, 1));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// Look for slots in auxiliary information.
|
||||
|
@ -559,15 +559,15 @@ void ZAMCompiler::ReMapFrame()
|
|||
{
|
||||
case OP_NEXT_TABLE_ITER_VV:
|
||||
case OP_NEXT_TABLE_ITER_VAL_VAR_VVV:
|
||||
{
|
||||
// Rewrite iteration variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
for ( auto& v : iter_vars )
|
||||
{
|
||||
// Rewrite iteration variables.
|
||||
auto& iter_vars = inst->aux->loop_vars;
|
||||
for ( auto& v : iter_vars )
|
||||
{
|
||||
ASSERT(v >= 0 && v < n1_slots);
|
||||
v = frame1_to_frame2[v];
|
||||
}
|
||||
ASSERT(v >= 0 && v < n1_slots);
|
||||
v = frame1_to_frame2[v];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -24,32 +24,32 @@ const ZAMStmt ZAMCompiler::CompileExpr(const Expr* e)
|
|||
return CompileAssignExpr(static_cast<const AssignExpr*>(e));
|
||||
|
||||
case EXPR_INDEX_ASSIGN:
|
||||
{
|
||||
auto iae = static_cast<const IndexAssignExpr*>(e);
|
||||
auto t = iae->GetOp1()->GetType()->Tag();
|
||||
if ( t == TYPE_VECTOR )
|
||||
return AssignVecElems(iae);
|
||||
{
|
||||
auto iae = static_cast<const IndexAssignExpr*>(e);
|
||||
auto t = iae->GetOp1()->GetType()->Tag();
|
||||
if ( t == TYPE_VECTOR )
|
||||
return AssignVecElems(iae);
|
||||
|
||||
ASSERT(t == TYPE_TABLE);
|
||||
return AssignTableElem(iae);
|
||||
}
|
||||
ASSERT(t == TYPE_TABLE);
|
||||
return AssignTableElem(iae);
|
||||
}
|
||||
|
||||
case EXPR_FIELD_LHS_ASSIGN:
|
||||
{
|
||||
auto flhs = static_cast<const FieldLHSAssignExpr*>(e);
|
||||
return CompileFieldLHSAssignExpr(flhs);
|
||||
}
|
||||
{
|
||||
auto flhs = static_cast<const FieldLHSAssignExpr*>(e);
|
||||
return CompileFieldLHSAssignExpr(flhs);
|
||||
}
|
||||
|
||||
case EXPR_SCHEDULE:
|
||||
return CompileScheduleExpr(static_cast<const ScheduleExpr*>(e));
|
||||
|
||||
case EXPR_EVENT:
|
||||
{
|
||||
auto ee = static_cast<const EventExpr*>(e);
|
||||
auto h = ee->Handler().Ptr();
|
||||
auto args = ee->Args();
|
||||
return EventHL(h, args);
|
||||
}
|
||||
{
|
||||
auto ee = static_cast<const EventExpr*>(e);
|
||||
auto h = ee->Handler().Ptr();
|
||||
auto args = ee->Args();
|
||||
return EventHL(h, args);
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad statement type in ZAMCompile::CompileExpr");
|
||||
|
@ -1111,31 +1111,31 @@ const ZAMStmt ZAMCompiler::ArithCoerce(const NameExpr* n, const Expr* e)
|
|||
switch ( targ_it )
|
||||
{
|
||||
case TYPE_INTERNAL_DOUBLE:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_DI_VEC_VV : OP_COERCE_DI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_DU_VEC_VV : OP_COERCE_DU_VV;
|
||||
break;
|
||||
}
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_DI_VEC_VV : OP_COERCE_DI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_DU_VEC_VV : OP_COERCE_DU_VV;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_INT:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_UNSIGNED )
|
||||
a = nt_is_vec ? OP_COERCE_IU_VEC_VV : OP_COERCE_IU_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_ID_VEC_VV : OP_COERCE_ID_VV;
|
||||
break;
|
||||
}
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_UNSIGNED )
|
||||
a = nt_is_vec ? OP_COERCE_IU_VEC_VV : OP_COERCE_IU_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_ID_VEC_VV : OP_COERCE_ID_VV;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_UNSIGNED:
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_UI_VEC_VV : OP_COERCE_UI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_UD_VEC_VV : OP_COERCE_UD_VV;
|
||||
break;
|
||||
}
|
||||
{
|
||||
if ( op_it == TYPE_INTERNAL_INT )
|
||||
a = nt_is_vec ? OP_COERCE_UI_VEC_VV : OP_COERCE_UI_VV;
|
||||
else
|
||||
a = nt_is_vec ? OP_COERCE_UD_VEC_VV : OP_COERCE_UD_VV;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad target internal type in coercion");
|
||||
|
|
|
@ -81,11 +81,11 @@ string find_type_accessor(ZAM_ExprType et)
|
|||
return "re_val";
|
||||
|
||||
default:
|
||||
{
|
||||
string acc = find_type_info(et).accessor;
|
||||
transform(acc.begin(), acc.end(), acc.begin(), ::tolower);
|
||||
return acc + "_val";
|
||||
}
|
||||
{
|
||||
string acc = find_type_info(et).accessor;
|
||||
transform(acc.begin(), acc.end(), acc.begin(), ::tolower);
|
||||
return acc + "_val";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,11 +36,11 @@ const ZAMStmt ZAMCompiler::CompileStmt(const Stmt* s)
|
|||
return CompileDel(static_cast<const DelStmt*>(s));
|
||||
|
||||
case STMT_EVENT:
|
||||
{
|
||||
auto es = static_cast<const EventStmt*>(s);
|
||||
auto e = static_cast<const EventExpr*>(es->StmtExpr());
|
||||
return CompileExpr(e);
|
||||
}
|
||||
{
|
||||
auto es = static_cast<const EventStmt*>(s);
|
||||
auto e = static_cast<const EventExpr*>(es->StmtExpr());
|
||||
return CompileExpr(e);
|
||||
}
|
||||
|
||||
case STMT_WHILE:
|
||||
return CompileWhile(static_cast<const WhileStmt*>(s));
|
||||
|
@ -67,12 +67,12 @@ const ZAMStmt ZAMCompiler::CompileStmt(const Stmt* s)
|
|||
return CompileWhen(static_cast<const WhenStmt*>(s));
|
||||
|
||||
case STMT_CHECK_ANY_LEN:
|
||||
{
|
||||
auto cs = static_cast<const CheckAnyLenStmt*>(s);
|
||||
auto n = cs->StmtExpr()->AsNameExpr();
|
||||
auto expected_len = cs->ExpectedLen();
|
||||
return CheckAnyLenVi(n, expected_len);
|
||||
}
|
||||
{
|
||||
auto cs = static_cast<const CheckAnyLenStmt*>(s);
|
||||
auto n = cs->StmtExpr()->AsNameExpr();
|
||||
auto expected_len = cs->ExpectedLen();
|
||||
return CheckAnyLenVi(n, expected_len);
|
||||
}
|
||||
|
||||
case STMT_NEXT:
|
||||
return CompileNext();
|
||||
|
@ -520,29 +520,29 @@ const ZAMStmt ZAMCompiler::ValueSwitch(const SwitchStmt* sw, const NameExpr* v,
|
|||
break;
|
||||
|
||||
case TYPE_INTERNAL_STRING:
|
||||
{
|
||||
// This leaks, but only statically so not worth
|
||||
// tracking the value for ultimate deletion.
|
||||
auto sv = cv->AsString()->Render();
|
||||
std::string s(sv);
|
||||
new_str_cases[s] = case_body_start;
|
||||
delete[] sv;
|
||||
break;
|
||||
}
|
||||
{
|
||||
// This leaks, but only statically so not worth
|
||||
// tracking the value for ultimate deletion.
|
||||
auto sv = cv->AsString()->Render();
|
||||
std::string s(sv);
|
||||
new_str_cases[s] = case_body_start;
|
||||
delete[] sv;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_ADDR:
|
||||
{
|
||||
auto a = cv->AsAddr().AsString();
|
||||
new_str_cases[a] = case_body_start;
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto a = cv->AsAddr().AsString();
|
||||
new_str_cases[a] = case_body_start;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INTERNAL_SUBNET:
|
||||
{
|
||||
auto n = cv->AsSubNet().AsString();
|
||||
new_str_cases[n] = case_body_start;
|
||||
break;
|
||||
}
|
||||
{
|
||||
auto n = cv->AsSubNet().AsString();
|
||||
new_str_cases[n] = case_body_start;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("bad recovered type when compiling switch");
|
||||
|
|
|
@ -144,23 +144,23 @@ bool Value::IsCompatibleType(Type* t, bool atomic_only)
|
|||
return ! atomic_only;
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
|
||||
if ( ! t->IsSet() )
|
||||
return false;
|
||||
if ( ! t->IsSet() )
|
||||
return false;
|
||||
|
||||
return IsCompatibleType(t->AsSetType()->GetIndices()->GetPureType().get(), true);
|
||||
}
|
||||
return IsCompatibleType(t->AsSetType()->GetIndices()->GetPureType().get(), true);
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
{
|
||||
if ( atomic_only )
|
||||
return false;
|
||||
|
||||
return IsCompatibleType(t->AsVectorType()->Yield().get(), true);
|
||||
}
|
||||
return IsCompatibleType(t->AsVectorType()->Yield().get(), true);
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -193,81 +193,81 @@ bool Value::Read(detail::SerializationFormat* fmt)
|
|||
return fmt->Read(&val.uint_val, "uint");
|
||||
|
||||
case TYPE_PORT:
|
||||
{
|
||||
int proto;
|
||||
if ( ! (fmt->Read(&val.port_val.port, "port") && fmt->Read(&proto, "proto")) )
|
||||
{
|
||||
int proto;
|
||||
if ( ! (fmt->Read(&val.port_val.port, "port") && fmt->Read(&proto, "proto")) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ( proto )
|
||||
{
|
||||
case 0:
|
||||
val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
break;
|
||||
case 1:
|
||||
val.port_val.proto = TRANSPORT_TCP;
|
||||
break;
|
||||
case 2:
|
||||
val.port_val.proto = TRANSPORT_UDP;
|
||||
break;
|
||||
case 3:
|
||||
val.port_val.proto = TRANSPORT_ICMP;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ( proto )
|
||||
{
|
||||
case 0:
|
||||
val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
break;
|
||||
case 1:
|
||||
val.port_val.proto = TRANSPORT_TCP;
|
||||
break;
|
||||
case 2:
|
||||
val.port_val.proto = TRANSPORT_UDP;
|
||||
break;
|
||||
case 3:
|
||||
val.port_val.proto = TRANSPORT_ICMP;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
char family;
|
||||
|
||||
if ( ! fmt->Read(&family, "addr-family") )
|
||||
return false;
|
||||
|
||||
switch ( family )
|
||||
{
|
||||
char family;
|
||||
case 4:
|
||||
val.addr_val.family = IPv4;
|
||||
return fmt->Read(&val.addr_val.in.in4, "addr-in4");
|
||||
|
||||
if ( ! fmt->Read(&family, "addr-family") )
|
||||
return false;
|
||||
|
||||
switch ( family )
|
||||
{
|
||||
case 4:
|
||||
val.addr_val.family = IPv4;
|
||||
return fmt->Read(&val.addr_val.in.in4, "addr-in4");
|
||||
|
||||
case 6:
|
||||
val.addr_val.family = IPv6;
|
||||
return fmt->Read(&val.addr_val.in.in6, "addr-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
case 6:
|
||||
val.addr_val.family = IPv6;
|
||||
return fmt->Read(&val.addr_val.in.in6, "addr-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
}
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
char length;
|
||||
char family;
|
||||
|
||||
if ( ! (fmt->Read(&length, "subnet-len") && fmt->Read(&family, "subnet-family")) )
|
||||
return false;
|
||||
|
||||
switch ( family )
|
||||
{
|
||||
char length;
|
||||
char family;
|
||||
case 4:
|
||||
val.subnet_val.length = (uint8_t)length;
|
||||
val.subnet_val.prefix.family = IPv4;
|
||||
return fmt->Read(&val.subnet_val.prefix.in.in4, "subnet-in4");
|
||||
|
||||
if ( ! (fmt->Read(&length, "subnet-len") && fmt->Read(&family, "subnet-family")) )
|
||||
return false;
|
||||
|
||||
switch ( family )
|
||||
{
|
||||
case 4:
|
||||
val.subnet_val.length = (uint8_t)length;
|
||||
val.subnet_val.prefix.family = IPv4;
|
||||
return fmt->Read(&val.subnet_val.prefix.in.in4, "subnet-in4");
|
||||
|
||||
case 6:
|
||||
val.subnet_val.length = (uint8_t)length;
|
||||
val.subnet_val.prefix.family = IPv6;
|
||||
return fmt->Read(&val.subnet_val.prefix.in.in6, "subnet-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
case 6:
|
||||
val.subnet_val.length = (uint8_t)length;
|
||||
val.subnet_val.prefix.family = IPv6;
|
||||
return fmt->Read(&val.subnet_val.prefix.in.in6, "subnet-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
}
|
||||
|
||||
case TYPE_DOUBLE:
|
||||
case TYPE_TIME:
|
||||
case TYPE_INTERVAL:
|
||||
|
@ -280,41 +280,41 @@ bool Value::Read(detail::SerializationFormat* fmt)
|
|||
return fmt->Read(&val.string_val.data, &val.string_val.length, "string");
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
if ( ! fmt->Read(&val.set_val.size, "set_size") )
|
||||
return false;
|
||||
|
||||
val.set_val.vals = new Value*[val.set_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < val.set_val.size; ++i )
|
||||
{
|
||||
if ( ! fmt->Read(&val.set_val.size, "set_size") )
|
||||
val.set_val.vals[i] = new Value;
|
||||
|
||||
if ( ! val.set_val.vals[i]->Read(fmt) )
|
||||
return false;
|
||||
|
||||
val.set_val.vals = new Value*[val.set_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < val.set_val.size; ++i )
|
||||
{
|
||||
val.set_val.vals[i] = new Value;
|
||||
|
||||
if ( ! val.set_val.vals[i]->Read(fmt) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
if ( ! fmt->Read(&val.vector_val.size, "vector_size") )
|
||||
return false;
|
||||
|
||||
val.vector_val.vals = new Value*[val.vector_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < val.vector_val.size; ++i )
|
||||
{
|
||||
if ( ! fmt->Read(&val.vector_val.size, "vector_size") )
|
||||
val.vector_val.vals[i] = new Value;
|
||||
|
||||
if ( ! val.vector_val.vals[i]->Read(fmt) )
|
||||
return false;
|
||||
|
||||
val.vector_val.vals = new Value*[val.vector_val.size];
|
||||
|
||||
for ( bro_int_t i = 0; i < val.vector_val.size; ++i )
|
||||
{
|
||||
val.vector_val.vals[i] = new Value;
|
||||
|
||||
if ( ! val.vector_val.vals[i]->Read(fmt) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("unsupported type %s in Value::Read", type_name(type));
|
||||
}
|
||||
|
@ -344,42 +344,42 @@ bool Value::Write(detail::SerializationFormat* fmt) const
|
|||
return fmt->Write(val.port_val.port, "port") && fmt->Write(val.port_val.proto, "proto");
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
switch ( val.addr_val.family )
|
||||
{
|
||||
switch ( val.addr_val.family )
|
||||
{
|
||||
case IPv4:
|
||||
return fmt->Write((char)4, "addr-family") &&
|
||||
fmt->Write(val.addr_val.in.in4, "addr-in4");
|
||||
case IPv4:
|
||||
return fmt->Write((char)4, "addr-family") &&
|
||||
fmt->Write(val.addr_val.in.in4, "addr-in4");
|
||||
|
||||
case IPv6:
|
||||
return fmt->Write((char)6, "addr-family") &&
|
||||
fmt->Write(val.addr_val.in.in6, "addr-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
case IPv6:
|
||||
return fmt->Write((char)6, "addr-family") &&
|
||||
fmt->Write(val.addr_val.in.in6, "addr-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
}
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
if ( ! fmt->Write((char)val.subnet_val.length, "subnet-length") )
|
||||
return false;
|
||||
|
||||
switch ( val.subnet_val.prefix.family )
|
||||
{
|
||||
if ( ! fmt->Write((char)val.subnet_val.length, "subnet-length") )
|
||||
return false;
|
||||
case IPv4:
|
||||
return fmt->Write((char)4, "subnet-family") &&
|
||||
fmt->Write(val.subnet_val.prefix.in.in4, "subnet-in4");
|
||||
|
||||
switch ( val.subnet_val.prefix.family )
|
||||
{
|
||||
case IPv4:
|
||||
return fmt->Write((char)4, "subnet-family") &&
|
||||
fmt->Write(val.subnet_val.prefix.in.in4, "subnet-in4");
|
||||
|
||||
case IPv6:
|
||||
return fmt->Write((char)6, "subnet-family") &&
|
||||
fmt->Write(val.subnet_val.prefix.in.in6, "subnet-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
case IPv6:
|
||||
return fmt->Write((char)6, "subnet-family") &&
|
||||
fmt->Write(val.subnet_val.prefix.in.in6, "subnet-in6");
|
||||
}
|
||||
|
||||
// Can't be reached.
|
||||
abort();
|
||||
}
|
||||
|
||||
case TYPE_DOUBLE:
|
||||
case TYPE_TIME:
|
||||
case TYPE_INTERVAL:
|
||||
|
@ -392,33 +392,33 @@ bool Value::Write(detail::SerializationFormat* fmt) const
|
|||
return fmt->Write(val.string_val.data, val.string_val.length, "string");
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
if ( ! fmt->Write(val.set_val.size, "set_size") )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < val.set_val.size; ++i )
|
||||
{
|
||||
if ( ! fmt->Write(val.set_val.size, "set_size") )
|
||||
if ( ! val.set_val.vals[i]->Write(fmt) )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < val.set_val.size; ++i )
|
||||
{
|
||||
if ( ! val.set_val.vals[i]->Write(fmt) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
if ( ! fmt->Write(val.vector_val.size, "vector_size") )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < val.vector_val.size; ++i )
|
||||
{
|
||||
if ( ! fmt->Write(val.vector_val.size, "vector_size") )
|
||||
if ( ! val.vector_val.vals[i]->Write(fmt) )
|
||||
return false;
|
||||
|
||||
for ( int i = 0; i < val.vector_val.size; ++i )
|
||||
{
|
||||
if ( ! val.vector_val.vals[i]->Write(fmt) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("unsupported type %s in Value::Write", type_name(type));
|
||||
}
|
||||
|
@ -464,204 +464,204 @@ Val* Value::ValueToVal(const std::string& source, const Value* val, bool& have_e
|
|||
return new IntervalVal(val->val.double_val);
|
||||
|
||||
case TYPE_STRING:
|
||||
{
|
||||
auto* s = new String((const u_char*)val->val.string_val.data,
|
||||
val->val.string_val.length, true);
|
||||
return new StringVal(s);
|
||||
}
|
||||
{
|
||||
auto* s = new String((const u_char*)val->val.string_val.data,
|
||||
val->val.string_val.length, true);
|
||||
return new StringVal(s);
|
||||
}
|
||||
|
||||
case TYPE_PORT:
|
||||
return val_mgr->Port(val->val.port_val.port, val->val.port_val.proto)->Ref();
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.addr_val.family )
|
||||
{
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.addr_val.in.in4);
|
||||
break;
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.addr_val.in.in4);
|
||||
break;
|
||||
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.addr_val.in.in6);
|
||||
break;
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.addr_val.in.in6);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* addrval = new AddrVal(*addr);
|
||||
delete addr;
|
||||
return addrval;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* addrval = new AddrVal(*addr);
|
||||
delete addr;
|
||||
return addrval;
|
||||
}
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
IPAddr* addr = nullptr;
|
||||
switch ( val->val.subnet_val.prefix.family )
|
||||
{
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in4);
|
||||
break;
|
||||
case IPv4:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in4);
|
||||
break;
|
||||
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in6);
|
||||
break;
|
||||
case IPv6:
|
||||
addr = new IPAddr(val->val.subnet_val.prefix.in.in6);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* subnetval = new SubNetVal(*addr, val->val.subnet_val.length);
|
||||
delete addr;
|
||||
return subnetval;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto* subnetval = new SubNetVal(*addr, val->val.subnet_val.length);
|
||||
delete addr;
|
||||
return subnetval;
|
||||
}
|
||||
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
auto* re = new RE_Matcher(val->val.pattern_text_val);
|
||||
re->Compile();
|
||||
return new PatternVal(re);
|
||||
}
|
||||
{
|
||||
auto* re = new RE_Matcher(val->val.pattern_text_val);
|
||||
re->Compile();
|
||||
return new PatternVal(re);
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
TypeListPtr set_index;
|
||||
if ( val->val.set_val.size == 0 &&
|
||||
(val->subtype == TYPE_VOID || val->subtype == TYPE_ENUM) )
|
||||
// don't know type - unspecified table.
|
||||
set_index = make_intrusive<TypeList>();
|
||||
else
|
||||
{
|
||||
TypeListPtr set_index;
|
||||
if ( val->val.set_val.size == 0 &&
|
||||
(val->subtype == TYPE_VOID || val->subtype == TYPE_ENUM) )
|
||||
// don't know type - unspecified table.
|
||||
set_index = make_intrusive<TypeList>();
|
||||
else
|
||||
// all entries have to have the same type...
|
||||
TypeTag stag = val->subtype;
|
||||
if ( stag == TYPE_VOID )
|
||||
stag = val->val.set_val.vals[0]->type;
|
||||
|
||||
TypePtr index_type;
|
||||
|
||||
if ( stag == TYPE_ENUM )
|
||||
{
|
||||
// all entries have to have the same type...
|
||||
TypeTag stag = val->subtype;
|
||||
if ( stag == TYPE_VOID )
|
||||
stag = val->val.set_val.vals[0]->type;
|
||||
// Enums are not a base-type, so need to look it up.
|
||||
const auto& sv = val->val.set_val.vals[0]->val.string_val;
|
||||
std::string enum_name(sv.data, sv.length);
|
||||
const auto& enum_id = detail::global_scope()->Find(enum_name);
|
||||
|
||||
TypePtr index_type;
|
||||
|
||||
if ( stag == TYPE_ENUM )
|
||||
if ( ! enum_id )
|
||||
{
|
||||
// Enums are not a base-type, so need to look it up.
|
||||
const auto& sv = val->val.set_val.vals[0]->val.string_val;
|
||||
std::string enum_name(sv.data, sv.length);
|
||||
const auto& enum_id = detail::global_scope()->Find(enum_name);
|
||||
reporter->Warning("Value '%s' of source '%s' is not a valid enum.",
|
||||
enum_name.data(), source.c_str());
|
||||
|
||||
if ( ! enum_id )
|
||||
{
|
||||
reporter->Warning("Value '%s' of source '%s' is not a valid enum.",
|
||||
enum_name.data(), source.c_str());
|
||||
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
index_type = enum_id->GetType();
|
||||
}
|
||||
else
|
||||
index_type = base_type(stag);
|
||||
|
||||
set_index = make_intrusive<TypeList>(index_type);
|
||||
set_index->Append(std::move(index_type));
|
||||
}
|
||||
|
||||
auto s = make_intrusive<SetType>(std::move(set_index), nullptr);
|
||||
auto t = make_intrusive<TableVal>(std::move(s));
|
||||
for ( int j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
Val* assignval = ValueToVal(source, val->val.set_val.vals[j], have_error);
|
||||
if ( have_error )
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t->Assign({AdoptRef{}, assignval}, nullptr);
|
||||
index_type = enum_id->GetType();
|
||||
}
|
||||
else
|
||||
index_type = base_type(stag);
|
||||
|
||||
return t.release();
|
||||
set_index = make_intrusive<TypeList>(index_type);
|
||||
set_index->Append(std::move(index_type));
|
||||
}
|
||||
|
||||
auto s = make_intrusive<SetType>(std::move(set_index), nullptr);
|
||||
auto t = make_intrusive<TableVal>(std::move(s));
|
||||
for ( int j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
Val* assignval = ValueToVal(source, val->val.set_val.vals[j], have_error);
|
||||
if ( have_error )
|
||||
return nullptr;
|
||||
|
||||
t->Assign({AdoptRef{}, assignval}, nullptr);
|
||||
}
|
||||
|
||||
return t.release();
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
TypePtr type;
|
||||
|
||||
if ( val->val.vector_val.size == 0 &&
|
||||
(val->subtype == TYPE_VOID || val->subtype == TYPE_ENUM) )
|
||||
// don't know type - unspecified table.
|
||||
type = base_type(TYPE_ANY);
|
||||
else
|
||||
{
|
||||
TypePtr type;
|
||||
|
||||
if ( val->val.vector_val.size == 0 &&
|
||||
(val->subtype == TYPE_VOID || val->subtype == TYPE_ENUM) )
|
||||
// don't know type - unspecified table.
|
||||
type = base_type(TYPE_ANY);
|
||||
else
|
||||
// all entries have to have the same type...
|
||||
if ( val->subtype == TYPE_VOID )
|
||||
type = base_type(val->val.vector_val.vals[0]->type);
|
||||
else if ( val->subtype == TYPE_ENUM )
|
||||
{
|
||||
// all entries have to have the same type...
|
||||
if ( val->subtype == TYPE_VOID )
|
||||
type = base_type(val->val.vector_val.vals[0]->type);
|
||||
else if ( val->subtype == TYPE_ENUM )
|
||||
// Enums are not a base-type, so need to look it up.
|
||||
const auto& sv = val->val.vector_val.vals[0]->val.string_val;
|
||||
std::string enum_name(sv.data, sv.length);
|
||||
const auto& enum_id = detail::global_scope()->Find(enum_name);
|
||||
|
||||
if ( ! enum_id )
|
||||
{
|
||||
// Enums are not a base-type, so need to look it up.
|
||||
const auto& sv = val->val.vector_val.vals[0]->val.string_val;
|
||||
std::string enum_name(sv.data, sv.length);
|
||||
const auto& enum_id = detail::global_scope()->Find(enum_name);
|
||||
reporter->Warning("Value '%s' of source '%s' is not a valid enum.",
|
||||
enum_name.data(), source.c_str());
|
||||
|
||||
if ( ! enum_id )
|
||||
{
|
||||
reporter->Warning("Value '%s' of source '%s' is not a valid enum.",
|
||||
enum_name.data(), source.c_str());
|
||||
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
type = enum_id->GetType();
|
||||
}
|
||||
else
|
||||
type = base_type(val->subtype);
|
||||
}
|
||||
|
||||
auto vt = make_intrusive<VectorType>(std::move(type));
|
||||
auto v = make_intrusive<VectorVal>(std::move(vt));
|
||||
|
||||
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
auto el = ValueToVal(source, val->val.vector_val.vals[j], have_error);
|
||||
if ( have_error )
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
v->Assign(j, {AdoptRef{}, el});
|
||||
type = enum_id->GetType();
|
||||
}
|
||||
|
||||
return v.release();
|
||||
else
|
||||
type = base_type(val->subtype);
|
||||
}
|
||||
|
||||
auto vt = make_intrusive<VectorType>(std::move(type));
|
||||
auto v = make_intrusive<VectorVal>(std::move(vt));
|
||||
|
||||
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
auto el = ValueToVal(source, val->val.vector_val.vals[j], have_error);
|
||||
if ( have_error )
|
||||
return nullptr;
|
||||
|
||||
v->Assign(j, {AdoptRef{}, el});
|
||||
}
|
||||
|
||||
return v.release();
|
||||
}
|
||||
|
||||
case TYPE_ENUM:
|
||||
{
|
||||
// Convert to string first to not have to deal with missing
|
||||
// \0's...
|
||||
std::string enum_string(val->val.string_val.data, val->val.string_val.length);
|
||||
|
||||
// let's try looking it up by global ID.
|
||||
const auto& id = detail::lookup_ID(enum_string.c_str(), detail::GLOBAL_MODULE_NAME);
|
||||
|
||||
if ( ! id || ! id->IsEnumConst() )
|
||||
{
|
||||
// Convert to string first to not have to deal with missing
|
||||
// \0's...
|
||||
std::string enum_string(val->val.string_val.data, val->val.string_val.length);
|
||||
reporter->Warning("Value '%s' for source '%s' is not a valid enum.",
|
||||
enum_string.c_str(), source.c_str());
|
||||
|
||||
// let's try looking it up by global ID.
|
||||
const auto& id = detail::lookup_ID(enum_string.c_str(), detail::GLOBAL_MODULE_NAME);
|
||||
|
||||
if ( ! id || ! id->IsEnumConst() )
|
||||
{
|
||||
reporter->Warning("Value '%s' for source '%s' is not a valid enum.",
|
||||
enum_string.c_str(), source.c_str());
|
||||
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EnumType* t = id->GetType()->AsEnumType();
|
||||
int intval = t->Lookup(id->ModuleName(), id->Name());
|
||||
if ( intval < 0 )
|
||||
{
|
||||
reporter->Warning("Enum value '%s' for source '%s' not found.",
|
||||
enum_string.c_str(), source.c_str());
|
||||
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto rval = t->GetEnumVal(intval);
|
||||
return rval.release();
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EnumType* t = id->GetType()->AsEnumType();
|
||||
int intval = t->Lookup(id->ModuleName(), id->Name());
|
||||
if ( intval < 0 )
|
||||
{
|
||||
reporter->Warning("Enum value '%s' for source '%s' not found.", enum_string.c_str(),
|
||||
source.c_str());
|
||||
|
||||
have_error = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto rval = t->GetEnumVal(intval);
|
||||
return rval.release();
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->InternalError("Unsupported type in SerialTypes::ValueToVal from source %s",
|
||||
source.c_str());
|
||||
|
|
|
@ -123,80 +123,80 @@ bool Ascii::Describe(ODesc* desc, Value* val, const string& name) const
|
|||
case TYPE_STRING:
|
||||
case TYPE_FILE:
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
int size = val->val.string_val.length;
|
||||
const char* data = val->val.string_val.data;
|
||||
|
||||
if ( ! size )
|
||||
{
|
||||
int size = val->val.string_val.length;
|
||||
const char* data = val->val.string_val.data;
|
||||
|
||||
if ( ! size )
|
||||
{
|
||||
desc->Add(separators.empty_field);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( escapeReservedContent(desc, separators.unset_field, data, size) )
|
||||
break;
|
||||
|
||||
if ( escapeReservedContent(desc, separators.empty_field, data, size) )
|
||||
break;
|
||||
|
||||
desc->AddN(data, size);
|
||||
desc->Add(separators.empty_field);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( escapeReservedContent(desc, separators.unset_field, data, size) )
|
||||
break;
|
||||
|
||||
if ( escapeReservedContent(desc, separators.empty_field, data, size) )
|
||||
break;
|
||||
|
||||
desc->AddN(data, size);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
if ( ! val->val.set_val.size )
|
||||
{
|
||||
if ( ! val->val.set_val.size )
|
||||
{
|
||||
desc->Add(separators.empty_field);
|
||||
break;
|
||||
}
|
||||
|
||||
desc->AddEscapeSequence(separators.set_separator);
|
||||
|
||||
for ( bro_int_t j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc->AddRaw(separators.set_separator);
|
||||
|
||||
if ( ! Describe(desc, val->val.set_val.vals[j]) )
|
||||
{
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
|
||||
desc->Add(separators.empty_field);
|
||||
break;
|
||||
}
|
||||
|
||||
desc->AddEscapeSequence(separators.set_separator);
|
||||
|
||||
for ( bro_int_t j = 0; j < val->val.set_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc->AddRaw(separators.set_separator);
|
||||
|
||||
if ( ! Describe(desc, val->val.set_val.vals[j]) )
|
||||
{
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
if ( ! val->val.vector_val.size )
|
||||
{
|
||||
if ( ! val->val.vector_val.size )
|
||||
{
|
||||
desc->Add(separators.empty_field);
|
||||
break;
|
||||
}
|
||||
|
||||
desc->AddEscapeSequence(separators.set_separator);
|
||||
|
||||
for ( bro_int_t j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc->AddRaw(separators.set_separator);
|
||||
|
||||
if ( ! Describe(desc, val->val.vector_val.vals[j]) )
|
||||
{
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
|
||||
desc->Add(separators.empty_field);
|
||||
break;
|
||||
}
|
||||
|
||||
desc->AddEscapeSequence(separators.set_separator);
|
||||
|
||||
for ( bro_int_t j = 0; j < val->val.vector_val.size; j++ )
|
||||
{
|
||||
if ( j > 0 )
|
||||
desc->AddRaw(separators.set_separator);
|
||||
|
||||
if ( ! Describe(desc, val->val.vector_val.vals[j]) )
|
||||
{
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
desc->RemoveEscapeSequence(separators.set_separator);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
GetThread()->Warning(
|
||||
GetThread()->Fmt("Ascii writer unsupported field format %d", val->type));
|
||||
|
@ -222,30 +222,30 @@ Value* Ascii::ParseValue(const string& s, const string& name, TypeTag type, Type
|
|||
{
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRING:
|
||||
{
|
||||
string unescaped = util::get_unescaped_string(s);
|
||||
val->val.string_val.length = unescaped.size();
|
||||
val->val.string_val.data = new char[val->val.string_val.length];
|
||||
// we do not need a zero-byte at the end - the input manager adds that explicitly
|
||||
memcpy(val->val.string_val.data, unescaped.data(), unescaped.size());
|
||||
break;
|
||||
}
|
||||
{
|
||||
string unescaped = util::get_unescaped_string(s);
|
||||
val->val.string_val.length = unescaped.size();
|
||||
val->val.string_val.data = new char[val->val.string_val.length];
|
||||
// we do not need a zero-byte at the end - the input manager adds that explicitly
|
||||
memcpy(val->val.string_val.data, unescaped.data(), unescaped.size());
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_BOOL:
|
||||
{
|
||||
auto stripped = util::strstrip(s);
|
||||
if ( stripped == "T" || stripped == "1" )
|
||||
val->val.int_val = 1;
|
||||
else if ( stripped == "F" || stripped == "0" )
|
||||
val->val.int_val = 0;
|
||||
else
|
||||
{
|
||||
auto stripped = util::strstrip(s);
|
||||
if ( stripped == "T" || stripped == "1" )
|
||||
val->val.int_val = 1;
|
||||
else if ( stripped == "F" || stripped == "0" )
|
||||
val->val.int_val = 0;
|
||||
else
|
||||
{
|
||||
GetThread()->Warning(GetThread()->Fmt("Field: %s Invalid value for boolean: %s",
|
||||
name.c_str(), start));
|
||||
goto parse_error;
|
||||
}
|
||||
break;
|
||||
GetThread()->Warning(GetThread()->Fmt("Field: %s Invalid value for boolean: %s",
|
||||
name.c_str(), start));
|
||||
goto parse_error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_INT:
|
||||
val->val.int_val = strtoll(start, &end, 10);
|
||||
|
@ -268,91 +268,91 @@ Value* Ascii::ParseValue(const string& s, const string& name, TypeTag type, Type
|
|||
break;
|
||||
|
||||
case TYPE_PORT:
|
||||
{
|
||||
auto stripped = util::strstrip(s);
|
||||
val->val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
pos = stripped.find('/');
|
||||
string numberpart;
|
||||
if ( pos != std::string::npos && stripped.length() > pos + 1 )
|
||||
{
|
||||
auto stripped = util::strstrip(s);
|
||||
val->val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
pos = stripped.find('/');
|
||||
string numberpart;
|
||||
if ( pos != std::string::npos && stripped.length() > pos + 1 )
|
||||
{
|
||||
auto proto = stripped.substr(pos + 1);
|
||||
if ( util::strtolower(proto) == "tcp" )
|
||||
val->val.port_val.proto = TRANSPORT_TCP;
|
||||
else if ( util::strtolower(proto) == "udp" )
|
||||
val->val.port_val.proto = TRANSPORT_UDP;
|
||||
else if ( util::strtolower(proto) == "icmp" )
|
||||
val->val.port_val.proto = TRANSPORT_ICMP;
|
||||
else if ( util::strtolower(proto) == "unknown" )
|
||||
val->val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
else
|
||||
GetThread()->Warning(GetThread()->Fmt(
|
||||
"Port '%s' contained unknown protocol '%s'", s.c_str(), proto.c_str()));
|
||||
}
|
||||
|
||||
if ( pos != std::string::npos && pos > 0 )
|
||||
{
|
||||
numberpart = stripped.substr(0, pos);
|
||||
start = numberpart.c_str();
|
||||
}
|
||||
val->val.port_val.port = strtoull(start, &end, 10);
|
||||
if ( CheckNumberError(start, end, true) )
|
||||
goto parse_error;
|
||||
auto proto = stripped.substr(pos + 1);
|
||||
if ( util::strtolower(proto) == "tcp" )
|
||||
val->val.port_val.proto = TRANSPORT_TCP;
|
||||
else if ( util::strtolower(proto) == "udp" )
|
||||
val->val.port_val.proto = TRANSPORT_UDP;
|
||||
else if ( util::strtolower(proto) == "icmp" )
|
||||
val->val.port_val.proto = TRANSPORT_ICMP;
|
||||
else if ( util::strtolower(proto) == "unknown" )
|
||||
val->val.port_val.proto = TRANSPORT_UNKNOWN;
|
||||
else
|
||||
GetThread()->Warning(GetThread()->Fmt(
|
||||
"Port '%s' contained unknown protocol '%s'", s.c_str(), proto.c_str()));
|
||||
}
|
||||
|
||||
if ( pos != std::string::npos && pos > 0 )
|
||||
{
|
||||
numberpart = stripped.substr(0, pos);
|
||||
start = numberpart.c_str();
|
||||
}
|
||||
val->val.port_val.port = strtoull(start, &end, 10);
|
||||
if ( CheckNumberError(start, end, true) )
|
||||
goto parse_error;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_SUBNET:
|
||||
{
|
||||
string unescaped = util::strstrip(util::get_unescaped_string(s));
|
||||
size_t pos = unescaped.find('/');
|
||||
if ( pos == unescaped.npos )
|
||||
{
|
||||
string unescaped = util::strstrip(util::get_unescaped_string(s));
|
||||
size_t pos = unescaped.find('/');
|
||||
if ( pos == unescaped.npos )
|
||||
{
|
||||
GetThread()->Warning(GetThread()->Fmt("Invalid value for subnet: %s", start));
|
||||
goto parse_error;
|
||||
}
|
||||
|
||||
string width_str = unescaped.substr(pos + 1);
|
||||
uint8_t width = (uint8_t)strtol(width_str.c_str(), &end, 10);
|
||||
|
||||
if ( CheckNumberError(start, end) )
|
||||
goto parse_error;
|
||||
|
||||
string addr = unescaped.substr(0, pos);
|
||||
|
||||
val->val.subnet_val.prefix = ParseAddr(addr);
|
||||
val->val.subnet_val.length = width;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
string unescaped = util::strstrip(util::get_unescaped_string(s));
|
||||
val->val.addr_val = ParseAddr(unescaped);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
string candidate = util::get_unescaped_string(s);
|
||||
// A string is a candidate pattern iff it begins and ends with
|
||||
// a '/'. Rather or not the rest of the string is legal will
|
||||
// be determined later when it is given to the RE engine.
|
||||
if ( candidate.size() >= 2 )
|
||||
{
|
||||
if ( candidate.front() == candidate.back() && candidate.back() == '/' )
|
||||
{
|
||||
// Remove the '/'s
|
||||
candidate.erase(0, 1);
|
||||
candidate.erase(candidate.size() - 1);
|
||||
val->val.pattern_text_val = util::copy_string(candidate.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GetThread()->Warning(GetThread()->Fmt("String '%s' contained no parseable pattern.",
|
||||
candidate.c_str()));
|
||||
GetThread()->Warning(GetThread()->Fmt("Invalid value for subnet: %s", start));
|
||||
goto parse_error;
|
||||
}
|
||||
|
||||
string width_str = unescaped.substr(pos + 1);
|
||||
uint8_t width = (uint8_t)strtol(width_str.c_str(), &end, 10);
|
||||
|
||||
if ( CheckNumberError(start, end) )
|
||||
goto parse_error;
|
||||
|
||||
string addr = unescaped.substr(0, pos);
|
||||
|
||||
val->val.subnet_val.prefix = ParseAddr(addr);
|
||||
val->val.subnet_val.length = width;
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ADDR:
|
||||
{
|
||||
string unescaped = util::strstrip(util::get_unescaped_string(s));
|
||||
val->val.addr_val = ParseAddr(unescaped);
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_PATTERN:
|
||||
{
|
||||
string candidate = util::get_unescaped_string(s);
|
||||
// A string is a candidate pattern iff it begins and ends with
|
||||
// a '/'. Rather or not the rest of the string is legal will
|
||||
// be determined later when it is given to the RE engine.
|
||||
if ( candidate.size() >= 2 )
|
||||
{
|
||||
if ( candidate.front() == candidate.back() && candidate.back() == '/' )
|
||||
{
|
||||
// Remove the '/'s
|
||||
candidate.erase(0, 1);
|
||||
candidate.erase(candidate.size() - 1);
|
||||
val->val.pattern_text_val = util::copy_string(candidate.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GetThread()->Warning(
|
||||
GetThread()->Fmt("String '%s' contained no parseable pattern.", candidate.c_str()));
|
||||
goto parse_error;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
case TYPE_VECTOR:
|
||||
// First - common initialization
|
||||
|
|
|
@ -127,80 +127,79 @@ void JSON::BuildJSON(NullDoubleWriter& writer, Value* val, const std::string& na
|
|||
break;
|
||||
|
||||
case TYPE_TIME:
|
||||
{
|
||||
if ( timestamps == TS_ISO8601 )
|
||||
{
|
||||
if ( timestamps == TS_ISO8601 )
|
||||
char buffer[40];
|
||||
char buffer2[48];
|
||||
time_t the_time = time_t(floor(val->val.double_val));
|
||||
struct tm t;
|
||||
|
||||
if ( ! gmtime_r(&the_time, &t) ||
|
||||
! strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", &t) )
|
||||
{
|
||||
char buffer[40];
|
||||
char buffer2[48];
|
||||
time_t the_time = time_t(floor(val->val.double_val));
|
||||
struct tm t;
|
||||
|
||||
if ( ! gmtime_r(&the_time, &t) ||
|
||||
! strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", &t) )
|
||||
{
|
||||
GetThread()->Error(GetThread()->Fmt(
|
||||
"json formatter: failure getting time: (%lf)", val->val.double_val));
|
||||
// This was a failure, doesn't really matter what gets put here
|
||||
// but it should probably stand out...
|
||||
writer.String("2000-01-01T00:00:00.000000");
|
||||
}
|
||||
else
|
||||
{
|
||||
double integ;
|
||||
double frac = modf(val->val.double_val, &integ);
|
||||
|
||||
if ( frac < 0 )
|
||||
frac += 1;
|
||||
|
||||
snprintf(buffer2, sizeof(buffer2), "%s.%06.0fZ", buffer,
|
||||
fabs(frac) * 1000000);
|
||||
writer.String(buffer2, strlen(buffer2));
|
||||
}
|
||||
GetThread()->Error(GetThread()->Fmt(
|
||||
"json formatter: failure getting time: (%lf)", val->val.double_val));
|
||||
// This was a failure, doesn't really matter what gets put here
|
||||
// but it should probably stand out...
|
||||
writer.String("2000-01-01T00:00:00.000000");
|
||||
}
|
||||
|
||||
else if ( timestamps == TS_EPOCH )
|
||||
writer.Double(val->val.double_val);
|
||||
|
||||
else if ( timestamps == TS_MILLIS )
|
||||
else
|
||||
{
|
||||
// ElasticSearch uses milliseconds for timestamps
|
||||
writer.Uint64((uint64_t)(val->val.double_val * 1000));
|
||||
}
|
||||
double integ;
|
||||
double frac = modf(val->val.double_val, &integ);
|
||||
|
||||
break;
|
||||
if ( frac < 0 )
|
||||
frac += 1;
|
||||
|
||||
snprintf(buffer2, sizeof(buffer2), "%s.%06.0fZ", buffer, fabs(frac) * 1000000);
|
||||
writer.String(buffer2, strlen(buffer2));
|
||||
}
|
||||
}
|
||||
|
||||
else if ( timestamps == TS_EPOCH )
|
||||
writer.Double(val->val.double_val);
|
||||
|
||||
else if ( timestamps == TS_MILLIS )
|
||||
{
|
||||
// ElasticSearch uses milliseconds for timestamps
|
||||
writer.Uint64((uint64_t)(val->val.double_val * 1000));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRING:
|
||||
case TYPE_FILE:
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
writer.String(util::json_escape_utf8(
|
||||
std::string(val->val.string_val.data, val->val.string_val.length)));
|
||||
break;
|
||||
}
|
||||
{
|
||||
writer.String(util::json_escape_utf8(
|
||||
std::string(val->val.string_val.data, val->val.string_val.length)));
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_TABLE:
|
||||
{
|
||||
writer.StartArray();
|
||||
{
|
||||
writer.StartArray();
|
||||
|
||||
for ( bro_int_t idx = 0; idx < val->val.set_val.size; idx++ )
|
||||
BuildJSON(writer, val->val.set_val.vals[idx]);
|
||||
for ( bro_int_t idx = 0; idx < val->val.set_val.size; idx++ )
|
||||
BuildJSON(writer, val->val.set_val.vals[idx]);
|
||||
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
|
||||
case TYPE_VECTOR:
|
||||
{
|
||||
writer.StartArray();
|
||||
{
|
||||
writer.StartArray();
|
||||
|
||||
for ( bro_int_t idx = 0; idx < val->val.vector_val.size; idx++ )
|
||||
BuildJSON(writer, val->val.vector_val.vals[idx]);
|
||||
for ( bro_int_t idx = 0; idx < val->val.vector_val.size; idx++ )
|
||||
BuildJSON(writer, val->val.vector_val.vals[idx]);
|
||||
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
writer.EndArray();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
reporter->Warning("Unhandled type in JSON::BuildJSON");
|
||||
|
|
86
src/util.cc
86
src/util.cc
|
@ -183,67 +183,67 @@ int expand_escape(const char*& s)
|
|||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
{ // \<octal>{1,3}
|
||||
--s; // put back the first octal digit
|
||||
const char* start = s;
|
||||
{ // \<octal>{1,3}
|
||||
--s; // put back the first octal digit
|
||||
const char* start = s;
|
||||
|
||||
// require at least one octal digit and parse at most three
|
||||
// require at least one octal digit and parse at most three
|
||||
|
||||
int result = parse_octal_digit(*s++);
|
||||
int result = parse_octal_digit(*s++);
|
||||
|
||||
if ( result < 0 )
|
||||
{
|
||||
reporter->Error("bad octal escape: %s", start);
|
||||
return 0;
|
||||
}
|
||||
if ( result < 0 )
|
||||
{
|
||||
reporter->Error("bad octal escape: %s", start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// second digit?
|
||||
int digit = parse_octal_digit(*s);
|
||||
// second digit?
|
||||
int digit = parse_octal_digit(*s);
|
||||
|
||||
if ( digit >= 0 )
|
||||
{
|
||||
result = (result << 3) | digit;
|
||||
++s;
|
||||
|
||||
// third digit?
|
||||
digit = parse_octal_digit(*s);
|
||||
|
||||
if ( digit >= 0 )
|
||||
{
|
||||
result = (result << 3) | digit;
|
||||
++s;
|
||||
|
||||
// third digit?
|
||||
digit = parse_octal_digit(*s);
|
||||
|
||||
if ( digit >= 0 )
|
||||
{
|
||||
result = (result << 3) | digit;
|
||||
++s;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case 'x':
|
||||
{ /* \x<hex> */
|
||||
const char* start = s;
|
||||
{ /* \x<hex> */
|
||||
const char* start = s;
|
||||
|
||||
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
||||
// Look at most 2 characters, so that "\x0ddir" -> "^Mdir".
|
||||
|
||||
int result = parse_hex_digit(*s++);
|
||||
int result = parse_hex_digit(*s++);
|
||||
|
||||
if ( result < 0 )
|
||||
{
|
||||
reporter->Error("bad hexadecimal escape: %s", start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// second digit?
|
||||
int digit = parse_hex_digit(*s);
|
||||
|
||||
if ( digit >= 0 )
|
||||
{
|
||||
result = (result << 4) | digit;
|
||||
++s;
|
||||
}
|
||||
|
||||
return result;
|
||||
if ( result < 0 )
|
||||
{
|
||||
reporter->Error("bad hexadecimal escape: %s", start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// second digit?
|
||||
int digit = parse_hex_digit(*s);
|
||||
|
||||
if ( digit >= 0 )
|
||||
{
|
||||
result = (result << 4) | digit;
|
||||
++s;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
default:
|
||||
return s[-1];
|
||||
}
|
||||
|
|
|
@ -81,38 +81,37 @@ static void write_plugin_components(FILE* f, const plugin::Plugin* p)
|
|||
switch ( component->Type() )
|
||||
{
|
||||
case plugin::component::ANALYZER:
|
||||
{
|
||||
const analyzer::Component* c =
|
||||
dynamic_cast<const analyzer::Component*>(component);
|
||||
{
|
||||
const analyzer::Component* c = dynamic_cast<const analyzer::Component*>(component);
|
||||
|
||||
if ( c )
|
||||
write_analyzer_component(f, c);
|
||||
else
|
||||
reporter->InternalError("component type mismatch");
|
||||
}
|
||||
if ( c )
|
||||
write_analyzer_component(f, c);
|
||||
else
|
||||
reporter->InternalError("component type mismatch");
|
||||
}
|
||||
break;
|
||||
|
||||
case plugin::component::PACKET_ANALYZER:
|
||||
{
|
||||
const packet_analysis::Component* c =
|
||||
dynamic_cast<const packet_analysis::Component*>(component);
|
||||
{
|
||||
const packet_analysis::Component* c =
|
||||
dynamic_cast<const packet_analysis::Component*>(component);
|
||||
|
||||
if ( c )
|
||||
write_analyzer_component(f, c);
|
||||
else
|
||||
reporter->InternalError("component type mismatch");
|
||||
}
|
||||
if ( c )
|
||||
write_analyzer_component(f, c);
|
||||
else
|
||||
reporter->InternalError("component type mismatch");
|
||||
}
|
||||
break;
|
||||
|
||||
case plugin::component::FILE_ANALYZER:
|
||||
{
|
||||
const auto* c = dynamic_cast<const file_analysis::Component*>(component);
|
||||
{
|
||||
const auto* c = dynamic_cast<const file_analysis::Component*>(component);
|
||||
|
||||
if ( c )
|
||||
write_analyzer_component(f, c);
|
||||
else
|
||||
reporter->InternalError("component type mismatch");
|
||||
}
|
||||
if ( c )
|
||||
write_analyzer_component(f, c);
|
||||
else
|
||||
reporter->InternalError("component type mismatch");
|
||||
}
|
||||
break;
|
||||
|
||||
case plugin::component::READER:
|
||||
|
|
|
@ -170,19 +170,19 @@ std::optional<std::string> source_code_range(const zeek::detail::ID* id)
|
|||
switch ( type->Tag() )
|
||||
{
|
||||
case TYPE_FUNC:
|
||||
{
|
||||
const auto& v = id->GetVal();
|
||||
{
|
||||
const auto& v = id->GetVal();
|
||||
|
||||
if ( v && v->AsFunc()->GetBodies().size() == 1 )
|
||||
{
|
||||
// Either a function or an event/hook with single body can
|
||||
// report that single, continuous range.
|
||||
loc = v->AsFunc()->GetBodies()[0].stmts->GetLocationInfo();
|
||||
++extra_lines;
|
||||
}
|
||||
else
|
||||
loc = id->GetLocationInfo();
|
||||
if ( v && v->AsFunc()->GetBodies().size() == 1 )
|
||||
{
|
||||
// Either a function or an event/hook with single body can
|
||||
// report that single, continuous range.
|
||||
loc = v->AsFunc()->GetBodies()[0].stmts->GetLocationInfo();
|
||||
++extra_lines;
|
||||
}
|
||||
else
|
||||
loc = id->GetLocationInfo();
|
||||
}
|
||||
break;
|
||||
case TYPE_ENUM:
|
||||
// Fallthrough
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue