Initial paraglob integration.

This commit is contained in:
ZekeMedley 2019-05-28 16:59:50 -07:00
parent f2b7764769
commit e1520a0d67
17 changed files with 302 additions and 3 deletions

View file

@ -869,3 +869,28 @@ void CardinalityVal::Add(const Val* val)
c->AddElement(key->Hash());
delete key;
}
ParaglobVal::ParaglobVal(paraglob::Paraglob* p)
: OpaqueVal(paraglob_type)
{
this->internal_paraglob = p;
}
VectorVal* ParaglobVal::get(StringVal* &pattern)
{
VectorVal* rval = new VectorVal(internal_type("string_vec")->AsVectorType());
std::string string_pattern (pattern->CheckString(), 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).c_str()));
}
return rval;
}
bool ParaglobVal::operator==(const ParaglobVal *other)
{
return (*(this->internal_paraglob) == *(other->internal_paraglob));
}

View file

@ -8,6 +8,7 @@
#include "RandTest.h"
#include "Val.h"
#include "digest.h"
#include "src/paraglob.h"
namespace probabilistic {
class BloomFilter;
@ -188,4 +189,14 @@ private:
DECLARE_SERIAL(CardinalityVal);
};
class ParaglobVal : public OpaqueVal {
public:
explicit ParaglobVal(paraglob::Paraglob* p);
VectorVal* get(StringVal* &pattern);
bool operator==(const ParaglobVal *other);
private:
paraglob::Paraglob* internal_paraglob;
};
#endif

View file

@ -639,6 +639,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

@ -789,6 +789,63 @@ 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 )
{
builtin_error("paraglob requires a vector 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(s->CheckString(), s->Len()));
}
return new ParaglobVal(new paraglob::Paraglob(patterns));
%}
## 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 of 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
%{
bool eq =
(static_cast<ParaglobVal*>(p_one) == static_cast<ParaglobVal*>(p_two));
return val_mgr->GetBool(eq);
%}
## 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>`_.
##
@ -3071,7 +3128,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());

View file

@ -224,7 +224,7 @@ ReaderBackend* Manager::CreateBackend(ReaderFrontend* frontend, EnumVal* tag)
return backend;
}
// Create a new input reader object to be used at whomevers leisure lateron.
// Create a new input reader object to be used at whomevers leisure later on.
bool Manager::CreateStream(Stream* info, RecordVal* description)
{
RecordType* rtype = description->Type()->AsRecordType();
@ -232,7 +232,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description)
|| same_type(rtype, BifType::Record::Input::EventDescription, 0)
|| same_type(rtype, BifType::Record::Input::AnalysisDescription, 0) ) )
{
reporter->Error("Streamdescription argument not of right type for new input stream");
reporter->Error("Stream description argument not of right type for new input stream");
return false;
}
@ -824,6 +824,7 @@ bool Manager::IsCompatibleType(BroType* t, bool atomic_only)
case TYPE_INTERVAL:
case TYPE_ENUM:
case TYPE_STRING:
case TYPE_PATTERN:
return true;
case TYPE_RECORD:
@ -2074,6 +2075,12 @@ int Manager::GetValueLength(const Value* val) const
}
break;
case TYPE_PATTERN:
{
length += strlen(val->val.pattern_text_val) + 1;
break;
}
case TYPE_TABLE:
{
for ( int i = 0; i < val->val.set_val.size; i++ )
@ -2193,6 +2200,14 @@ int Manager::CopyValue(char *data, const int startpos, const Value* val) const
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;
}
case TYPE_TABLE:
{
int length = 0;
@ -2350,6 +2365,13 @@ Val* Manager::ValueToVal(const Stream* i, const Value* val, BroType* request_typ
return subnetval;
}
case TYPE_PATTERN:
{
RE_Matcher* 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...
@ -2492,6 +2514,13 @@ Val* Manager::ValueToVal(const Stream* i, const Value* val, bool& have_error) co
return subnetval;
}
case TYPE_PATTERN:
{
RE_Matcher* re = new RE_Matcher(val->val.pattern_text_val);
re->Compile();
return new PatternVal(re);
}
case TYPE_TABLE:
{
TypeList* set_index;

View file

@ -122,6 +122,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;
@ -809,6 +810,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

@ -126,6 +126,7 @@ struct Value {
vec_t vector_val;
addr_t addr_val;
subnet_t subnet_val;
const char* pattern_text_val;
struct {
char* data;

View file

@ -325,6 +325,28 @@ threading::Value* Ascii::ParseValue(const string& s, const string& name, TypeTag
break;
}
case TYPE_PATTERN:
{
string cannidate = get_unescaped_string(s);
// A string is a cannidate 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 ( cannidate.size() >= 2 )
{
if ( cannidate.front() == cannidate.back() &&
cannidate.back() == '/' )
{
// Remove the '/'s
cannidate.erase(0, 1);
cannidate.erase(cannidate.size() - 1);
val->val.pattern_text_val = copy_string(cannidate.c_str());
break;
}
}
GetThread()->Error(GetThread()->Fmt("String '%s' contained no parseable pattern.", cannidate.c_str()));
goto parse_error;
}
case TYPE_TABLE:
case TYPE_VECTOR:
// First - common initialization