mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
input/Manager: Improve type checks of record fields with type any
Calling AsRecordType() or AsFunc() on a Val of type any isn't safe. Closes #3836
This commit is contained in:
parent
0ba80d13b4
commit
3797622152
3 changed files with 70 additions and 1 deletions
|
@ -264,6 +264,15 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Return true if v is a TypeVal that contains a record type, else false;
|
||||
static bool is_record_type_val(const zeek::ValPtr& v) {
|
||||
const auto& t = v->GetType();
|
||||
return t->Tag() == TYPE_TYPE && t->AsTypeType()->GetType()->Tag() == TYPE_RECORD;
|
||||
}
|
||||
|
||||
// Return true if v contains is not nil and contains a FuncVal, else false;
|
||||
static bool is_func_val(const zeek::ValPtr& v) { return v->GetType()->Tag() == TYPE_FUNC; }
|
||||
|
||||
bool Manager::CreateEventStream(RecordVal* fval) {
|
||||
RecordType* rtype = fval->GetType()->AsRecordType();
|
||||
if ( ! same_type(rtype, BifType::Record::Input::EventDescription, false) ) {
|
||||
|
@ -274,11 +283,21 @@ bool Manager::CreateEventStream(RecordVal* fval) {
|
|||
string stream_name = fval->GetFieldOrDefault("name")->AsString()->CheckString();
|
||||
|
||||
auto fields_val = fval->GetFieldOrDefault("fields");
|
||||
if ( ! is_record_type_val(fields_val) ) {
|
||||
reporter->Error("Input stream %s: 'idx' field is not a record type", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
RecordType* fields = fields_val->AsType()->AsTypeType()->GetType()->AsRecordType();
|
||||
|
||||
auto want_record = fval->GetFieldOrDefault("want_record");
|
||||
|
||||
auto ev_val = fval->GetFieldOrDefault("ev");
|
||||
if ( ev_val && ! is_func_val(ev_val) ) {
|
||||
reporter->Error("Input stream %s: 'ev' field is not an event", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Func* event = ev_val->AsFunc();
|
||||
|
||||
const auto& etype = event->GetType();
|
||||
|
@ -356,6 +375,11 @@ bool Manager::CreateEventStream(RecordVal* fval) {
|
|||
assert(false);
|
||||
|
||||
auto error_event_val = fval->GetFieldOrDefault("error_ev");
|
||||
if ( error_event_val && ! is_func_val(error_event_val) ) {
|
||||
reporter->Error("Input stream %s: 'error_ev' field is not an event", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Func* error_event = error_event_val ? error_event_val->AsFunc() : nullptr;
|
||||
|
||||
if ( ! CheckErrorEventTypes(stream_name, error_event, false) )
|
||||
|
@ -414,15 +438,31 @@ bool Manager::CreateTableStream(RecordVal* fval) {
|
|||
|
||||
auto pred = fval->GetFieldOrDefault("pred");
|
||||
auto idx_val = fval->GetFieldOrDefault("idx");
|
||||
if ( ! is_record_type_val(idx_val) ) {
|
||||
reporter->Error("Input stream %s: 'idx' field is not a record type", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
RecordType* idx = idx_val->AsType()->AsTypeType()->GetType()->AsRecordType();
|
||||
|
||||
RecordTypePtr val;
|
||||
auto val_val = fval->GetFieldOrDefault("val");
|
||||
|
||||
if ( val_val )
|
||||
if ( val_val ) {
|
||||
if ( ! is_record_type_val(val_val) ) {
|
||||
reporter->Error("Input stream %s: 'val' field is not a record type", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
val = val_val->AsType()->AsTypeType()->GetType<RecordType>();
|
||||
}
|
||||
|
||||
auto dst = fval->GetFieldOrDefault("destination");
|
||||
if ( ! dst->GetType()->IsSet() && ! dst->GetType()->IsTable() ) {
|
||||
reporter->Error("Input stream %s: 'destination' field has type %s, expected table or set identifier",
|
||||
stream_name.c_str(), obj_desc_short(dst->GetType().get()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if index fields match table description
|
||||
size_t num = idx->NumFields();
|
||||
|
@ -497,6 +537,11 @@ bool Manager::CreateTableStream(RecordVal* fval) {
|
|||
}
|
||||
|
||||
auto event_val = fval->GetFieldOrDefault("ev");
|
||||
if ( event_val && ! is_func_val(event_val) ) {
|
||||
reporter->Error("Input stream %s: 'ev' field is not an event", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Func* event = event_val ? event_val->AsFunc() : nullptr;
|
||||
|
||||
if ( event ) {
|
||||
|
@ -572,6 +617,11 @@ bool Manager::CreateTableStream(RecordVal* fval) {
|
|||
}
|
||||
|
||||
auto error_event_val = fval->GetFieldOrDefault("error_ev");
|
||||
if ( error_event_val && ! is_func_val(error_event_val) ) {
|
||||
reporter->Error("Input stream %s: 'error_ev' field is not an event", stream_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Func* error_event = error_event_val ? error_event_val->AsFunc() : nullptr;
|
||||
|
||||
if ( ! CheckErrorEventTypes(stream_name, error_event, true) )
|
||||
|
|
|
@ -40,4 +40,12 @@ error: Input stream error3: Error event's first attribute must be of type Input:
|
|||
error: Input stream error4: Error event's second attribute must be of type string
|
||||
error: Input stream error5: Error event's third attribute must be of type Reporter::Level
|
||||
error: Input stream error6: 'destination' field is a table, but 'val' field is not provided (did you mean to use a set instead of a table?)
|
||||
error: Input stream types1: 'idx' field is not a record type
|
||||
error: Input stream types2: 'val' field is not a record type
|
||||
error: Input stream types3: 'destination' field has type string, expected table or set identifier
|
||||
error: Input stream types4: 'ev' field is not an event
|
||||
error: Input stream types5: 'error_ev' field is not an event
|
||||
error: Input stream types6: 'idx' field is not a record type
|
||||
error: Input stream types7: 'ev' field is not an event
|
||||
error: Input stream types8: 'error_ev' field is not an event
|
||||
received termination signal
|
||||
|
|
|
@ -59,6 +59,7 @@ global val_table: table[count] of Val = table();
|
|||
global val_table2: table[count, int] of Val = table();
|
||||
global val_table3: table[count, int] of int = table();
|
||||
global val_table4: table[count] of int;
|
||||
global val_set: set[count];
|
||||
|
||||
event line_file(description: Input::EventDescription, tpe: Input::Event, r:FileVal)
|
||||
{
|
||||
|
@ -190,5 +191,15 @@ event zeek_init()
|
|||
|
||||
Input::add_table([$source="input.log", $name="error6", $idx=Idx, $destination=val_table]);
|
||||
|
||||
# Check that we do not crash when a user passes unexpected types to any fields in the description records.
|
||||
Input::add_table([$source="input.log", $name="types1", $idx="string-is-not-allowed", $destination=val_set]);
|
||||
Input::add_table([$source="input.log", $name="types2", $idx=Idx, $val="string-is-not-allowed", $destination=val_set]);
|
||||
Input::add_table([$source="input.log", $name="types3", $idx=Idx, $destination="string-is-not-allowed"]);
|
||||
Input::add_table([$source="input.log", $name="types4", $idx=Idx, $destination=val_set, $ev="not-an-event"]);
|
||||
Input::add_table([$source="input.log", $name="types5", $idx=Idx, $destination=val_set, $error_ev="not-an-event"]);
|
||||
Input::add_event([$source="input.log", $name="types6", $fields="string-is-not-allowed", $ev=event11]);
|
||||
Input::add_event([$source="input.log", $name="types7", $fields=Val, $ev="not-an-event"]);
|
||||
Input::add_event([$source="input.log", $name="types8", $fields=Val, $ev=event11, $error_ev="not-an-event"]);
|
||||
|
||||
schedule 3secs { kill_me() };
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue