mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 15:48:19 +00:00
Merge remote-tracking branch 'origin/topic/johanna/bit-1199'
* origin/topic/johanna/bit-1199: add a basic leak test for an unparseable enum Change the way the input framework deals with values it cannot convert into BroVals (especially enums) Make error message when encountering not existing enums better. BIT-1199: #merged
This commit is contained in:
commit
88165ad72c
7 changed files with 310 additions and 135 deletions
|
@ -971,7 +971,7 @@ Val* Manager::RecordValToIndexVal(RecordVal *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Val* Manager::ValueToIndexVal(int num_fields, const RecordType *type, const Value* const *vals)
|
Val* Manager::ValueToIndexVal(const Stream* i, int num_fields, const RecordType *type, const Value* const *vals, bool& have_error)
|
||||||
{
|
{
|
||||||
Val* idxval;
|
Val* idxval;
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
@ -979,7 +979,7 @@ Val* Manager::ValueToIndexVal(int num_fields, const RecordType *type, const Valu
|
||||||
|
|
||||||
if ( num_fields == 1 && type->FieldType(0)->Tag() != TYPE_RECORD )
|
if ( num_fields == 1 && type->FieldType(0)->Tag() != TYPE_RECORD )
|
||||||
{
|
{
|
||||||
idxval = ValueToVal(vals[0], type->FieldType(0));
|
idxval = ValueToVal(i, vals[0], type->FieldType(0), have_error);
|
||||||
position = 1;
|
position = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -988,11 +988,11 @@ Val* Manager::ValueToIndexVal(int num_fields, const RecordType *type, const Valu
|
||||||
for ( int j = 0 ; j < type->NumFields(); j++ )
|
for ( int j = 0 ; j < type->NumFields(); j++ )
|
||||||
{
|
{
|
||||||
if ( type->FieldType(j)->Tag() == TYPE_RECORD )
|
if ( type->FieldType(j)->Tag() == TYPE_RECORD )
|
||||||
l->Append(ValueToRecordVal(vals,
|
l->Append(ValueToRecordVal(i, vals,
|
||||||
type->FieldType(j)->AsRecordType(), &position));
|
type->FieldType(j)->AsRecordType(), &position, have_error));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
l->Append(ValueToVal(vals[position], type->FieldType(j)));
|
l->Append(ValueToVal(i, vals[position], type->FieldType(j), have_error));
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1079,7 +1079,7 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
{
|
{
|
||||||
// seen before
|
// seen before
|
||||||
if ( stream->num_val_fields == 0 || h->valhash == valhash )
|
if ( stream->num_val_fields == 0 || h->valhash == valhash )
|
||||||
{
|
{
|
||||||
// ok, exact duplicate, move entry to new dicrionary and do nothing else.
|
// ok, exact duplicate, move entry to new dicrionary and do nothing else.
|
||||||
stream->lastDict->Remove(idxhash);
|
stream->lastDict->Remove(idxhash);
|
||||||
stream->currDict->Insert(idxhash, h);
|
stream->currDict->Insert(idxhash, h);
|
||||||
|
@ -1094,8 +1094,8 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
stream->lastDict->Remove(idxhash);
|
stream->lastDict->Remove(idxhash);
|
||||||
// keep h for predicates
|
// keep h for predicates
|
||||||
updated = true;
|
updated = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* valval;
|
Val* valval;
|
||||||
|
@ -1103,63 +1103,68 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
|
|
||||||
int position = stream->num_idx_fields;
|
int position = stream->num_idx_fields;
|
||||||
|
|
||||||
|
bool convert_error = false; // this will be set to true by ValueTo* on Error
|
||||||
|
|
||||||
if ( stream->num_val_fields == 0 )
|
if ( stream->num_val_fields == 0 )
|
||||||
valval = 0;
|
valval = 0;
|
||||||
|
|
||||||
else if ( stream->num_val_fields == 1 && !stream->want_record )
|
else if ( stream->num_val_fields == 1 && !stream->want_record )
|
||||||
valval = ValueToVal(vals[position], stream->rtype->FieldType(0));
|
valval = ValueToVal(i, vals[position], stream->rtype->FieldType(0), convert_error);
|
||||||
|
|
||||||
else
|
else
|
||||||
valval = ValueToRecordVal(vals, stream->rtype, &position);
|
valval = ValueToRecordVal(i, vals, stream->rtype, &position, convert_error);
|
||||||
|
|
||||||
|
|
||||||
// call stream first to determine if we really add / change the entry
|
// call stream first to determine if we really add / change the entry
|
||||||
if ( stream->pred )
|
if ( stream->pred && ! convert_error )
|
||||||
{
|
{
|
||||||
EnumVal* ev;
|
EnumVal* ev;
|
||||||
int startpos = 0;
|
int startpos = 0;
|
||||||
predidx = ValueToRecordVal(vals, stream->itype, &startpos);
|
bool pred_convert_error = false;
|
||||||
|
predidx = ValueToRecordVal(i, vals, stream->itype, &startpos, pred_convert_error);
|
||||||
|
|
||||||
if ( updated )
|
// if we encountered a convert error here - just continue as we would have without
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
|
// emitting the event. I do not really think that that can happen just here and not
|
||||||
else
|
// at the top-level. But - this is safe.
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
if ( ! pred_convert_error )
|
||||||
|
|
||||||
bool result;
|
|
||||||
if ( stream->num_val_fields > 0 ) // we have values
|
|
||||||
result = CallPred(stream->pred, 3, ev, predidx->Ref(), valval->Ref());
|
|
||||||
else // no values
|
|
||||||
result = CallPred(stream->pred, 2, ev, predidx->Ref());
|
|
||||||
|
|
||||||
if ( result == false )
|
|
||||||
{
|
{
|
||||||
Unref(predidx);
|
if ( updated )
|
||||||
Unref(valval);
|
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
|
||||||
|
|
||||||
if ( ! updated )
|
|
||||||
{
|
|
||||||
// just quit and delete everything we created.
|
|
||||||
delete idxhash;
|
|
||||||
return stream->num_val_fields + stream->num_idx_fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
if ( stream->num_val_fields > 0 ) // we have values
|
||||||
|
result = CallPred(stream->pred, 3, ev, predidx->Ref(), valval->Ref());
|
||||||
|
else // no values
|
||||||
|
result = CallPred(stream->pred, 2, ev, predidx->Ref());
|
||||||
|
|
||||||
|
if ( result == false )
|
||||||
{
|
{
|
||||||
// keep old one
|
Unref(predidx);
|
||||||
stream->currDict->Insert(idxhash, h);
|
Unref(valval);
|
||||||
delete idxhash;
|
|
||||||
return stream->num_val_fields + stream->num_idx_fields;
|
if ( ! updated )
|
||||||
|
{
|
||||||
|
// just quit and delete everything we created.
|
||||||
|
delete idxhash;
|
||||||
|
return stream->num_val_fields + stream->num_idx_fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// keep old one
|
||||||
|
stream->currDict->Insert(idxhash, h);
|
||||||
|
delete idxhash;
|
||||||
|
return stream->num_val_fields + stream->num_idx_fields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we don't need h anymore - if we are here, the entry is updated and a new h is created.
|
// now we don't need h anymore - if we are here, the entry is updated and a new h is created.
|
||||||
if ( h )
|
delete h;
|
||||||
{
|
h = 0;
|
||||||
delete h;
|
|
||||||
h = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Val* idxval;
|
Val* idxval;
|
||||||
if ( predidx != 0 )
|
if ( predidx != 0 )
|
||||||
|
@ -1168,7 +1173,20 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
// I think there is an unref missing here. But if I insert is, it crashes :)
|
// I think there is an unref missing here. But if I insert is, it crashes :)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
idxval = ValueToIndexVal(stream->num_idx_fields, stream->itype, vals);
|
idxval = ValueToIndexVal(i, stream->num_idx_fields, stream->itype, vals, convert_error);
|
||||||
|
|
||||||
|
if ( convert_error )
|
||||||
|
{
|
||||||
|
// abort here and free everything that was allocated so far.
|
||||||
|
Unref(predidx);
|
||||||
|
Unref(valval);
|
||||||
|
Unref(idxval);
|
||||||
|
|
||||||
|
delete idxhash;
|
||||||
|
return stream->num_val_fields + stream->num_idx_fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(idxval);
|
||||||
|
|
||||||
Val* oldval = 0;
|
Val* oldval = 0;
|
||||||
if ( updated == true )
|
if ( updated == true )
|
||||||
|
@ -1178,7 +1196,6 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
oldval = stream->tab->Lookup(idxval, false);
|
oldval = stream->tab->Lookup(idxval, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(idxval);
|
|
||||||
HashKey* k = stream->tab->ComputeHash(idxval);
|
HashKey* k = stream->tab->ComputeHash(idxval);
|
||||||
if ( ! k )
|
if ( ! k )
|
||||||
reporter->InternalError("could not hash");
|
reporter->InternalError("could not hash");
|
||||||
|
@ -1203,16 +1220,21 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
{
|
{
|
||||||
EnumVal* ev;
|
EnumVal* ev;
|
||||||
int startpos = 0;
|
int startpos = 0;
|
||||||
Val* predidx = ValueToRecordVal(vals, stream->itype, &startpos);
|
Val* predidx = ValueToRecordVal(i, vals, stream->itype, &startpos, convert_error);
|
||||||
|
|
||||||
if ( updated )
|
if ( convert_error )
|
||||||
|
{
|
||||||
|
// the only thing to clean up here is predidx. Everything else should
|
||||||
|
// already be ok again
|
||||||
|
Unref(predidx);
|
||||||
|
}
|
||||||
|
else if ( updated )
|
||||||
{ // in case of update send back the old value.
|
{ // in case of update send back the old value.
|
||||||
assert ( stream->num_val_fields > 0 );
|
assert ( stream->num_val_fields > 0 );
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
|
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED, BifType::Enum::Input::Event);
|
||||||
assert ( oldval != 0 );
|
assert ( oldval != 0 );
|
||||||
SendEvent(stream->event, 4, stream->description->Ref(), ev, predidx, oldval);
|
SendEvent(stream->event, 4, stream->description->Ref(), ev, predidx, oldval);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
ev = new EnumVal(BifEnum::Input::EVENT_NEW, BifType::Enum::Input::Event);
|
||||||
|
@ -1223,7 +1245,6 @@ int Manager::SendEntryTable(Stream* i, const Value* const *vals)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendEvent(stream->event, 4, stream->description->Ref(), ev, predidx, valval->Ref());
|
SendEvent(stream->event, 4, stream->description->Ref(), ev, predidx, valval->Ref());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1416,7 +1437,6 @@ int Manager::SendEventStreamEvent(Stream* i, EnumVal* type, const Value* const *
|
||||||
assert(i->stream_type == EVENT_STREAM);
|
assert(i->stream_type == EVENT_STREAM);
|
||||||
EventStream* stream = (EventStream*) i;
|
EventStream* stream = (EventStream*) i;
|
||||||
|
|
||||||
Val *val;
|
|
||||||
list<Val*> out_vals;
|
list<Val*> out_vals;
|
||||||
Ref(stream->description);
|
Ref(stream->description);
|
||||||
out_vals.push_back(stream->description);
|
out_vals.push_back(stream->description);
|
||||||
|
@ -1425,9 +1445,11 @@ int Manager::SendEventStreamEvent(Stream* i, EnumVal* type, const Value* const *
|
||||||
|
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
|
||||||
|
bool convert_error = false;
|
||||||
|
|
||||||
if ( stream->want_record )
|
if ( stream->want_record )
|
||||||
{
|
{
|
||||||
RecordVal * r = ValueToRecordVal(vals, stream->fields, &position);
|
RecordVal * r = ValueToRecordVal(i, vals, stream->fields, &position, convert_error);
|
||||||
out_vals.push_back(r);
|
out_vals.push_back(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1438,13 +1460,13 @@ int Manager::SendEventStreamEvent(Stream* i, EnumVal* type, const Value* const *
|
||||||
Val* val = 0;
|
Val* val = 0;
|
||||||
|
|
||||||
if ( stream->fields->FieldType(j)->Tag() == TYPE_RECORD )
|
if ( stream->fields->FieldType(j)->Tag() == TYPE_RECORD )
|
||||||
val = ValueToRecordVal(vals,
|
val = ValueToRecordVal(i, vals,
|
||||||
stream->fields->FieldType(j)->AsRecordType(),
|
stream->fields->FieldType(j)->AsRecordType(),
|
||||||
&position);
|
&position, convert_error);
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
val = ValueToVal(vals[position], stream->fields->FieldType(j));
|
val = ValueToVal(i, vals[position], stream->fields->FieldType(j), convert_error);
|
||||||
position++;
|
position++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1452,7 +1474,14 @@ int Manager::SendEventStreamEvent(Stream* i, EnumVal* type, const Value* const *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendEvent(stream->event, out_vals);
|
if ( convert_error )
|
||||||
|
{
|
||||||
|
// we have an error somewhere in our out_vals. Just delete all of them.
|
||||||
|
for ( list<Val*>::const_iterator it = out_vals.begin(), end = out_vals.end(); it != end; ++it )
|
||||||
|
Unref(*it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SendEvent(stream->event, out_vals);
|
||||||
|
|
||||||
return stream->num_fields;
|
return stream->num_fields;
|
||||||
}
|
}
|
||||||
|
@ -1464,7 +1493,9 @@ int Manager::PutTable(Stream* i, const Value* const *vals)
|
||||||
assert(i->stream_type == TABLE_STREAM);
|
assert(i->stream_type == TABLE_STREAM);
|
||||||
TableStream* stream = (TableStream*) i;
|
TableStream* stream = (TableStream*) i;
|
||||||
|
|
||||||
Val* idxval = ValueToIndexVal(stream->num_idx_fields, stream->itype, vals);
|
bool convert_error = 0;
|
||||||
|
|
||||||
|
Val* idxval = ValueToIndexVal(i, stream->num_idx_fields, stream->itype, vals, convert_error);
|
||||||
Val* valval;
|
Val* valval;
|
||||||
|
|
||||||
int position = stream->num_idx_fields;
|
int position = stream->num_idx_fields;
|
||||||
|
@ -1473,9 +1504,16 @@ int Manager::PutTable(Stream* i, const Value* const *vals)
|
||||||
valval = 0;
|
valval = 0;
|
||||||
|
|
||||||
else if ( stream->num_val_fields == 1 && stream->want_record == 0 )
|
else if ( stream->num_val_fields == 1 && stream->want_record == 0 )
|
||||||
valval = ValueToVal(vals[position], stream->rtype->FieldType(0));
|
valval = ValueToVal(i, vals[position], stream->rtype->FieldType(0), convert_error);
|
||||||
else
|
else
|
||||||
valval = ValueToRecordVal(vals, stream->rtype, &position);
|
valval = ValueToRecordVal(i, vals, stream->rtype, &position, convert_error);
|
||||||
|
|
||||||
|
if ( convert_error )
|
||||||
|
{
|
||||||
|
Unref(valval);
|
||||||
|
Unref(idxval);
|
||||||
|
return stream->num_idx_fields + stream->num_val_fields;
|
||||||
|
}
|
||||||
|
|
||||||
// if we have a subscribed event, we need to figure out, if this is an update or not
|
// if we have a subscribed event, we need to figure out, if this is an update or not
|
||||||
// same for predicates
|
// same for predicates
|
||||||
|
@ -1503,31 +1541,37 @@ int Manager::PutTable(Stream* i, const Value* const *vals)
|
||||||
{
|
{
|
||||||
EnumVal* ev;
|
EnumVal* ev;
|
||||||
int startpos = 0;
|
int startpos = 0;
|
||||||
Val* predidx = ValueToRecordVal(vals, stream->itype, &startpos);
|
bool pred_convert_error = false;
|
||||||
|
Val* predidx = ValueToRecordVal(i, vals, stream->itype, &startpos, pred_convert_error);
|
||||||
|
|
||||||
if ( updated )
|
if ( pred_convert_error )
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED,
|
Unref(predidx);
|
||||||
BifType::Enum::Input::Event);
|
|
||||||
else
|
else
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_NEW,
|
|
||||||
BifType::Enum::Input::Event);
|
|
||||||
|
|
||||||
bool result;
|
|
||||||
if ( stream->num_val_fields > 0 ) // we have values
|
|
||||||
{
|
{
|
||||||
Ref(valval);
|
if ( updated )
|
||||||
result = CallPred(stream->pred, 3, ev, predidx, valval);
|
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED,
|
||||||
}
|
BifType::Enum::Input::Event);
|
||||||
else // no values
|
else
|
||||||
result = CallPred(stream->pred, 2, ev, predidx);
|
ev = new EnumVal(BifEnum::Input::EVENT_NEW,
|
||||||
|
BifType::Enum::Input::Event);
|
||||||
|
|
||||||
if ( result == false )
|
bool result;
|
||||||
{
|
if ( stream->num_val_fields > 0 ) // we have values
|
||||||
// do nothing
|
{
|
||||||
Unref(idxval);
|
Ref(valval);
|
||||||
Unref(valval);
|
result = CallPred(stream->pred, 3, ev, predidx, valval);
|
||||||
Unref(oldval);
|
}
|
||||||
return stream->num_val_fields + stream->num_idx_fields;
|
else // no values
|
||||||
|
result = CallPred(stream->pred, 2, ev, predidx);
|
||||||
|
|
||||||
|
if ( result == false )
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
Unref(idxval);
|
||||||
|
Unref(valval);
|
||||||
|
Unref(oldval);
|
||||||
|
return stream->num_val_fields + stream->num_idx_fields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1538,28 +1582,34 @@ int Manager::PutTable(Stream* i, const Value* const *vals)
|
||||||
{
|
{
|
||||||
EnumVal* ev;
|
EnumVal* ev;
|
||||||
int startpos = 0;
|
int startpos = 0;
|
||||||
Val* predidx = ValueToRecordVal(vals, stream->itype, &startpos);
|
bool event_convert_error = false;
|
||||||
|
Val* predidx = ValueToRecordVal(i, vals, stream->itype, &startpos, event_convert_error);
|
||||||
|
|
||||||
if ( updated )
|
if ( event_convert_error )
|
||||||
{
|
Unref(predidx);
|
||||||
// in case of update send back the old value.
|
|
||||||
assert ( stream->num_val_fields > 0 );
|
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED,
|
|
||||||
BifType::Enum::Input::Event);
|
|
||||||
assert ( oldval != 0 );
|
|
||||||
SendEvent(stream->event, 4, stream->description->Ref(),
|
|
||||||
ev, predidx, oldval);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ev = new EnumVal(BifEnum::Input::EVENT_NEW,
|
if ( updated )
|
||||||
BifType::Enum::Input::Event);
|
{
|
||||||
if ( stream->num_val_fields == 0 )
|
// in case of update send back the old value.
|
||||||
|
assert ( stream->num_val_fields > 0 );
|
||||||
|
ev = new EnumVal(BifEnum::Input::EVENT_CHANGED,
|
||||||
|
BifType::Enum::Input::Event);
|
||||||
|
assert ( oldval != 0 );
|
||||||
SendEvent(stream->event, 4, stream->description->Ref(),
|
SendEvent(stream->event, 4, stream->description->Ref(),
|
||||||
ev, predidx);
|
ev, predidx, oldval);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SendEvent(stream->event, 4, stream->description->Ref(),
|
{
|
||||||
ev, predidx, valval->Ref());
|
ev = new EnumVal(BifEnum::Input::EVENT_NEW,
|
||||||
|
BifType::Enum::Input::Event);
|
||||||
|
if ( stream->num_val_fields == 0 )
|
||||||
|
SendEvent(stream->event, 4, stream->description->Ref(),
|
||||||
|
ev, predidx);
|
||||||
|
else
|
||||||
|
SendEvent(stream->event, 4, stream->description->Ref(),
|
||||||
|
ev, predidx, valval->Ref());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1612,29 +1662,42 @@ bool Manager::Delete(ReaderFrontend* reader, Value* *vals)
|
||||||
if ( i->stream_type == TABLE_STREAM )
|
if ( i->stream_type == TABLE_STREAM )
|
||||||
{
|
{
|
||||||
TableStream* stream = (TableStream*) i;
|
TableStream* stream = (TableStream*) i;
|
||||||
Val* idxval = ValueToIndexVal(stream->num_idx_fields, stream->itype, vals);
|
bool convert_error = false;
|
||||||
|
Val* idxval = ValueToIndexVal(i, stream->num_idx_fields, stream->itype, vals, convert_error);
|
||||||
assert(idxval != 0);
|
assert(idxval != 0);
|
||||||
readVals = stream->num_idx_fields + stream->num_val_fields;
|
readVals = stream->num_idx_fields + stream->num_val_fields;
|
||||||
bool streamresult = true;
|
bool streamresult = true;
|
||||||
|
|
||||||
|
if ( convert_error )
|
||||||
|
{
|
||||||
|
Unref(idxval);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ( stream->pred || stream->event )
|
if ( stream->pred || stream->event )
|
||||||
{
|
{
|
||||||
Val *val = stream->tab->Lookup(idxval);
|
Val *val = stream->tab->Lookup(idxval);
|
||||||
|
|
||||||
if ( stream->pred )
|
if ( stream->pred )
|
||||||
{
|
{
|
||||||
Ref(val);
|
|
||||||
EnumVal *ev = new EnumVal(BifEnum::Input::EVENT_REMOVED, BifType::Enum::Input::Event);
|
|
||||||
int startpos = 0;
|
int startpos = 0;
|
||||||
Val* predidx = ValueToRecordVal(vals, stream->itype, &startpos);
|
Val* predidx = ValueToRecordVal(i, vals, stream->itype, &startpos, convert_error);
|
||||||
|
|
||||||
streamresult = CallPred(stream->pred, 3, ev, predidx, val);
|
if ( convert_error )
|
||||||
|
Unref(predidx);
|
||||||
if ( streamresult == false )
|
else
|
||||||
{
|
{
|
||||||
// keep it.
|
Ref(val);
|
||||||
Unref(idxval);
|
EnumVal *ev = new EnumVal(BifEnum::Input::EVENT_REMOVED, BifType::Enum::Input::Event);
|
||||||
success = true;
|
|
||||||
|
streamresult = CallPred(stream->pred, 3, ev, predidx, val);
|
||||||
|
|
||||||
|
if ( streamresult == false )
|
||||||
|
{
|
||||||
|
// keep it.
|
||||||
|
Unref(idxval);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1708,8 +1771,15 @@ bool Manager::CallPred(Func* pred_func, const int numvals, ...)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Manager::SendEvent(const string& name, const int num_vals, Value* *vals)
|
bool Manager::SendEvent(ReaderFrontend* reader, const string& name, const int num_vals, Value* *vals)
|
||||||
{
|
{
|
||||||
|
Stream *i = FindStream(reader);
|
||||||
|
if ( i == 0 )
|
||||||
|
{
|
||||||
|
reporter->InternalWarning("Unknown reader %s in SendEvent for event %s", reader->Name(), name.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
EventHandler* handler = event_registry->Lookup(name.c_str());
|
EventHandler* handler = event_registry->Lookup(name.c_str());
|
||||||
if ( handler == 0 )
|
if ( handler == 0 )
|
||||||
{
|
{
|
||||||
|
@ -1732,13 +1802,22 @@ bool Manager::SendEvent(const string& name, const int num_vals, Value* *vals)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
val_list* vl = new val_list;
|
bool convert_error = false;
|
||||||
for ( int i = 0; i < num_vals; i++)
|
|
||||||
vl->append(ValueToVal(vals[i], type->FieldType(i)));
|
|
||||||
|
|
||||||
mgr.QueueEvent(handler, vl, SOURCE_LOCAL);
|
val_list* vl = new val_list;
|
||||||
|
for ( int j = 0; j < num_vals; j++)
|
||||||
|
vl->append(ValueToVal(i, vals[j], type->FieldType(j), convert_error));
|
||||||
|
|
||||||
delete_value_ptr_array(vals, num_vals);
|
delete_value_ptr_array(vals, num_vals);
|
||||||
|
|
||||||
|
if ( convert_error )
|
||||||
|
{
|
||||||
|
delete_vals(vl);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mgr.QueueEvent(handler, vl, SOURCE_LOCAL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1809,8 +1888,8 @@ RecordVal* Manager::ListValToRecordVal(ListVal* list, RecordType *request_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a threading value to a record value
|
// Convert a threading value to a record value
|
||||||
RecordVal* Manager::ValueToRecordVal(const Value* const *vals,
|
RecordVal* Manager::ValueToRecordVal(const Stream* stream, const Value* const *vals,
|
||||||
RecordType *request_type, int* position)
|
RecordType *request_type, int* position, bool& have_error)
|
||||||
{
|
{
|
||||||
assert(position != 0); // we need the pointer to point to data.
|
assert(position != 0); // we need the pointer to point to data.
|
||||||
|
|
||||||
|
@ -1819,7 +1898,7 @@ RecordVal* Manager::ValueToRecordVal(const Value* const *vals,
|
||||||
{
|
{
|
||||||
Val* fieldVal = 0;
|
Val* fieldVal = 0;
|
||||||
if ( request_type->FieldType(i)->Tag() == TYPE_RECORD )
|
if ( request_type->FieldType(i)->Tag() == TYPE_RECORD )
|
||||||
fieldVal = ValueToRecordVal(vals, request_type->FieldType(i)->AsRecordType(), position);
|
fieldVal = ValueToRecordVal(stream, vals, request_type->FieldType(i)->AsRecordType(), position, have_error);
|
||||||
else if ( request_type->FieldType(i)->Tag() == TYPE_FILE ||
|
else if ( request_type->FieldType(i)->Tag() == TYPE_FILE ||
|
||||||
request_type->FieldType(i)->Tag() == TYPE_FUNC )
|
request_type->FieldType(i)->Tag() == TYPE_FUNC )
|
||||||
{
|
{
|
||||||
|
@ -1834,7 +1913,7 @@ RecordVal* Manager::ValueToRecordVal(const Value* const *vals,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fieldVal = ValueToVal(vals[*position], request_type->FieldType(i));
|
fieldVal = ValueToVal(stream, vals[*position], request_type->FieldType(i), have_error);
|
||||||
(*position)++;
|
(*position)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2103,12 +2182,17 @@ HashKey* Manager::HashValues(const int num_elements, const Value* const *vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert threading value to Bro value
|
// convert threading value to Bro value
|
||||||
Val* Manager::ValueToVal(const Value* val, BroType* request_type)
|
// have_error is a reference to a boolean which is set to true as soon as an error occured.
|
||||||
|
// When have_error is set to true at the beginning of the function, it is assumed that
|
||||||
|
// an error already occured in the past and processing is aborted.
|
||||||
|
Val* Manager::ValueToVal(const Stream* i, const Value* val, BroType* request_type, bool& have_error)
|
||||||
{
|
{
|
||||||
|
if ( have_error )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if ( request_type->Tag() != TYPE_ANY && request_type->Tag() != val->type )
|
if ( request_type->Tag() != TYPE_ANY && request_type->Tag() != val->type )
|
||||||
{
|
{
|
||||||
reporter->InternalError("Typetags don't match: %d vs %d", request_type->Tag(), val->type);
|
reporter->InternalError("Typetags don't match: %d vs %d in stream %s", request_type->Tag(), val->type, i->name.c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2189,11 +2273,12 @@ Val* Manager::ValueToVal(const Value* val, BroType* request_type)
|
||||||
set_index->Append(type->Ref());
|
set_index->Append(type->Ref());
|
||||||
SetType* s = new SetType(set_index, 0);
|
SetType* s = new SetType(set_index, 0);
|
||||||
TableVal* t = new TableVal(s);
|
TableVal* t = new TableVal(s);
|
||||||
for ( int i = 0; i < val->val.set_val.size; i++ )
|
for ( int j = 0; j < val->val.set_val.size; j++ )
|
||||||
{
|
{
|
||||||
Val* assignval = ValueToVal( val->val.set_val.vals[i], type );
|
Val* assignval = ValueToVal(i, val->val.set_val.vals[j], type, have_error);
|
||||||
|
|
||||||
t->Assign(assignval, 0);
|
t->Assign(assignval, 0);
|
||||||
Unref(assignval); // idex is not consumed by assign.
|
Unref(assignval); // index is not consumed by assign.
|
||||||
}
|
}
|
||||||
|
|
||||||
Unref(s);
|
Unref(s);
|
||||||
|
@ -2206,8 +2291,10 @@ Val* Manager::ValueToVal(const Value* val, BroType* request_type)
|
||||||
BroType* type = request_type->AsVectorType()->YieldType();
|
BroType* type = request_type->AsVectorType()->YieldType();
|
||||||
VectorType* vt = new VectorType(type->Ref());
|
VectorType* vt = new VectorType(type->Ref());
|
||||||
VectorVal* v = new VectorVal(vt);
|
VectorVal* v = new VectorVal(vt);
|
||||||
for ( int i = 0; i < val->val.vector_val.size; i++ )
|
for ( int j = 0; j < val->val.vector_val.size; j++ )
|
||||||
v->Assign(i, ValueToVal( val->val.set_val.vals[i], type ));
|
{
|
||||||
|
v->Assign(j, ValueToVal(i, val->val.set_val.vals[j], type, have_error));
|
||||||
|
}
|
||||||
|
|
||||||
Unref(vt);
|
Unref(vt);
|
||||||
return v;
|
return v;
|
||||||
|
@ -2216,25 +2303,29 @@ Val* Manager::ValueToVal(const Value* val, BroType* request_type)
|
||||||
case TYPE_ENUM: {
|
case TYPE_ENUM: {
|
||||||
// Convert to string first to not have to deal with missing
|
// Convert to string first to not have to deal with missing
|
||||||
// \0's...
|
// \0's...
|
||||||
string module_string(val->val.string_val.data, val->val.string_val.length);
|
string enum_string(val->val.string_val.data, val->val.string_val.length);
|
||||||
string var_string(val->val.string_val.data, val->val.string_val.length);
|
|
||||||
|
|
||||||
string module = extract_module_name(module_string.c_str());
|
string module = extract_module_name(enum_string.c_str());
|
||||||
string var = extract_var_name(var_string.c_str());
|
string var = extract_var_name(enum_string.c_str());
|
||||||
|
|
||||||
// Well, this is kind of stupid, because EnumType just
|
// Well, this is kind of stupid, because EnumType just
|
||||||
// mangles the module name and the var name together again...
|
// mangles the module name and the var name together again...
|
||||||
// but well.
|
// but well.
|
||||||
bro_int_t index = request_type->AsEnumType()->Lookup(module, var.c_str());
|
bro_int_t index = request_type->AsEnumType()->Lookup(module, var.c_str());
|
||||||
if ( index == -1 )
|
if ( index == -1 )
|
||||||
reporter->InternalError("Value not found in enum mappimg. Module: %s, var: %s, var size: %zu",
|
{
|
||||||
module.c_str(), var.c_str(), var.size());
|
reporter->Error("Value not '%s' for stream '%s' is not a valid enum.",
|
||||||
|
enum_string.c_str(), i->name.c_str());
|
||||||
|
|
||||||
|
have_error = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return new EnumVal(index, request_type->Ref()->AsEnumType());
|
return new EnumVal(index, request_type->Ref()->AsEnumType());
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
reporter->InternalError("unsupported type for input_read");
|
reporter->InternalError("Unsupported type for input_read in stream %s", i->name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|
|
@ -129,7 +129,7 @@ protected:
|
||||||
// Allows readers to directly send Bro events. The num_vals and vals
|
// Allows readers to directly send Bro events. The num_vals and vals
|
||||||
// must be the same the named event expects. Takes ownership of
|
// must be the same the named event expects. Takes ownership of
|
||||||
// threading::Value fields.
|
// threading::Value fields.
|
||||||
bool SendEvent(const string& name, const int num_vals, threading::Value* *vals);
|
bool SendEvent(ReaderFrontend* reader, const string& name, const int num_vals, threading::Value* *vals);
|
||||||
|
|
||||||
// Instantiates a new ReaderBackend of the given type (note that
|
// Instantiates a new ReaderBackend of the given type (note that
|
||||||
// doing so creates a new thread!).
|
// doing so creates a new thread!).
|
||||||
|
@ -205,14 +205,14 @@ private:
|
||||||
|
|
||||||
// Convert Threading::Value to an internal Bro Type (works also with
|
// Convert Threading::Value to an internal Bro Type (works also with
|
||||||
// Records).
|
// Records).
|
||||||
Val* ValueToVal(const threading::Value* val, BroType* request_type);
|
Val* ValueToVal(const Stream* i, const threading::Value* val, BroType* request_type, bool& have_error);
|
||||||
|
|
||||||
// Convert Threading::Value to an internal Bro List type.
|
// Convert Threading::Value to an internal Bro List type.
|
||||||
Val* ValueToIndexVal(int num_fields, const RecordType* type, const threading::Value* const *vals);
|
Val* ValueToIndexVal(const Stream* i, int num_fields, const RecordType* type, const threading::Value* const *vals, bool& have_error);
|
||||||
|
|
||||||
// Converts a threading::value to a record type. Mostly used by
|
// Converts a threading::value to a record type. Mostly used by
|
||||||
// ValueToVal.
|
// ValueToVal.
|
||||||
RecordVal* ValueToRecordVal(const threading::Value* const *vals, RecordType *request_type, int* position);
|
RecordVal* ValueToRecordVal(const Stream* i, const threading::Value* const *vals, RecordType *request_type, int* position, bool& have_error);
|
||||||
|
|
||||||
Val* RecordValToIndexVal(RecordVal *r);
|
Val* RecordValToIndexVal(RecordVal *r);
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
|
|
||||||
virtual bool Process()
|
virtual bool Process()
|
||||||
{
|
{
|
||||||
bool success = input_mgr->SendEvent(name, num_vals, val);
|
bool success = input_mgr->SendEvent(Object(), name, num_vals, val);
|
||||||
|
|
||||||
if ( ! success )
|
if ( ! success )
|
||||||
reporter->Error("SendEvent for event %s failed", name);
|
reporter->Error("SendEvent for event %s failed", name);
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
error: Value not 'IdoNot::Exist' for stream 'enum' is not a valid enum.
|
||||||
|
received termination signal
|
|
@ -0,0 +1,4 @@
|
||||||
|
Table:
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
41
testing/btest/core/leaks/input-missing-enum.bro
Normal file
41
testing/btest/core/leaks/input-missing-enum.bro
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# Needs perftools support.
|
||||||
|
#
|
||||||
|
# @TEST-GROUP: leaks
|
||||||
|
#
|
||||||
|
# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local btest-bg-run bro bro -m -b %INPUT
|
||||||
|
# @TEST-EXEC: btest-bg-wait 15
|
||||||
|
|
||||||
|
@TEST-START-FILE input.log
|
||||||
|
#fields e i
|
||||||
|
IdoNot::Exist 1
|
||||||
|
@TEST-END-FILE
|
||||||
|
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
|
||||||
|
module A;
|
||||||
|
|
||||||
|
type Idx: record {
|
||||||
|
i: int;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Val: record {
|
||||||
|
e: Log::ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
global etable: table[int] of Log::ID = table();
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# first read in the old stuff into the table...
|
||||||
|
Input::add_table([$source="../input.log", $name="enum", $idx=Idx, $val=Val, $destination=etable, $want_record=F]);
|
||||||
|
}
|
||||||
|
|
||||||
|
event Input::end_of_data(name: string, source:string)
|
||||||
|
{
|
||||||
|
print "Table:";
|
||||||
|
print etable;
|
||||||
|
Input::remove("enum");
|
||||||
|
terminate();
|
||||||
|
}
|
37
testing/btest/scripts/base/frameworks/input/missing-enum.bro
Normal file
37
testing/btest/scripts/base/frameworks/input/missing-enum.bro
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# @TEST-EXEC: btest-bg-run bro bro -b %INPUT
|
||||||
|
# @TEST-EXEC: btest-bg-wait 10
|
||||||
|
# @TEST-EXEC: btest-diff bro/.stderr
|
||||||
|
# @TEST-EXEC: btest-diff bro/.stdout
|
||||||
|
|
||||||
|
@TEST-START-FILE input.log
|
||||||
|
#fields e i
|
||||||
|
IdoNot::Exist 1
|
||||||
|
@TEST-END-FILE
|
||||||
|
|
||||||
|
redef exit_only_after_terminate = T;
|
||||||
|
|
||||||
|
module A;
|
||||||
|
|
||||||
|
type Idx: record {
|
||||||
|
i: int;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Val: record {
|
||||||
|
e: Log::ID;
|
||||||
|
};
|
||||||
|
|
||||||
|
global etable: table[int] of Log::ID = table();
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# first read in the old stuff into the table...
|
||||||
|
Input::add_table([$source="../input.log", $name="enum", $idx=Idx, $val=Val, $destination=etable, $want_record=F]);
|
||||||
|
}
|
||||||
|
|
||||||
|
event Input::end_of_data(name: string, source:string)
|
||||||
|
{
|
||||||
|
print "Table:";
|
||||||
|
print etable;
|
||||||
|
Input::remove("enum");
|
||||||
|
terminate();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue