* 'paraglob' of https://github.com/ZekeMedley/zeek:
  Add leak test to paraglob.
  Catch paraglob serialization errors in DoClone.
  Update paraglob serialization.
  Stop execution on paraglob error.
  Update paraglob submodule
  Change C++11 detection in paraglob.
  Make paraglob serializable and copyable.
  Initial paraglob integration.

I made a bunch of small changes:
 * paraglob now deals better with \0 characters
 * I rolled back the changes to Binary Serialization format,
 * there were some small formatting issue
 * the error output was slightly unsafe
 * build_unique is now in util.h.

and perhaps a few more small things.
This commit is contained in:
Johanna Amann 2019-06-24 14:05:57 -07:00
commit 5f9a9bbcbe
22 changed files with 432 additions and 4 deletions

View file

@ -281,4 +281,3 @@ string IPPrefix::AsString() const
return prefix.AsString() +"/" + l;
}

View file

@ -1024,3 +1024,88 @@ bool CardinalityVal::DoUnserialize(const broker::data& data)
c = cu.release();
return true;
}
ParaglobVal::ParaglobVal(std::unique_ptr<paraglob::Paraglob> p)
: OpaqueVal(paraglob_type)
{
this->internal_paraglob = std::move(p);
}
VectorVal* ParaglobVal::Get(StringVal* &pattern)
{
VectorVal* rval = new VectorVal(internal_type("string_vec")->AsVectorType());
std::string string_pattern (reinterpret_cast<const char*>(pattern->Bytes()), pattern->Len());
std::vector<std::string> matches = this->internal_paraglob->get(string_pattern);
for (unsigned int i = 0; i < matches.size(); i++)
rval->Assign(i, new StringVal(matches.at(i)));
return rval;
}
bool ParaglobVal::operator==(const ParaglobVal& other) const
{
return *(this->internal_paraglob) == *(other.internal_paraglob);
}
IMPLEMENT_OPAQUE_VALUE(ParaglobVal)
broker::expected<broker::data> ParaglobVal::DoSerialize() const
{
broker::vector d;
std::unique_ptr<std::vector<uint8_t>> iv = this->internal_paraglob->serialize();
for (uint8_t a : *(iv.get()))
d.emplace_back(static_cast<uint64_t>(a));
return {std::move(d)};
}
bool ParaglobVal::DoUnserialize(const broker::data& data)
{
auto d = caf::get_if<broker::vector>(&data);
if ( ! d )
return false;
std::unique_ptr<std::vector<uint8_t>> iv (new std::vector<uint8_t>);
iv->resize(d->size());
for (std::vector<broker::data>::size_type i = 0; i < d->size(); ++i)
{
if ( ! get_vector_idx<uint64_t>(*d, i, iv.get()->data() + i) )
return false;
}
try
{
this->internal_paraglob = build_unique<paraglob::Paraglob>(std::move(iv));
}
catch (const paraglob::underflow_error& e)
{
reporter->Error("Paraglob underflow error -> %s", e.what());
return false;
}
catch (const paraglob::overflow_error& e)
{
reporter->Error("Paraglob overflow error -> %s", e.what());
return false;
}
return true;
}
Val* ParaglobVal::DoClone(CloneState* state)
{
try {
return new ParaglobVal
(build_unique<paraglob::Paraglob>(this->internal_paraglob->serialize()));
}
catch (const paraglob::underflow_error& e)
{
reporter->Error("Paraglob underflow error while cloning -> %s", e.what());
return nullptr;
}
catch (const paraglob::overflow_error& e)
{
reporter->Error("Paraglob overflow error while cloning -> %s", e.what());
return nullptr;
}
}

View file

@ -3,12 +3,18 @@
#ifndef OPAQUEVAL_H
#define OPAQUEVAL_H
#include <memory> // std::unique_ptr
#include <broker/data.hh>
#include <broker/expected.hh>
#include "RandTest.h"
#include "Val.h"
#include "digest.h"
#include "src/paraglob.h"
class OpaqueVal;
@ -319,4 +325,20 @@ private:
probabilistic::CardinalityCounter* c;
};
class ParaglobVal : public OpaqueVal {
public:
explicit ParaglobVal(std::unique_ptr<paraglob::Paraglob> p);
VectorVal* Get(StringVal* &pattern);
Val* DoClone(CloneState* state) override;
bool operator==(const ParaglobVal& other) const;
protected:
ParaglobVal() : OpaqueVal(paraglob_type) {}
DECLARE_OPAQUE_VALUE(ParaglobVal)
private:
std::unique_ptr<paraglob::Paraglob> internal_paraglob;
};
#endif

View file

@ -635,6 +635,7 @@ extern OpaqueType* topk_type;
extern OpaqueType* bloomfilter_type;
extern OpaqueType* x509_opaque_type;
extern OpaqueType* ocsp_resp_opaque_type;
extern OpaqueType* paraglob_type;
// Returns the Bro basic (non-parameterized) type with the given type.
// The reference count of the type is not increased.

View file

@ -118,6 +118,7 @@ OpaqueType* topk_type = 0;
OpaqueType* bloomfilter_type = 0;
OpaqueType* x509_opaque_type = 0;
OpaqueType* ocsp_resp_opaque_type = 0;
OpaqueType* paraglob_type = 0;
// Keep copy of command line
int bro_argc;
@ -786,6 +787,7 @@ int main(int argc, char** argv)
bloomfilter_type = new OpaqueType("bloomfilter");
x509_opaque_type = new OpaqueType("x509");
ocsp_resp_opaque_type = new OpaqueType("ocsp_resp");
paraglob_type = new OpaqueType("paraglob");
// The leak-checker tends to produce some false
// positives (memory which had already been

View file

@ -555,4 +555,13 @@ void bro_strerror_r(int bro_errno, char* buf, size_t buflen);
*/
char* zeekenv(const char* name);
/**
* Small convenience function. Does what std::make_unique does in C++14. Will not
* work on arrays.
*/
template <typename T, typename ... Args>
std::unique_ptr<T> build_unique (Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#endif

View file

@ -789,6 +789,74 @@ function sha256_hash_finish%(handle: opaque of sha256%): string
return static_cast<HashVal*>(handle)->Get();
%}
## Initializes and returns a new paraglob.
##
## v: Vector of patterns to initialize the paraglob with.
##
## Returns: A new, compiled, paraglob with the patterns in *v*
##
## .. zeek:see::paraglob_get paraglob_equals paraglob_add
function paraglob_init%(v: any%) : opaque of paraglob
%{
if ( v->Type()->Tag() != TYPE_VECTOR ||
v->Type()->YieldType()->Tag() != TYPE_STRING )
{
// reporter->Error will throw an exception.
reporter->Error("paraglob requires a vector of strings for initialization.");
return nullptr;
}
std::vector<std::string> patterns;
VectorVal* vv = v->AsVectorVal();
for ( unsigned int i = 0; i < vv->Size(); ++i )
{
const BroString* s = vv->Lookup(i)->AsString();
patterns.push_back(std::string(reinterpret_cast<const char*>(s->Bytes()), s->Len()));
}
try
{
std::unique_ptr<paraglob::Paraglob> p (new paraglob::Paraglob(patterns));
return new ParaglobVal(std::move(p));
}
// Thrown if paraglob fails to add a pattern.
catch (const paraglob::add_error& e)
{
reporter->Error("Paraglob failed to add pattern: %s", e.what());
return nullptr;
}
%}
## Gets all the strings inside the handle associated with an input pattern.
##
## handle: A compiled paraglob.
##
## pattern: A glob style pattern.
##
## Returns: A vector of strings matching the input pattern
##
## ## .. zeek:see::paraglob_add paraglob_equals paraglob_init
function paraglob_get%(handle: opaque of paraglob, pat: string%): string_vec
%{
return static_cast<ParaglobVal*>(handle)->Get(pat);
%}
## Compares two paraglobs for equality.
##
## p_one: A compiled paraglob.
##
## p_two: A compiled paraglob.
##
## Returns: True if both paraglobs contain the same patterns, false otherwise.
##
## ## .. zeek:see::paraglob_add paraglob_get paraglob_init
function paraglob_equals%(p_one: opaque of paraglob, p_two: opaque of paraglob%) : bool
%{
return val_mgr->GetBool(
*(static_cast<ParaglobVal*>(p_one)) == *(static_cast<ParaglobVal*>(p_two))
);
%}
## Returns 32-bit digest of arbitrary input values using FNV-1a hash algorithm.
## See `<https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function>`_.
##
@ -3077,7 +3145,7 @@ function strptime%(fmt: string, d: string%) : time
const time_t timeval = time_t();
struct tm t;
if ( ! localtime_r(&timeval, &t) ||
if ( ! localtime_r(&timeval, &t) ||
! strptime(d->CheckString(), fmt->CheckString(), &t) )
{
reporter->Warning("strptime conversion failed: fmt:%s d:%s", fmt->CheckString(), d->CheckString());