diff --git a/src/Expr.cc b/src/Expr.cc index e64172675e..f060b98602 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3137,12 +3137,14 @@ FieldExpr::FieldExpr(Expr* arg_op, const char* arg_field_name) { RecordType* rt = op->Type()->AsRecordType(); field = rt->FieldOffset(field_name); - td = rt->FieldDecl(field); if ( field < 0 ) ExprError("no such field in record"); else + { SetType(rt->FieldType(field)->Ref()); + td = rt->FieldDecl(field); + } } } @@ -3852,7 +3854,15 @@ void FieldAssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) Val* v = op->Eval(f); if ( v ) - rec->Assign(rt->FieldOffset(field_name.c_str()), v); + { + int idx = rt->FieldOffset(field_name.c_str()); + + if ( idx < 0 ) + reporter->InternalError("Missing record field: %s", + field_name.c_str()); + + rec->Assign(idx, v); + } } int FieldAssignExpr::IsRecordElement(TypeDecl* td) const diff --git a/src/Val.cc b/src/Val.cc index 389e76fe1d..9d1b27b333 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -2670,6 +2670,16 @@ Val* RecordVal::LookupWithDefault(int field) const return record_type->FieldDefault(field); } +Val* RecordVal::Lookup(const char* field, bool with_default) const + { + int idx = record_type->FieldOffset(field); + + if ( idx < 0 ) + reporter->InternalError("missing record field: %s", field); + + return with_default ? LookupWithDefault(idx) : Lookup(idx); + } + RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr, bool allow_orphaning) const { if ( ! record_promotion_compatible(t->AsRecordType(), Type()->AsRecordType()) ) diff --git a/src/Val.h b/src/Val.h index 019c390699..a7088313d6 100644 --- a/src/Val.h +++ b/src/Val.h @@ -895,6 +895,17 @@ public: Val* Lookup(int field) const; // Does not Ref() value. Val* LookupWithDefault(int field) const; // Does Ref() value. + /** + * Looks up the value of a field by field name. If the field doesn't + * exist in the record type, it's an internal error: abort. + * @param field name of field to lookup. + * @param with_default whether to rely on field's &default attribute when + * the field has yet to be initialized. + * @return the value in field \a field. It is Ref()'d only if + * \a with_default is true. + */ + Val* Lookup(const char* field, bool with_default = false) const; + void Describe(ODesc* d) const; // This is an experiment to associate a BroObj within the diff --git a/src/analyzer/protocol/conn-size/ConnSize.cc b/src/analyzer/protocol/conn-size/ConnSize.cc index b912fe3d2d..ad08c78c4f 100644 --- a/src/analyzer/protocol/conn-size/ConnSize.cc +++ b/src/analyzer/protocol/conn-size/ConnSize.cc @@ -54,17 +54,19 @@ void ConnSize_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, void ConnSize_Analyzer::UpdateConnVal(RecordVal *conn_val) { // RecordType *connection_type is decleared in NetVar.h - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp = conn_val->Lookup("resp")->AsRecordVal(); // endpoint is the RecordType from NetVar.h - // TODO: or orig_endp->Type()->AsRecordVal()->FieldOffset() int pktidx = endpoint->FieldOffset("num_pkts"); int bytesidx = endpoint->FieldOffset("num_bytes_ip"); - // TODO: error handling? + if ( pktidx < 0 ) + reporter->InternalError("'endpoint' record missing 'num_pkts' field"); + + if ( bytesidx < 0 ) + reporter->InternalError("'endpoint' record missing 'num_bytes_ip' field"); + orig_endp->Assign(pktidx, new Val(orig_pkts, TYPE_COUNT)); orig_endp->Assign(bytesidx, new Val(orig_bytes, TYPE_COUNT)); resp_endp->Assign(pktidx, new Val(resp_pkts, TYPE_COUNT)); diff --git a/src/analyzer/protocol/icmp/ICMP.cc b/src/analyzer/protocol/icmp/ICMP.cc index 732727d709..a851ebe8ee 100644 --- a/src/analyzer/protocol/icmp/ICMP.cc +++ b/src/analyzer/protocol/icmp/ICMP.cc @@ -440,10 +440,8 @@ void ICMP_Analyzer::Describe(ODesc* d) const void ICMP_Analyzer::UpdateConnVal(RecordVal *conn_val) { - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp = conn_val->Lookup("resp")->AsRecordVal(); UpdateEndpointVal(orig_endp, 1); UpdateEndpointVal(resp_endp, 0); diff --git a/src/analyzer/protocol/tcp/TCP.cc b/src/analyzer/protocol/tcp/TCP.cc index 8f42e0f2b1..c9cd8ed8d1 100644 --- a/src/analyzer/protocol/tcp/TCP.cc +++ b/src/analyzer/protocol/tcp/TCP.cc @@ -1102,11 +1102,8 @@ void TCP_Analyzer::FlipRoles() void TCP_Analyzer::UpdateConnVal(RecordVal *conn_val) { - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - - RecordVal *orig_endp_val = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp_val = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp_val = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp_val = conn_val->Lookup("resp")->AsRecordVal(); orig_endp_val->Assign(0, new Val(orig->Size(), TYPE_COUNT)); orig_endp_val->Assign(1, new Val(int(orig->state), TYPE_COUNT)); diff --git a/src/analyzer/protocol/udp/UDP.cc b/src/analyzer/protocol/udp/UDP.cc index 3050ea5648..4c26ae5d99 100644 --- a/src/analyzer/protocol/udp/UDP.cc +++ b/src/analyzer/protocol/udp/UDP.cc @@ -170,13 +170,9 @@ void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, void UDP_Analyzer::UpdateConnVal(RecordVal *conn_val) { - int orig_endp_idx = connection_type->FieldOffset("orig"); - int resp_endp_idx = connection_type->FieldOffset("resp"); - RecordVal *orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - RecordVal *resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); + RecordVal *orig_endp = conn_val->Lookup("orig")->AsRecordVal(); + RecordVal *resp_endp = conn_val->Lookup("resp")->AsRecordVal(); - orig_endp = conn_val->Lookup(orig_endp_idx)->AsRecordVal(); - resp_endp = conn_val->Lookup(resp_endp_idx)->AsRecordVal(); UpdateEndpointVal(orig_endp, 1); UpdateEndpointVal(resp_endp, 0); diff --git a/src/file_analysis/analyzer/data_event/DataEvent.cc b/src/file_analysis/analyzer/data_event/DataEvent.cc index cf2d7e52ec..a9ffa26bf2 100644 --- a/src/file_analysis/analyzer/data_event/DataEvent.cc +++ b/src/file_analysis/analyzer/data_event/DataEvent.cc @@ -20,13 +20,8 @@ DataEvent::DataEvent(RecordVal* args, File* file, file_analysis::Analyzer* DataEvent::Instantiate(RecordVal* args, File* file) { - using BifType::Record::Files::AnalyzerArgs; - - int chunk_off = AnalyzerArgs->FieldOffset("chunk_event"); - int stream_off = AnalyzerArgs->FieldOffset("stream_event"); - - Val* chunk_val = args->Lookup(chunk_off); - Val* stream_val = args->Lookup(stream_off); + Val* chunk_val = args->Lookup("chunk_event"); + Val* stream_val = args->Lookup("stream_event"); if ( ! chunk_val && ! stream_val ) return 0; diff --git a/src/file_analysis/analyzer/extract/Extract.cc b/src/file_analysis/analyzer/extract/Extract.cc index 504ffd9112..1a3917cd0e 100644 --- a/src/file_analysis/analyzer/extract/Extract.cc +++ b/src/file_analysis/analyzer/extract/Extract.cc @@ -33,8 +33,7 @@ Extract::~Extract() static Val* get_extract_field_val(RecordVal* args, const char* name) { - using BifType::Record::Files::AnalyzerArgs; - Val* rval = args->Lookup(AnalyzerArgs->FieldOffset(name)); + Val* rval = args->Lookup(name); if ( ! rval ) reporter->Error("File extraction analyzer missing arg field: %s", name); diff --git a/src/input/Manager.cc b/src/input/Manager.cc index d838e8cb75..d739a96809 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -296,7 +296,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) return false; } - Val* name_val = description->LookupWithDefault(rtype->FieldOffset("name")); + Val* name_val = description->Lookup("name", true); string name = name_val->AsString()->CheckString(); Unref(name_val); @@ -308,10 +308,10 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) return false; } - EnumVal* reader = description->LookupWithDefault(rtype->FieldOffset("reader"))->AsEnumVal(); + EnumVal* reader = description->Lookup("reader", true)->AsEnumVal(); // get the source ... - Val* sourceval = description->LookupWithDefault(rtype->FieldOffset("source")); + Val* sourceval = description->Lookup("source", true); assert ( sourceval != 0 ); const BroString* bsource = sourceval->AsString(); string source((const char*) bsource->Bytes(), bsource->Len()); @@ -321,7 +321,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) rinfo.source = copy_string(source.c_str()); rinfo.name = copy_string(name.c_str()); - EnumVal* mode = description->LookupWithDefault(rtype->FieldOffset("mode"))->AsEnumVal(); + EnumVal* mode = description->Lookup("mode", true)->AsEnumVal(); switch ( mode->InternalInt() ) { case 0: @@ -342,7 +342,7 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) Unref(mode); - Val* config = description->LookupWithDefault(rtype->FieldOffset("config")); + Val* config = description->Lookup("config", true); info->config = config->AsTableVal(); // ref'd by LookupWithDefault { @@ -401,11 +401,11 @@ bool Manager::CreateEventStream(RecordVal* fval) } - RecordType *fields = fval->LookupWithDefault(rtype->FieldOffset("fields"))->AsType()->AsTypeType()->Type()->AsRecordType(); + RecordType *fields = fval->Lookup("fields", true)->AsType()->AsTypeType()->Type()->AsRecordType(); - Val *want_record = fval->LookupWithDefault(rtype->FieldOffset("want_record")); + Val *want_record = fval->Lookup("want_record", true); - Val* event_val = fval->LookupWithDefault(rtype->FieldOffset("ev")); + Val* event_val = fval->Lookup("ev", true); Func* event = event_val->AsFunc(); Unref(event_val); @@ -547,18 +547,18 @@ bool Manager::CreateTableStream(RecordVal* fval) } } - Val* pred = fval->LookupWithDefault(rtype->FieldOffset("pred")); + Val* pred = fval->Lookup("pred", true); - RecordType *idx = fval->LookupWithDefault(rtype->FieldOffset("idx"))->AsType()->AsTypeType()->Type()->AsRecordType(); + RecordType *idx = fval->Lookup("idx", true)->AsType()->AsTypeType()->Type()->AsRecordType(); RecordType *val = 0; - if ( fval->LookupWithDefault(rtype->FieldOffset("val")) != 0 ) + if ( fval->Lookup("val", true) != 0 ) { - val = fval->LookupWithDefault(rtype->FieldOffset("val"))->AsType()->AsTypeType()->Type()->AsRecordType(); + val = fval->Lookup("val", true)->AsType()->AsTypeType()->Type()->AsRecordType(); Unref(val); // The lookupwithdefault in the if-clause ref'ed val. } - TableVal *dst = fval->LookupWithDefault(rtype->FieldOffset("destination"))->AsTableVal(); + TableVal *dst = fval->Lookup("destination", true)->AsTableVal(); // check if index fields match table description int num = idx->NumFields(); @@ -588,9 +588,9 @@ bool Manager::CreateTableStream(RecordVal* fval) return false; } - Val *want_record = fval->LookupWithDefault(rtype->FieldOffset("want_record")); + Val *want_record = fval->Lookup("want_record", true); - Val* event_val = fval->LookupWithDefault(rtype->FieldOffset("ev")); + Val* event_val = fval->Lookup("ev", true); Func* event = event_val ? event_val->AsFunc() : 0; Unref(event_val); diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 79e23fb63f..87d3be9f13 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -295,7 +295,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval) return false; } - RecordType* columns = sval->Lookup(rtype->FieldOffset("columns")) + RecordType* columns = sval->Lookup("columns") ->AsType()->AsTypeType()->Type()->AsRecordType(); bool log_attr_present = false; @@ -322,7 +322,7 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval) return false; } - Val* event_val = sval->Lookup(rtype->FieldOffset("ev")); + Val* event_val = sval->Lookup("ev"); Func* event = event_val ? event_val->AsFunc() : 0; if ( event ) @@ -579,19 +579,18 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) return false; // Find the right writer type. - int idx = rtype->FieldOffset("writer"); - EnumVal* writer = fval->LookupWithDefault(idx)->AsEnumVal(); + EnumVal* writer = fval->Lookup("writer", true)->AsEnumVal(); // Create a new Filter instance. - Val* name = fval->LookupWithDefault(rtype->FieldOffset("name")); - Val* pred = fval->LookupWithDefault(rtype->FieldOffset("pred")); - Val* path_func = fval->LookupWithDefault(rtype->FieldOffset("path_func")); - Val* log_local = fval->LookupWithDefault(rtype->FieldOffset("log_local")); - Val* log_remote = fval->LookupWithDefault(rtype->FieldOffset("log_remote")); - Val* interv = fval->LookupWithDefault(rtype->FieldOffset("interv")); - Val* postprocessor = fval->LookupWithDefault(rtype->FieldOffset("postprocessor")); - Val* config = fval->LookupWithDefault(rtype->FieldOffset("config")); + Val* name = fval->Lookup("name", true); + Val* pred = fval->Lookup("pred", true); + Val* path_func = fval->Lookup("path_func", true); + Val* log_local = fval->Lookup("log_local", true); + Val* log_remote = fval->Lookup("log_remote", true); + Val* interv = fval->Lookup("interv", true); + Val* postprocessor = fval->Lookup("postprocessor", true); + Val* config = fval->Lookup("config", true); Filter* filter = new Filter; filter->name = name->AsString()->CheckString(); @@ -616,8 +615,8 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) // Build the list of fields that the filter wants included, including // potentially rolling out fields. - Val* include = fval->Lookup(rtype->FieldOffset("include")); - Val* exclude = fval->Lookup(rtype->FieldOffset("exclude")); + Val* include = fval->Lookup("include"); + Val* exclude = fval->Lookup("exclude"); filter->num_fields = 0; filter->fields = 0; @@ -631,7 +630,7 @@ bool Manager::AddFilter(EnumVal* id, RecordVal* fval) } // Get the path for the filter. - Val* path_val = fval->Lookup(rtype->FieldOffset("path")); + Val* path_val = fval->Lookup("path"); if ( path_val ) { diff --git a/src/util.cc b/src/util.cc index f26b3fb0c2..aeb8fdeef8 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1261,6 +1261,16 @@ void _set_processing_status(const char* status) int fd = open(proc_status_file, O_CREAT | O_WRONLY | O_TRUNC, 0700); + if ( fd < 0 ) + { + char buf[256]; + strerror_r(errno, buf, sizeof(buf)); + reporter->Error("Failed to open process status file '%s': %s", + proc_status_file, buf); + errno = old_errno; + return; + } + int len = strlen(status); while ( len ) {