diff --git a/CHANGES b/CHANGES index 4cb4ad82c0..ce53510f16 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,11 @@ +2.2-199 | 2014-03-03 16:34:20 -0800 + + * Allow iterating over bif functions with result type vector of any. + This changes the internal type that is used to signal that a + vector is unspecified from any to void. Addresses BIT-1144 + (Bernhard Amann) + 2.2-197 | 2014-02-28 15:36:58 -0800 * Remove test code. (Robin Sommer) diff --git a/VERSION b/VERSION index 90e2bd5d51..6407bbf911 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2-197 +2.2-199 diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 46a838e8ae..afb89ba1c7 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -39,6 +39,14 @@ type count_set: set[count]; ## directly and then remove this alias. type index_vec: vector of count; +## A vector of any, used by some builtin functions to store a list of varying +## types. +## +## .. todo:: We need this type definition only for declaring builtin functions +## via ``bifcl``. We should extend ``bifcl`` to understand composite types +## directly and then remove this alias. +type any_vec: vector of any; + ## A vector of strings. ## ## .. todo:: We need this type definition only for declaring builtin functions diff --git a/src/Expr.cc b/src/Expr.cc index 5f6c7d41c6..a5315b533d 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3819,7 +3819,9 @@ VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list, if ( constructor_list->Exprs().length() == 0 ) { // vector(). - SetType(new ::VectorType(base_type(TYPE_ANY))); + // By default, assign VOID type here. A vector with + // void type set is seen as an unspecified vector. + SetType(new ::VectorType(base_type(TYPE_VOID))); return; } diff --git a/src/Type.cc b/src/Type.cc index 340ab973bc..02a486056d 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1626,6 +1626,23 @@ VectorType::~VectorType() Unref(yield_type); } +BroType* VectorType::YieldType() + { + // Work around the fact that we use void internally to mark a vector + // as being unspecified. When looking at its yield type, we need to + // return any as that's what other code historically expects for type + // comparisions. + if ( IsUnspecifiedVector() ) + { + BroType* ret = ::base_type(TYPE_ANY); + Unref(ret); // unref, because this won't be held by anyone. + assert(ret); + return ret; + } + + return yield_type; + } + int VectorType::MatchesIndex(ListExpr*& index) const { expr_list& el = index->Exprs(); @@ -1645,7 +1662,7 @@ int VectorType::MatchesIndex(ListExpr*& index) const bool VectorType::IsUnspecifiedVector() const { - return yield_type->Tag() == TYPE_ANY; + return yield_type->Tag() == TYPE_VOID; } IMPLEMENT_SERIAL(VectorType, SER_VECTOR_TYPE); diff --git a/src/Type.h b/src/Type.h index f6328aed4a..361c2794f0 100644 --- a/src/Type.h +++ b/src/Type.h @@ -572,7 +572,7 @@ class VectorType : public BroType { public: VectorType(BroType* t); virtual ~VectorType(); - BroType* YieldType() { return yield_type; } + BroType* YieldType(); int MatchesIndex(ListExpr*& index) const; diff --git a/src/Val.cc b/src/Val.cc index 8c60f4c490..4aec6a7c31 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3122,7 +3122,7 @@ bool VectorVal::DoUnserialize(UnserialInfo* info) for ( int i = 0; i < len; ++i ) { Val* v; - UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY)); + UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY)); // accept any type Assign(i, v); } diff --git a/src/Val.h b/src/Val.h index 3d4141cd7a..b94cb2d621 100644 --- a/src/Val.h +++ b/src/Val.h @@ -656,6 +656,8 @@ protected: DECLARE_SERIAL(PatternVal); }; +// ListVals are mainly used to index tables that have more than one +// element in their index. class ListVal : public Val { public: ListVal(TypeTag t); diff --git a/src/probabilistic/top-k.bif b/src/probabilistic/top-k.bif index 5362750467..8f7b071a4c 100644 --- a/src/probabilistic/top-k.bif +++ b/src/probabilistic/top-k.bif @@ -49,7 +49,7 @@ function topk_add%(handle: opaque of topk, value: any%): any ## ## .. bro:see:: topk_init topk_add topk_count topk_epsilon ## topk_size topk_sum topk_merge topk_merge_prune -function topk_get_top%(handle: opaque of topk, k: count%): any +function topk_get_top%(handle: opaque of topk, k: count%): any_vec %{ assert(handle); probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; diff --git a/testing/btest/Baseline/bifs.topk/out b/testing/btest/Baseline/bifs.topk/out index 1ce5c4b850..48d7e23f96 100644 --- a/testing/btest/Baseline/bifs.topk/out +++ b/testing/btest/Baseline/bifs.topk/out @@ -79,3 +79,12 @@ 0 8 0 +0, c +1, e +2, d +0, c +1, e +2, d +0, c +1, e +2, d diff --git a/testing/btest/Baseline/language.vector-unspecified/output b/testing/btest/Baseline/language.vector-unspecified/output new file mode 100644 index 0000000000..8d726561ab --- /dev/null +++ b/testing/btest/Baseline/language.vector-unspecified/output @@ -0,0 +1 @@ +[5, Hi, 127.0.0.1] diff --git a/testing/btest/bifs/topk.bro b/testing/btest/bifs/topk.bro index 02d13c4195..1e650335a7 100644 --- a/testing/btest/bifs/topk.bro +++ b/testing/btest/bifs/topk.bro @@ -148,7 +148,17 @@ event bro_init() print topk_count(k3, "d"); print topk_epsilon(k3, "d"); - + local styped: vector of count; + styped = topk_get_top(k3, 3); + for ( i in styped ) + print i, styped[i]; + local anytyped: vector of any; + anytyped = topk_get_top(k3, 3); + for ( i in anytyped ) + print i, anytyped[i]; + local suntyped = topk_get_top(k3, 3); + for ( i in suntyped ) + print i, suntyped[i]; } diff --git a/testing/btest/language/vector-unspecified.bro b/testing/btest/language/vector-unspecified.bro new file mode 100644 index 0000000000..b91f910504 --- /dev/null +++ b/testing/btest/language/vector-unspecified.bro @@ -0,0 +1,11 @@ +# @TEST-EXEC: bro -b %INPUT >output 2>&1 +# @TEST-EXEC: btest-diff output + +# Test assignment behavior of unspecified vectors +local a = vector(); + +a[0] = 5; +a[1] = "Hi"; +a[2] = 127.0.0.1; + +print a;