diff --git a/src/CompHash.cc b/src/CompHash.cc index f120c3618b..81ff353ab8 100644 --- a/src/CompHash.cc +++ b/src/CompHash.cc @@ -7,6 +7,9 @@ #include "Reporter.h" #include "Func.h" +#include +#include + CompositeHash::CompositeHash(TypeList* composite_type) { type = composite_type; @@ -174,12 +177,44 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0, { int* kp = AlignAndPadType(kp0); TableVal* tv = v->AsTableVal(); - ListVal* lv = tv->ConvertToList(); *kp = tv->Size(); kp1 = reinterpret_cast(kp+1); - for ( int i = 0; i < tv->Size(); ++i ) + + auto tbl = tv->AsTable(); + auto it = tbl->InitForIteration(); + ListVal* lv = new ListVal(TYPE_ANY); + + struct HashKeyComparer { + bool operator()(const HashKey* a, const HashKey* b) + { + if ( a->Hash() != b->Hash() ) + return a->Hash() < b->Hash(); + if ( a->Size() != b->Size() ) + return a->Size() < b->Size(); + return strncmp(static_cast(a->Key()), + static_cast(b->Key()), + a->Size()) < 0; + } + }; + + std::map hashkeys; + HashKey* k; + auto idx = 0; + + while ( tbl->NextEntry(k, it) ) { - Val* key = lv->Index(i); + hashkeys[k] = idx++; + lv->Append(tv->RecoverIndex(k)); + } + + for ( auto& kv : hashkeys ) + delete kv.first; + + for ( auto& kv : hashkeys ) + { + auto idx = kv.second; + Val* key = lv->Index(idx); + if ( ! (kp1 = SingleValHash(type_check, kp1, key->Type(), key, false)) ) { diff --git a/testing/btest/Baseline/language.record-index-complex-fields/output b/testing/btest/Baseline/language.record-index-complex-fields/output index f47493ea82..c07d86ee5e 100644 --- a/testing/btest/Baseline/language.record-index-complex-fields/output +++ b/testing/btest/Baseline/language.record-index-complex-fields/output @@ -10,18 +10,18 @@ a } } { -[a=4, tags_v=[0, 1], tags_t={ -[two] = 2, -[one] = 1 -}, tags_s={ -b, -a -}], [a=13, tags_v=[, , 2, 3], tags_t={ [five] = 5, [four] = 4 }, tags_s={ c, d +}], +[a=4, tags_v=[0, 1], tags_t={ +[two] = 2, +[one] = 1 +}, tags_s={ +b, +a }] } diff --git a/testing/btest/language/nested-sets.bro b/testing/btest/language/nested-sets.bro new file mode 100644 index 0000000000..e33e1ac842 --- /dev/null +++ b/testing/btest/language/nested-sets.bro @@ -0,0 +1,19 @@ +# @TEST-EXEC: for i in `seq 21`; do echo 0 >> random.seed; done +# @TEST-EXEC: test `bro -b -G random.seed %INPUT` = "pass" + +type r: record { + b: set[count]; +}; + +global foo: set[r]; +global bar = set(1,3,5); + +add foo[record($b=bar)]; + +bar = set(5,3,1); +delete foo[record($b=bar)]; + +if ( |foo| > 0 ) + print "fail"; +else + print "pass";