diff --git a/CHANGES b/CHANGES index c51cd00bbf..355b58f8fc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,8 @@ +2.5-852 | 2018-08-17 15:15:55 -0500 + + * BIT-466: add redef += support to vectors (Jon Siwek, Corelight) + 2.5-850 | 2018-08-17 11:12:53 -0500 * BIT-1815: move SMB::write_cmd_log functionality into policy/ script diff --git a/NEWS b/NEWS index e5f5b28054..bb9ea619c8 100644 --- a/NEWS +++ b/NEWS @@ -314,6 +314,9 @@ New Functionality - An expression of the form "v += e" will append the value of the expression "e" to the end of the vector "v" (of course assuming type-compatbility). + "redef v += { a, b, c }" will similarly extend a vector previously declared + with &redef by appending the result of expressions "a", "b", and "c" to + the vector at initialization-time. Changed Functionality --------------------- diff --git a/VERSION b/VERSION index 3e949de53a..6aa99abe08 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.5-850 +2.5-852 diff --git a/src/ID.cc b/src/ID.cc index a68abb6264..9e4eb7d245 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -140,10 +140,11 @@ void ID::SetVal(Val* v, init_class c) } if ( type->Tag() != TYPE_TABLE && - (type->Tag() != TYPE_PATTERN || c == INIT_REMOVE) ) + (type->Tag() != TYPE_PATTERN || c == INIT_REMOVE) && + (type->Tag() != TYPE_VECTOR || c == INIT_REMOVE) ) { if ( c == INIT_EXTRA ) - Error("+= initializer only applies to tables, sets and patterns", v); + Error("+= initializer only applies to tables, sets, vectors and patterns", v); else Error("-= initializer only applies to tables and sets", v); } diff --git a/src/Val.cc b/src/Val.cc index 7879d282b2..71d38e3c63 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3321,6 +3321,29 @@ bool VectorVal::AssignRepeat(unsigned int index, unsigned int how_many, return true; } +int VectorVal::AddTo(Val* val, int /* is_first_init */) const + { + if ( val->Type()->Tag() != TYPE_VECTOR ) + { + val->Error("not a vector"); + return 0; + } + + VectorVal* v = val->AsVectorVal(); + + if ( ! same_type(type, v->Type()) ) + { + type->Error("vector type clash", v->Type()); + return 0; + } + + auto last_idx = v->Size(); + + for ( auto i = 0u; i < Size(); ++i ) + v->Assign(last_idx++, Lookup(i)->Ref()); + + return 1; + } Val* VectorVal::Lookup(unsigned int index) const { diff --git a/src/Val.h b/src/Val.h index bb18dceb4f..f189668b28 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1046,6 +1046,10 @@ public: bool AssignRepeat(unsigned int index, unsigned int how_many, Val* element); + // Add this value to the given value (if appropriate). + // Returns true if succcessful. + int AddTo(Val* v, int is_first_init) const override; + // Returns nil if no element was at that value. // Lookup does NOT grow the vector to this size. // The Val* variant assumes that the index Val* has been type-checked. diff --git a/testing/btest/Baseline/language.redef-vector/out b/testing/btest/Baseline/language.redef-vector/out new file mode 100644 index 0000000000..73a5ef460d --- /dev/null +++ b/testing/btest/Baseline/language.redef-vector/out @@ -0,0 +1,3 @@ +[testing, blah, foo, foo, testing] +[one, two, three] +[a, b, c, one, two, three, a, b, c, abc, d] diff --git a/testing/btest/language/redef-vector.bro b/testing/btest/language/redef-vector.bro new file mode 100644 index 0000000000..26dc2109ba --- /dev/null +++ b/testing/btest/language/redef-vector.bro @@ -0,0 +1,18 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +const foo: vector of string &redef; +redef foo += { "testing", "blah", "foo", "foo", "testing" }; + +const bar: vector of string = vector() &redef; +redef bar += { "one", "two", "three" }; + +const baz: vector of string = vector("a", "b", "c") &redef; +redef baz += { "one", "two", "three" }; +redef baz += { "a", "b", "c" }; +const d = "d"; +redef baz += { "a" + "b" + "c", d }; + +print foo; +print bar; +print baz;