From a463c5763f75aae0bdc51378ce65f1eb22d690d8 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 10 Dec 2019 15:34:02 -0700 Subject: [PATCH 01/12] Use fixed types in NetbiosSSN.h and Timer.h instead of bit fields --- src/Timer.h | 8 +++----- src/analyzer/protocol/netbios/NetbiosSSN.h | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/Timer.h b/src/Timer.h index 5eb0aadec8..a251e5a183 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -12,7 +12,7 @@ extern "C" { } // If you add a timer here, adjust TimerNames in Timer.cc. -enum TimerType { +enum TimerType : uint8_t { TIMER_BACKDOOR, TIMER_BREAKPOINT, TIMER_CONN_DELETE, @@ -51,8 +51,7 @@ class ODesc; class Timer : public PQ_Element { public: - Timer(double t, TimerType arg_type) : PQ_Element(t) - { type = (char) arg_type; } + Timer(double t, TimerType arg_type) : PQ_Element(t), type(arg_type) { } ~Timer() override { } TimerType Type() const { return (TimerType) type; } @@ -66,8 +65,7 @@ public: protected: Timer() {} - - unsigned int type:8; + TimerType type; }; class TimerMgr { diff --git a/src/analyzer/protocol/netbios/NetbiosSSN.h b/src/analyzer/protocol/netbios/NetbiosSSN.h index e38b7b223b..7a6c1fab8f 100644 --- a/src/analyzer/protocol/netbios/NetbiosSSN.h +++ b/src/analyzer/protocol/netbios/NetbiosSSN.h @@ -32,9 +32,9 @@ typedef enum { struct NetbiosSSN_RawMsgHdr { NetbiosSSN_RawMsgHdr(const u_char*& data, int& len); - unsigned int type:8; - unsigned int flags:8; - unsigned int length:16; + uint8_t type; + uint8_t flags; + uint16_t length; }; // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -51,13 +51,13 @@ struct NetbiosSSN_RawMsgHdr { struct NetbiosDGM_RawMsgHdr { NetbiosDGM_RawMsgHdr(const u_char*& data, int& len); - unsigned int type:8; - unsigned int flags:8; - unsigned int id:16; - unsigned int srcip:32; - unsigned int srcport:16; - unsigned int length:16; - unsigned int offset:16; + uint8_t type; + uint8_t flags; + uint16_t id; + uint32_t srcip; + uint16_t srcport; + uint16_t length; + uint16_t offset; }; From 9d38419e8a02354cd95981d27d4677ad5ffc42fd Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 2 Jan 2020 13:20:51 -0700 Subject: [PATCH 02/12] Bit of code-modernization cleanup in BroString - Convert single-bit bit fields into bools - Use bool for a number of function arguments that were previously ints - Use delegated constructors to reduce repetition in the other constructors --- src/BroString.cc | 58 +++++++++++++++++++----------------------------- src/BroString.h | 10 ++++----- 2 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/BroString.cc b/src/BroString.cc index bb741724a5..2938410a9f 100644 --- a/src/BroString.cc +++ b/src/BroString.cc @@ -25,52 +25,40 @@ const int BroString::BRO_STRING_LITERAL; // arg_final_NUL == 1; when str is a sequence of n bytes, make // arg_final_NUL == 0. -BroString::BroString(int arg_final_NUL, byte_vec str, int arg_n) +BroString::BroString(bool arg_final_NUL, byte_vec str, int arg_n) { b = str; n = arg_n; final_NUL = arg_final_NUL; - use_free_to_delete = 0; + use_free_to_delete = false; } -BroString::BroString(const u_char* str, int arg_n, int add_NUL) +BroString::BroString(const u_char* str, int arg_n, bool add_NUL) : BroString() { - b = 0; - n = 0; - use_free_to_delete = 0; Set(str, arg_n, add_NUL); } -BroString::BroString(const char* str) +BroString::BroString(const char* str) : BroString() { - b = 0; - n = 0; - use_free_to_delete = 0; Set(str); } -BroString::BroString(const string &str) +BroString::BroString(const string &str) : BroString() { - b = 0; - n = 0; - use_free_to_delete = 0; Set(str); } -BroString::BroString(const BroString& bs) +BroString::BroString(const BroString& bs) : BroString() { - b = 0; - n = 0; - use_free_to_delete = 0; *this = bs; } BroString::BroString() { - b = 0; + b = nullptr; n = 0; - final_NUL = 0; - use_free_to_delete = 0; + final_NUL = false; + use_free_to_delete = false; } void BroString::Reset() @@ -80,10 +68,10 @@ void BroString::Reset() else delete [] b; - b = 0; + b = nullptr; n = 0; - final_NUL = 0; - use_free_to_delete = 0; + final_NUL = false; + use_free_to_delete = false; } const BroString& BroString::operator=(const BroString &bs) @@ -95,8 +83,8 @@ const BroString& BroString::operator=(const BroString &bs) memcpy(b, bs.b, n); b[n] = '\0'; - final_NUL = 1; - use_free_to_delete = 0; + final_NUL = true; + use_free_to_delete = false; return *this; } @@ -122,7 +110,7 @@ void BroString::Adopt(byte_vec bytes, int len) n = len - final_NUL; } -void BroString::Set(const u_char* str, int len, int add_NUL) +void BroString::Set(const u_char* str, int len, bool add_NUL) { Reset(); @@ -134,7 +122,7 @@ void BroString::Set(const u_char* str, int len, int add_NUL) if ( add_NUL ) b[n] = 0; - use_free_to_delete = 0; + use_free_to_delete = false; } void BroString::Set(const char* str) @@ -144,8 +132,8 @@ void BroString::Set(const char* str) n = strlen(str); b = new u_char[n+1]; memcpy(b, str, n+1); - final_NUL = 1; - use_free_to_delete = 0; + final_NUL = true; + use_free_to_delete = false; } void BroString::Set(const string& str) @@ -155,8 +143,8 @@ void BroString::Set(const string& str) n = str.size(); b = new u_char[n+1]; memcpy(b, str.c_str(), n+1); - final_NUL = 1; - use_free_to_delete = 0; + final_NUL = true; + use_free_to_delete = false; } void BroString::Set(const BroString& str) @@ -307,7 +295,7 @@ BroString::Vec* BroString::Split(const BroString::IdxVec& indices) const { unsigned int i; - if ( indices.size() == 0 ) + if ( indices.empty() ) return 0; // Copy input, ensuring space for "0": @@ -453,7 +441,7 @@ BroString* concatenate(std::vector& v) *b = '\0'; - return new BroString(1, (byte_vec) data, len); + return new BroString(true, (byte_vec) data, len); } BroString* concatenate(BroString::CVec& v) @@ -474,7 +462,7 @@ BroString* concatenate(BroString::CVec& v) } *b = '\0'; - return new BroString(1, (byte_vec) data, len); + return new BroString(true, (byte_vec) data, len); } BroString* concatenate(BroString::Vec& v) diff --git a/src/BroString.h b/src/BroString.h index f8bcbbc7dd..0361c0a927 100644 --- a/src/BroString.h +++ b/src/BroString.h @@ -33,13 +33,13 @@ public: typedef IdxVec::const_iterator IdxVecCIt; // Constructors creating internal copies of the data passed in. - BroString(const u_char* str, int arg_n, int add_NUL); + BroString(const u_char* str, int arg_n, bool add_NUL); explicit BroString(const char* str); explicit BroString(const std::string& str); BroString(const BroString& bs); // Constructor that takes owernship of the vector passed in. - BroString(int arg_final_NUL, byte_vec str, int arg_n); + BroString(bool arg_final_NUL, byte_vec str, int arg_n); BroString(); ~BroString() { Reset(); } @@ -61,7 +61,7 @@ public: // current contents, if any, and then set the string's // contents to a copy of the string given by the arguments. // - void Set(const u_char* str, int len, int add_NUL=1); + void Set(const u_char* str, int len, bool add_NUL=true); void Set(const char* str); void Set(const std::string& str); void Set(const BroString &str); @@ -146,8 +146,8 @@ protected: byte_vec b; int n; - unsigned int final_NUL:1; // whether we have added a final NUL - unsigned int use_free_to_delete:1; // free() vs. operator delete + bool final_NUL; // whether we have added a final NUL + bool use_free_to_delete; // free() vs. operator delete }; // A comparison class that sorts pointers to BroString's according to From 0f8f53808e51902f8767cb12756987dd30b7f7de Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 7 Jan 2020 12:07:40 -0700 Subject: [PATCH 03/12] Use bools instead of single-bit bitfields in Ident and TCP protocol analyzers --- src/Conn.cc | 18 +++++++++--------- src/Conn.h | 8 ++++---- src/analyzer/protocol/ident/Ident.cc | 6 +++--- src/analyzer/protocol/ident/Ident.h | 6 +++--- src/analyzer/protocol/tcp/ContentLine.cc | 15 +++++++-------- src/analyzer/protocol/tcp/ContentLine.h | 16 ++++++++-------- src/analyzer/protocol/tcp/TCP_Reassembler.cc | 16 ++++++++-------- src/analyzer/protocol/tcp/TCP_Reassembler.h | 10 +++++----- 8 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/Conn.cc b/src/Conn.cc index 3b9f66347d..9329045f79 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -18,7 +18,7 @@ #include "analyzer/Manager.h" void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer, - int arg_do_expire) + bool arg_do_expire) { conn = arg_conn; timer = arg_timer; @@ -87,8 +87,8 @@ Connection::Connection(NetSessions* s, const ConnIDKey& k, double t, const ConnI vlan = pkt->vlan; inner_vlan = pkt->inner_vlan; - conn_val = 0; - login_conn = 0; + conn_val = nullptr; + login_conn = nullptr; is_active = 1; skip = 0; @@ -108,8 +108,8 @@ Connection::Connection(NetSessions* s, const ConnIDKey& k, double t, const ConnI hist_seen = 0; history = ""; - root_analyzer = 0; - primary_PIA = 0; + root_analyzer = nullptr; + primary_PIA = nullptr; ++current_connections; ++total_connections; @@ -172,7 +172,7 @@ void Connection::CheckEncapsulation(const EncapsulationStack* arg_encap) EncapsulationStack empty; Event(tunnel_changed, 0, empty.GetVectorVal()); delete encapsulation; - encapsulation = 0; + encapsulation = nullptr; } else if ( arg_encap ) @@ -222,7 +222,7 @@ void Connection::NextPacket(double t, int is_orig, last_time = t; current_timestamp = 0; - current_pkt = 0; + current_pkt = nullptr; } void Connection::SetLifetime(double lifetime) @@ -533,7 +533,7 @@ void Connection::Weird(const char* name, const char* addl) reporter->Weird(this, name, addl ? addl : ""); } -void Connection::AddTimer(timer_func timer, double t, int do_expire, +void Connection::AddTimer(timer_func timer, double t, bool do_expire, TimerType type) { if ( timers_canceled ) @@ -609,7 +609,7 @@ void Connection::FlipRoles() orig_flow_label = tmp_flow; Unref(conn_val); - conn_val = 0; + conn_val = nullptr; if ( root_analyzer ) root_analyzer->FlipRoles(); diff --git a/src/Conn.h b/src/Conn.h index 07e669d11f..9a2d3e8f6a 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -303,7 +303,7 @@ protected: // Add the given timer to expire at time t. If do_expire // is true, then the timer is also evaluated when Bro terminates, // otherwise not. - void AddTimer(timer_func timer, double t, int do_expire, + void AddTimer(timer_func timer, double t, bool do_expire, TimerType type); void RemoveTimer(Timer* t); @@ -367,7 +367,7 @@ protected: class ConnectionTimer : public Timer { public: ConnectionTimer(Connection* arg_conn, timer_func arg_timer, - double arg_t, int arg_do_expire, TimerType arg_type) + double arg_t, bool arg_do_expire, TimerType arg_type) : Timer(arg_t, arg_type) { Init(arg_conn, arg_timer, arg_do_expire); } ~ConnectionTimer() override; @@ -377,11 +377,11 @@ public: protected: ConnectionTimer() {} - void Init(Connection* conn, timer_func timer, int do_expire); + void Init(Connection* conn, timer_func timer, bool do_expire); Connection* conn; timer_func timer; - int do_expire; + bool do_expire; }; #define ADD_TIMER(timer, t, do_expire, type) \ diff --git a/src/analyzer/protocol/ident/Ident.cc b/src/analyzer/protocol/ident/Ident.cc index b24675ee53..5b10a19c05 100644 --- a/src/analyzer/protocol/ident/Ident.cc +++ b/src/analyzer/protocol/ident/Ident.cc @@ -15,7 +15,7 @@ using namespace analyzer::ident; Ident_Analyzer::Ident_Analyzer(Connection* conn) : tcp::TCP_ApplicationAnalyzer("IDENT", conn) { - did_bad_reply = did_deliver = 0; + did_bad_reply = did_deliver = false; orig_ident = new tcp::ContentLine_Analyzer(conn, true, 1000); resp_ident = new tcp::ContentLine_Analyzer(conn, false, 1000); @@ -89,7 +89,7 @@ void Ident_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) val_mgr->GetPort(remote_port, TRANSPORT_TCP), }); - did_deliver = 1; + did_deliver = true; } else @@ -251,6 +251,6 @@ void Ident_Analyzer::BadReply(int length, const char* line) { BroString s((const u_char*)line, length, true); Weird("bad_ident_reply", s.CheckString()); - did_bad_reply = 1; + did_bad_reply = true; } } diff --git a/src/analyzer/protocol/ident/Ident.h b/src/analyzer/protocol/ident/Ident.h index fa1a7b9583..3725f3bc91 100644 --- a/src/analyzer/protocol/ident/Ident.h +++ b/src/analyzer/protocol/ident/Ident.h @@ -29,8 +29,8 @@ protected: tcp::ContentLine_Analyzer* orig_ident; tcp::ContentLine_Analyzer* resp_ident; - unsigned int did_deliver:1; - unsigned int did_bad_reply:1; + bool did_deliver; + bool did_bad_reply; }; -} } // namespace analyzer::* +} } // namespace analyzer::* diff --git a/src/analyzer/protocol/tcp/ContentLine.cc b/src/analyzer/protocol/tcp/ContentLine.cc index eb7fa1e3ea..d98c5b4d2f 100644 --- a/src/analyzer/protocol/tcp/ContentLine.cc +++ b/src/analyzer/protocol/tcp/ContentLine.cc @@ -21,17 +21,17 @@ ContentLine_Analyzer::ContentLine_Analyzer(const char* name, Connection* conn, b void ContentLine_Analyzer::InitState() { - flag_NULs = 0; + flag_NULs = false; CR_LF_as_EOL = (CR_as_EOL | LF_as_EOL); - skip_deliveries = 0; - skip_partial = 0; + skip_deliveries = false; + skip_partial = false; buf = 0; seq_delivered_in_lines = 0; skip_pending = 0; seq = 0; seq_to_skip = 0; plain_delivery_length = 0; - is_plain = 0; + is_plain = false; suppress_weirds = false; InitBuffer(0); @@ -70,7 +70,7 @@ ContentLine_Analyzer::~ContentLine_Analyzer() delete [] buf; } -int ContentLine_Analyzer::HasPartialLine() const +bool ContentLine_Analyzer::HasPartialLine() const { return buf && offset > 0; } @@ -150,11 +150,11 @@ void ContentLine_Analyzer::DoDeliver(int len, const u_char* data) last_char = 0; // clear last_char plain_delivery_length -= deliver_plain; - is_plain = 1; + is_plain = true; ForwardStream(deliver_plain, data, IsOrig()); - is_plain = 0; + is_plain = false; data += deliver_plain; len -= deliver_plain; @@ -339,4 +339,3 @@ void ContentLine_Analyzer::SkipBytes(int64_t length) skip_pending = 0; seq_to_skip = SeqDelivered() + length; } - diff --git a/src/analyzer/protocol/tcp/ContentLine.h b/src/analyzer/protocol/tcp/ContentLine.h index 09244094df..e7f310e90e 100644 --- a/src/analyzer/protocol/tcp/ContentLine.h +++ b/src/analyzer/protocol/tcp/ContentLine.h @@ -35,12 +35,12 @@ public: int CRLFAsEOL() { return CR_LF_as_EOL ; } - int HasPartialLine() const; + bool HasPartialLine() const; bool SkipDeliveries() const { return skip_deliveries; } - void SetSkipDeliveries(int should_skip) + void SetSkipDeliveries(bool should_skip) { skip_deliveries = should_skip; } // We actually have two delivery modes: line delivery and plain @@ -97,21 +97,21 @@ protected: // Remaining bytes to deliver plain. int64_t plain_delivery_length; - int is_plain; + bool is_plain; // Don't deliver further data. - int skip_deliveries; + bool skip_deliveries; bool suppress_weirds; // If true, flag (first) line with embedded NUL. - unsigned int flag_NULs:1; + bool flag_NULs; // Whether single CR / LF are considered as EOL. - unsigned int CR_LF_as_EOL:2; + uint8_t CR_LF_as_EOL:2; // Whether to skip partial conns. - unsigned int skip_partial:1; + bool skip_partial; }; -} } // namespace analyzer::* +} } // namespace analyzer::* diff --git a/src/analyzer/protocol/tcp/TCP_Reassembler.cc b/src/analyzer/protocol/tcp/TCP_Reassembler.cc index 947ebcd433..5df1cc468a 100644 --- a/src/analyzer/protocol/tcp/TCP_Reassembler.cc +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.cc @@ -28,9 +28,9 @@ TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer, endp = arg_endp; had_gap = false; record_contents_file = 0; - deliver_tcp_contents = 0; - skip_deliveries = 0; - did_EOF = 0; + deliver_tcp_contents = false; + skip_deliveries = false; + did_EOF = false; seq_to_skip = 0; in_delivery = false; @@ -49,7 +49,7 @@ TCP_Reassembler::TCP_Reassembler(analyzer::Analyzer* arg_dst_analyzer, if ( (IsOrig() && tcp_content_deliver_all_orig) || (! IsOrig() && tcp_content_deliver_all_resp) || (result && result->AsBool()) ) - deliver_tcp_contents = 1; + deliver_tcp_contents = true; Unref(dst_port_val); } @@ -221,7 +221,7 @@ void TCP_Reassembler::Undelivered(uint64_t up_to_seq) // the SYN packet carries data. // // Skip the undelivered part without reporting to the endpoint. - skip_deliveries = 1; + skip_deliveries = true; } else { @@ -517,7 +517,7 @@ int TCP_Reassembler::DataSent(double t, uint64_t seq, int len, { tcp_analyzer->Weird("above_hole_data_without_any_acks"); ClearBlocks(); - skip_deliveries = 1; + skip_deliveries = true; } if ( tcp_excessive_data_without_further_acks && @@ -525,7 +525,7 @@ int TCP_Reassembler::DataSent(double t, uint64_t seq, int len, { tcp_analyzer->Weird("excessive_data_without_further_acks"); ClearBlocks(); - skip_deliveries = 1; + skip_deliveries = true; } return 1; @@ -592,7 +592,7 @@ void TCP_Reassembler::CheckEOF() network_time, endp->IsOrig()); } - did_EOF = 1; + did_EOF = true; tcp_analyzer->EndpointEOF(this); } } diff --git a/src/analyzer/protocol/tcp/TCP_Reassembler.h b/src/analyzer/protocol/tcp/TCP_Reassembler.h index 37c04c9e37..dd499e79cc 100644 --- a/src/analyzer/protocol/tcp/TCP_Reassembler.h +++ b/src/analyzer/protocol/tcp/TCP_Reassembler.h @@ -96,10 +96,10 @@ private: TCP_Endpoint* endp; - unsigned int deliver_tcp_contents:1; - unsigned int had_gap:1; - unsigned int did_EOF:1; - unsigned int skip_deliveries:1; + bool deliver_tcp_contents; + bool had_gap; + bool did_EOF; + bool skip_deliveries; uint64_t seq_to_skip; @@ -114,4 +114,4 @@ private: Type type; }; -} } // namespace analyzer::* +} } // namespace analyzer::* From 50a0835b41f3bee692c767c4f6b680f1f592d68e Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 7 Nov 2019 12:19:43 -0700 Subject: [PATCH 04/12] Convert type-checking macros to actual functions --- src/Type.h | 64 +++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/Type.h b/src/Type.h index 7be4e01946..371e4385a5 100644 --- a/src/Type.h +++ b/src/Type.h @@ -698,53 +698,53 @@ extern BroType* init_type(Expr* init); // Returns true if argument is an atomic type. bool is_atomic_type(const BroType* t); -// True if the given type tag corresponds to an integral type. -#define IsIntegral(t) (t == TYPE_INT || t == TYPE_COUNT || t == TYPE_COUNTER) - -// True if the given type tag corresponds to an arithmetic type. -#define IsArithmetic(t) (IsIntegral(t) || t == TYPE_DOUBLE) - -// True if the given type tag corresponds to a boolean type. -#define IsBool(t) (t == TYPE_BOOL) - -// True if the given type tag corresponds to an interval type. -#define IsInterval(t) (t == TYPE_INTERVAL) - -// True if the given type tag corresponds to a record type. -#define IsRecord(t) (t == TYPE_RECORD || t == TYPE_UNION) - -// True if the given type tag corresponds to a function type. -#define IsFunc(t) (t == TYPE_FUNC) - -// True if the given type type is a vector. -#define IsVector(t) (t == TYPE_VECTOR) - -// True if the given type type is a string. -#define IsString(t) (t == TYPE_STRING) - // True if the given type tag corresponds to type that can be assigned to. extern int is_assignable(BroType* t); +// True if the given type tag corresponds to an integral type. +inline bool IsIntegral(TypeTag t) { return (t == TYPE_INT || t == TYPE_COUNT || t == TYPE_COUNTER); } + +// True if the given type tag corresponds to an arithmetic type. +inline bool IsArithmetic(TypeTag t) { return (IsIntegral(t) || t == TYPE_DOUBLE); } + +// True if the given type tag corresponds to a boolean type. +inline bool IsBool(TypeTag t) { return (t == TYPE_BOOL); } + +// True if the given type tag corresponds to an interval type. +inline bool IsInterval(TypeTag t) { return (t == TYPE_INTERVAL); } + +// True if the given type tag corresponds to a record type. +inline bool IsRecord(TypeTag t) { return (t == TYPE_RECORD || t == TYPE_UNION); } + +// True if the given type tag corresponds to a function type. +inline bool IsFunc(TypeTag t) { return (t == TYPE_FUNC); } + +// True if the given type type is a vector. +inline bool IsVector(TypeTag t) { return (t == TYPE_VECTOR); } + +// True if the given type type is a string. +inline bool IsString(TypeTag t) { return (t == TYPE_STRING); } + // True if the given type tag corresponds to the error type. -#define IsErrorType(t) (t == TYPE_ERROR) +inline bool IsErrorType(TypeTag t) { return (t == TYPE_ERROR); } // True if both tags are integral types. -#define BothIntegral(t1, t2) (IsIntegral(t1) && IsIntegral(t2)) +inline bool BothIntegral(TypeTag t1, TypeTag t2) { return (IsIntegral(t1) && IsIntegral(t2)); } // True if both tags are arithmetic types. -#define BothArithmetic(t1, t2) (IsArithmetic(t1) && IsArithmetic(t2)) +inline bool BothArithmetic(TypeTag t1, TypeTag t2) { return (IsArithmetic(t1) && IsArithmetic(t2)); } // True if either tags is an arithmetic type. -#define EitherArithmetic(t1, t2) (IsArithmetic(t1) || IsArithmetic(t2)) +inline bool EitherArithmetic(TypeTag t1, TypeTag t2) { return (IsArithmetic(t1) || IsArithmetic(t2)); } // True if both tags are boolean types. -#define BothBool(t1, t2) (IsBool(t1) && IsBool(t2)) +inline bool BothBool(TypeTag t1, TypeTag t2) { return (IsBool(t1) && IsBool(t2)); } // True if both tags are interval types. -#define BothInterval(t1, t2) (IsInterval(t1) && IsInterval(t2)) +inline bool BothInterval(TypeTag t1, TypeTag t2) { return (IsInterval(t1) && IsInterval(t2)); } // True if both tags are string types. -#define BothString(t1, t2) (IsString(t1) && IsString(t2)) +inline bool BothString(TypeTag t1, TypeTag t2) { return (IsString(t1) && IsString(t2)); } // True if either tag is the error type. -#define EitherError(t1, t2) (IsErrorType(t1) || IsErrorType(t2)) +inline bool EitherError(TypeTag t1, TypeTag t2) { return (IsErrorType(t1) || IsErrorType(t2)); } From d9ed76c90a899b852d9b33adc96cf1a6741b6dba Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 14 Jan 2020 10:53:02 -0500 Subject: [PATCH 05/12] Fix warning when reading files from non-network sources If files are being read from non-network sources, there was a warning in the SSL base scripts about missing the f$conns field. --- scripts/base/protocols/ssl/files.zeek | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/base/protocols/ssl/files.zeek b/scripts/base/protocols/ssl/files.zeek index fd3080b47d..d0349a0dae 100644 --- a/scripts/base/protocols/ssl/files.zeek +++ b/scripts/base/protocols/ssl/files.zeek @@ -92,7 +92,7 @@ event zeek_init() &priority=5 event file_sniff(f: fa_file, meta: fa_metadata) &priority=5 { - if ( |f$conns| != 1 ) + if ( ! f?$conns || |f$conns| != 1 ) return; if ( ! f?$info || ! f$info?$mime_type ) From 46e730842297d16d1ea9e02cb06edd95b02c81dc Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Thu, 7 Nov 2019 12:30:30 -0700 Subject: [PATCH 06/12] GHI-595: Convert from nlohmann/json to rapidjson for performance reasons --- src/3rdparty | 2 +- src/CMakeLists.txt | 9 +- src/Val.cc | 167 +++++++++++------- src/threading/formatters/JSON.cc | 99 +++++++---- src/threading/formatters/JSON.h | 26 ++- .../json.log | 10 +- .../Baseline/scripts.base.utils.json/output | 2 +- 7 files changed, 183 insertions(+), 132 deletions(-) diff --git a/src/3rdparty b/src/3rdparty index 2b3206b7ad..e2f0a1b3f1 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 2b3206b7add3472ea0736f2841473e11d506a85e +Subproject commit e2f0a1b3f1c54f9dc97a806261cc329e4dd596c8 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c47f7dd3b..c64f9608fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -413,15 +413,14 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ ) install(FILES - ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/json.hpp ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sqlite3.h DESTINATION include/zeek/3rdparty -) + ) install(FILES - ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/tsl-ordered-map/ordered_map.h - ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/tsl-ordered-map/ordered_hash.h - DESTINATION include/zeek/3rdparty/tsl-ordered-map + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/rapidjson/include/rapidjson/document.h + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/rapidjson/include/rapidjson/writer.h + DESTINATION include/zeek/3rdparty/rapidjson/include/rapidjson ) ######################################################################## diff --git a/src/Val.cc b/src/Val.cc index 98ef6da532..b5b667aa56 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -12,6 +12,11 @@ #include #include +#define RAPIDJSON_HAS_STDSTRING 1 +#include "3rdparty/rapidjson/include/rapidjson/document.h" +#include "3rdparty/rapidjson/include/rapidjson/stringbuffer.h" +#include "3rdparty/rapidjson/include/rapidjson/writer.h" + #include "Val.h" #include "Net.h" #include "File.h" @@ -27,20 +32,17 @@ #include "broker/Data.h" -#include "3rdparty/json.hpp" -#include "3rdparty/tsl-ordered-map/ordered_map.h" +class NullDoubleWriter : public rapidjson::Writer { +public: + NullDoubleWriter(rapidjson::StringBuffer& buffer) : rapidjson::Writer(buffer) {} + bool Double(double d) + { + if ( rapidjson::internal::Double(d).IsNanOrInf() ) + return rapidjson::Writer::Null(); - -// Define a class for use with the json library that orders the keys in the same order that -// they were inserted. By default, the json library orders them alphabetically and we don't -// want it like that. -template, class KeyEqual = std::equal_to, - class AllocatorPair = typename std::allocator_traits::template rebind_alloc>, - class ValueTypeContainer = std::vector, AllocatorPair>> -using ordered_map = tsl::ordered_map; - -using ZeekJson = nlohmann::basic_json; + return rapidjson::Writer::Double(d); + } +}; Val::Val(Func* f) { @@ -433,46 +435,56 @@ TableVal* Val::GetRecordFields() return rt->GetRecordFieldsVal(rv); } -// This is a static method in this file to avoid including json.hpp in Val.h since it's huge. -static ZeekJson BuildJSON(Val* val, bool only_loggable=false, RE_Matcher* re=nullptr) +// This is a static method in this file to avoid including rapidjson's headers in Val.h because they're huge. +static void BuildJSON(NullDoubleWriter& writer, Val* val, bool only_loggable=false, RE_Matcher* re=nullptr, const string& key="") { - // If the value wasn't set, return a nullptr. This will get turned into a 'null' in the json output. - if ( ! val ) - return nullptr; + if ( !key.empty() ) + writer.Key(key); - ZeekJson j; + // If the value wasn't set, write a null into the stream and return. + if ( ! val ) + { + writer.Null(); + return; + } + + rapidjson::Value j; BroType* type = val->Type(); switch ( type->Tag() ) { case TYPE_BOOL: - j = val->AsBool(); + writer.Bool(val->AsBool()); break; case TYPE_INT: - j = val->AsInt(); + writer.Int64(val->AsInt()); break; case TYPE_COUNT: - j = val->AsCount(); + writer.Uint64(val->AsCount()); break; case TYPE_COUNTER: - j = val->AsCounter(); + writer.Uint64(val->AsCounter()); break; case TYPE_TIME: - j = val->AsTime(); + writer.Double(val->AsTime()); break; case TYPE_DOUBLE: - j = val->AsDouble(); + writer.Double(val->AsDouble()); break; case TYPE_PORT: { auto* pval = val->AsPortVal(); - j.emplace("port", pval->Port()); - j.emplace("proto", pval->Protocol()); + writer.StartObject(); + writer.Key("port"); + writer.Int64(pval->Port()); + writer.Key("proto"); + writer.String(pval->Protocol()); + writer.EndObject(); break; } @@ -484,7 +496,7 @@ static ZeekJson BuildJSON(Val* val, bool only_loggable=false, RE_Matcher* re=nul ODesc d; d.SetStyle(RAW_STYLE); val->Describe(&d); - j = string(reinterpret_cast(d.Bytes()), d.Len()); + writer.String(reinterpret_cast(d.Bytes()), d.Len()); break; } @@ -496,7 +508,7 @@ static ZeekJson BuildJSON(Val* val, bool only_loggable=false, RE_Matcher* re=nul ODesc d; d.SetStyle(RAW_STYLE); val->Describe(&d); - j = json_escape_utf8(string(reinterpret_cast(d.Bytes()), d.Len())); + writer.String(json_escape_utf8(string(reinterpret_cast(d.Bytes()), d.Len()))); break; } @@ -506,9 +518,9 @@ static ZeekJson BuildJSON(Val* val, bool only_loggable=false, RE_Matcher* re=nul auto* tval = val->AsTableVal(); if ( tval->Type()->IsSet() ) - j = ZeekJson::array(); + writer.StartArray(); else - j = ZeekJson::object(); + writer.StartObject(); HashKey* k; TableEntryVal* entry; @@ -524,102 +536,125 @@ static ZeekJson BuildJSON(Val* val, bool only_loggable=false, RE_Matcher* re=nul else entry_key = lv->Ref(); - ZeekJson key_json = BuildJSON(entry_key, only_loggable, re); - if ( tval->Type()->IsSet() ) - j.emplace_back(std::move(key_json)); + BuildJSON(writer, entry_key, only_loggable, re); else { Val* entry_value = entry->Value(); - string key_string; - if ( key_json.is_string() ) - key_string = key_json; - else - key_string = key_json.dump(); + rapidjson::StringBuffer buffer; + NullDoubleWriter key_writer(buffer); + BuildJSON(key_writer, entry_key, only_loggable, re); + string key_str = buffer.GetString(); + if ( key_str[0] == '"') + key_str = key_str.substr(1); + if ( key_str[key_str.length()-1] == '"') + key_str = key_str.substr(0, key_str.length()-1); - j.emplace(key_string, BuildJSON(entry_value, only_loggable, re)); + BuildJSON(writer, entry_value, only_loggable, re, key_str); } Unref(entry_key); Unref(lv); } + if ( tval->Type()->IsSet() ) + writer.EndArray(); + else + writer.EndObject(); + break; } case TYPE_RECORD: { - j = ZeekJson::object(); + writer.StartObject(); + auto* rval = val->AsRecordVal(); auto rt = rval->Type()->AsRecordType(); for ( auto i = 0; i < rt->NumFields(); ++i ) { - auto field_name = rt->FieldName(i); - std::string key_string; - - if ( re && re->MatchAnywhere(field_name) != 0 ) - { - StringVal blank(""); - StringVal fn_val(field_name); - auto key_val = fn_val.Substitute(re, &blank, 0)->AsStringVal(); - key_string = key_val->ToStdString(); - Unref(key_val); - } - else - key_string = field_name; - Val* value = rval->LookupWithDefault(i); if ( value && ( ! only_loggable || rt->FieldHasAttr(i, ATTR_LOG) ) ) - j.emplace(key_string, BuildJSON(value, only_loggable, re)); + { + string key_str; + auto field_name = rt->FieldName(i); + + if ( re && re->MatchAnywhere(field_name) != 0 ) + { + StringVal blank(""); + StringVal fn_val(field_name); + auto key_val = fn_val.Substitute(re, &blank, 0)->AsStringVal(); + key_str = key_val->ToStdString(); + Unref(key_val); + } + else + key_str = field_name; + + BuildJSON(writer, value, only_loggable, re, key_str); + } Unref(value); } + writer.EndObject(); break; } case TYPE_LIST: { - j = ZeekJson::array(); + writer.StartArray(); + auto* lval = val->AsListVal(); size_t size = lval->Length(); for (size_t i = 0; i < size; i++) - j.push_back(BuildJSON(lval->Index(i), only_loggable, re)); + BuildJSON(writer, lval->Index(i), only_loggable, re); + writer.EndArray(); break; } case TYPE_VECTOR: { - j = ZeekJson::array(); + writer.StartArray(); + auto* vval = val->AsVectorVal(); size_t size = vval->SizeVal()->AsCount(); for (size_t i = 0; i < size; i++) - j.push_back(BuildJSON(vval->Lookup(i), only_loggable, re)); + BuildJSON(writer, vval->Lookup(i), only_loggable, re); + writer.EndArray(); break; } case TYPE_OPAQUE: { + writer.StartObject(); + + writer.Key("opaque_type"); auto* oval = val->AsOpaqueVal(); - j = { { "opaque_type", OpaqueMgr::mgr()->TypeID(oval) } }; + writer.String(OpaqueMgr::mgr()->TypeID(oval)); + + writer.EndObject(); break; } - default: break; + default: + writer.Null(); + break; } - - return j; } StringVal* Val::ToJSON(bool only_loggable, RE_Matcher* re) { - ZeekJson j = BuildJSON(this, only_loggable, re); - return new StringVal(j.dump()); + rapidjson::StringBuffer buffer; + NullDoubleWriter writer(buffer); + + BuildJSON(writer, this, only_loggable, re, ""); + + return new StringVal(buffer.GetString()); } IntervalVal::IntervalVal(double quantity, double units) : diff --git a/src/threading/formatters/JSON.cc b/src/threading/formatters/JSON.cc index 919ecd4a2b..6944af81cd 100644 --- a/src/threading/formatters/JSON.cc +++ b/src/threading/formatters/JSON.cc @@ -12,9 +12,18 @@ #include #include "JSON.h" +#include "3rdparty/rapidjson/include/rapidjson/internal/ieee754.h" using namespace threading::formatter; +bool JSON::NullDoubleWriter::Double(double d) + { + if ( rapidjson::internal::Double(d).IsNanOrInf() ) + return rapidjson::Writer::Null(); + + return rapidjson::Writer::Double(d); + } + JSON::JSON(MsgThread* t, TimeFormat tf) : Formatter(t), surrounding_braces(true) { timestamps = tf; @@ -27,21 +36,19 @@ JSON::~JSON() bool JSON::Describe(ODesc* desc, int num_fields, const Field* const * fields, Value** vals) const { - ZeekJson j = ZeekJson::object(); + rapidjson::StringBuffer buffer; + NullDoubleWriter writer(buffer); + + writer.StartObject(); for ( int i = 0; i < num_fields; i++ ) { if ( vals[i]->present ) - { - ZeekJson new_entry = BuildJSON(vals[i]); - if ( new_entry.is_null() ) - return false; - - j.emplace(fields[i]->name, new_entry); - } + BuildJSON(writer, vals[i], fields[i]->name); } - desc->Add(j.dump()); + writer.EndObject(); + desc->Add(buffer.GetString()); return true; } @@ -54,14 +61,18 @@ bool JSON::Describe(ODesc* desc, Value* val, const string& name) const return false; } - if ( ! val->present ) + if ( ! val->present || name.empty() ) return true; - ZeekJson j = BuildJSON(val, name); - if ( j.is_null() ) - return false; + rapidjson::Document doc; + rapidjson::StringBuffer buffer; + NullDoubleWriter writer(buffer); - desc->Add(j.dump()); + writer.StartObject(); + BuildJSON(writer, val, name); + writer.EndObject(); + + desc->Add(buffer.GetString()); return true; } @@ -71,47 +82,56 @@ threading::Value* JSON::ParseValue(const string& s, const string& name, TypeTag return nullptr; } -ZeekJson JSON::BuildJSON(Value* val, const string& name) const +void JSON::BuildJSON(NullDoubleWriter& writer, Value* val, const string& name) const { - // If the value wasn't set, return a nullptr. This will get turned into a 'null' in the json output. if ( ! val->present ) - return nullptr; + { + writer.Null(); + return; + } - ZeekJson j; switch ( val->type ) { case TYPE_BOOL: - j = val->val.int_val != 0; + if ( ! name.empty() ) writer.Key(name); + writer.Bool(val->val.int_val != 0); break; case TYPE_INT: - j = val->val.int_val; + if ( ! name.empty() ) writer.Key(name); + writer.Int64(val->val.int_val); break; case TYPE_COUNT: case TYPE_COUNTER: - j = val->val.uint_val; + if ( ! name.empty() ) writer.Key(name); + writer.Uint64(val->val.uint_val); break; case TYPE_PORT: - j = val->val.port_val.port; + if ( ! name.empty() ) writer.Key(name); + writer.Uint64(val->val.port_val.port); break; case TYPE_SUBNET: - j = Formatter::Render(val->val.subnet_val); + if ( ! name.empty() ) writer.Key(name); + writer.String(Formatter::Render(val->val.subnet_val)); break; case TYPE_ADDR: - j = Formatter::Render(val->val.addr_val); + if ( ! name.empty() ) writer.Key(name); + writer.String(Formatter::Render(val->val.addr_val)); break; case TYPE_DOUBLE: case TYPE_INTERVAL: - j = val->val.double_val; + if ( ! name.empty() ) writer.Key(name); + writer.Double(val->val.double_val); break; case TYPE_TIME: { + if ( ! name.empty() ) writer.Key(name); if ( timestamps == TS_ISO8601 ) { char buffer[40]; @@ -125,7 +145,7 @@ ZeekJson JSON::BuildJSON(Value* val, const string& name) const GetThread()->Error(GetThread()->Fmt("json formatter: failure getting time: (%lf)", val->val.double_val)); // This was a failure, doesn't really matter what gets put here // but it should probably stand out... - j = "2000-01-01T00:00:00.000000"; + writer.String("2000-01-01T00:00:00.000000"); } else { @@ -136,17 +156,17 @@ ZeekJson JSON::BuildJSON(Value* val, const string& name) const frac += 1; snprintf(buffer2, sizeof(buffer2), "%s.%06.0fZ", buffer, fabs(frac) * 1000000); - j = buffer2; + writer.String(buffer2, strlen(buffer2)); } } else if ( timestamps == TS_EPOCH ) - j = val->val.double_val; + writer.Double(val->val.double_val); else if ( timestamps == TS_MILLIS ) { // ElasticSearch uses milliseconds for timestamps - j = (uint64_t) (val->val.double_val * 1000); + writer.Uint64((uint64_t) (val->val.double_val * 1000)); } break; @@ -157,36 +177,37 @@ ZeekJson JSON::BuildJSON(Value* val, const string& name) const case TYPE_FILE: case TYPE_FUNC: { - j = json_escape_utf8(string(val->val.string_val.data, val->val.string_val.length)); + if ( ! name.empty() ) writer.Key(name); + writer.String(json_escape_utf8(string(val->val.string_val.data, val->val.string_val.length))); break; } case TYPE_TABLE: { - j = ZeekJson::array(); + if ( ! name.empty() ) writer.Key(name); + writer.StartArray(); for ( int idx = 0; idx < val->val.set_val.size; idx++ ) - j.push_back(BuildJSON(val->val.set_val.vals[idx])); + BuildJSON(writer, val->val.set_val.vals[idx]); + writer.EndArray(); break; } case TYPE_VECTOR: { - j = ZeekJson::array(); + if ( ! name.empty() ) writer.Key(name); + writer.StartArray(); for ( int idx = 0; idx < val->val.vector_val.size; idx++ ) - j.push_back(BuildJSON(val->val.vector_val.vals[idx])); + BuildJSON(writer, val->val.vector_val.vals[idx]); + writer.EndArray(); break; } default: + reporter->Warning("Unhandled type in JSON::BuildJSON"); break; } - - if ( ! name.empty() && ! j.is_null() ) - return { { name, j } }; - - return j; } diff --git a/src/threading/formatters/JSON.h b/src/threading/formatters/JSON.h index 71edadc61d..e640264a3a 100644 --- a/src/threading/formatters/JSON.h +++ b/src/threading/formatters/JSON.h @@ -2,24 +2,14 @@ #pragma once -#include "../Formatter.h" -#include "3rdparty/json.hpp" -#include "3rdparty/tsl-ordered-map/ordered_map.h" +#define RAPIDJSON_HAS_STDSTRING 1 +#include "3rdparty/rapidjson/include/rapidjson/document.h" +#include "3rdparty/rapidjson/include/rapidjson/writer.h" +#include "../Formatter.h" namespace threading { namespace formatter { -// Define a class for use with the json library that orders the keys in the same order that -// they were inserted. By default, the json library orders them alphabetically and we don't -// want it like that. -template, class KeyEqual = std::equal_to, - class AllocatorPair = typename std::allocator_traits::template rebind_alloc>, - class ValueTypeContainer = std::vector, AllocatorPair>> -using ordered_map = tsl::ordered_map; - -using ZeekJson = nlohmann::basic_json; - /** * A thread-safe class for converting values into a JSON representation * and vice versa. @@ -42,7 +32,13 @@ public: private: - ZeekJson BuildJSON(Value* val, const string& name = "") const; + class NullDoubleWriter : public rapidjson::Writer { + public: + NullDoubleWriter(rapidjson::StringBuffer& stream) : rapidjson::Writer(stream) {} + bool Double(double d); + }; + + void BuildJSON(NullDoubleWriter& writer, Value* val, const string& name = "") const; TimeFormat timestamps; bool surrounding_braces; diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-double/json.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-double/json.log index bb0f950b13..99d353b197 100644 --- a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-double/json.log +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-double/json.log @@ -9,11 +9,11 @@ {"d":0.1234} {"d":50000.0} {"d":-50000.0} -{"d":3.14e+15} -{"d":-3.14e+15} -{"d":1.79e+308} -{"d":-1.79e+308} -{"d":1.23456789e-05} +{"d":3140000000000000.0} +{"d":-3140000000000000.0} +{"d":1.79e308} +{"d":-1.79e308} +{"d":0.0000123456789} {"d":2.23e-308} {"d":-2.23e-308} {"d":null} diff --git a/testing/btest/Baseline/scripts.base.utils.json/output b/testing/btest/Baseline/scripts.base.utils.json/output index 8757a51433..0794bd9587 100644 --- a/testing/btest/Baseline/scripts.base.utils.json/output +++ b/testing/btest/Baseline/scripts.base.utils.json/output @@ -2,7 +2,7 @@ true 123 -999 3.14 --1.23456789e+308 +-1.23456789e308 9e-308 1480788576.868945 "-12.0 hrs" From ee0619f99905bfbdb7590010ed217e659bf78890 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 8 Jan 2020 12:06:52 -0700 Subject: [PATCH 07/12] Expand unit test for json_escape_utf8 to include all of the strings from the ascii-json-utf8 btest --- src/util.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/util.cc b/src/util.cc index 2b46e38f7b..16ec14515a 100644 --- a/src/util.cc +++ b/src/util.cc @@ -2190,6 +2190,60 @@ TEST_CASE("util json_escape_utf8") CHECK(json_escape_utf8("string") == "string"); CHECK(json_escape_utf8("string\n") == "string\n"); CHECK(json_escape_utf8("string\x82") == "string\\x82"); + CHECK(json_escape_utf8("\x07\xd4\xb7o") == "\\x07Էo"); + + // These strings are duplicated from the scripts.base.frameworks.logging.ascii-json-utf8 btest + + // Valid ASCII and valid ASCII control characters + CHECK(json_escape_utf8("a") == "a"); + CHECK(json_escape_utf8("\b\f\n\r\t\x00\x15") == "\b\f\n\r\t\x00\x15"); + + // Table 3-7 in https://www.unicode.org/versions/Unicode12.0.0/ch03.pdf describes what is + // valid and invalid for the tests below + + // Valid 2 Octet Sequence + CHECK(json_escape_utf8("\xc3\xb1") == "\xc3\xb1"); + + // Invalid 2 Octet Sequence + CHECK(json_escape_utf8("\xc3\x28") == "\\xc3("); + CHECK(json_escape_utf8("\xc0\x81") == "\\xc0\\x81"); + CHECK(json_escape_utf8("\xc1\x81") == "\\xc1\\x81"); + CHECK(json_escape_utf8("\xc2\xcf") == "\\xc2\\xcf"); + + // Invalid Sequence Identifier + CHECK(json_escape_utf8("\xa0\xa1") == "\\xa0\\xa1"); + + // Valid 3 Octet Sequence + CHECK(json_escape_utf8("\xe2\x82\xa1") == "\xe2\x82\xa1"); + CHECK(json_escape_utf8("\xe0\xa3\xa1") == "\xe0\xa3\xa1"); + + // Invalid 3 Octet Sequence (in 2nd Octet) + CHECK(json_escape_utf8("\xe0\x80\xa1") == "\\xe0\\x80\\xa1"); + CHECK(json_escape_utf8("\xe2\x28\xa1") == "\\xe2(\\xa1"); + CHECK(json_escape_utf8("\xed\xa0\xa1") == "\\xed\\xa0\\xa1"); + + // Invalid 3 Octet Sequence (in 3rd Octet) + CHECK(json_escape_utf8("\xe2\x82\x28") == "\\xe2\\x82("); + + // Valid 4 Octet Sequence + CHECK(json_escape_utf8("\xf0\x90\x8c\xbc") == "\xf0\x90\x8c\xbc"); + CHECK(json_escape_utf8("\xf1\x80\x8c\xbc") == "\xf1\x80\x8c\xbc"); + CHECK(json_escape_utf8("\xf4\x80\x8c\xbc") == "\xf4\x80\x8c\xbc"); + + // Invalid 4 Octet Sequence (in 2nd Octet) + CHECK(json_escape_utf8("\xf0\x80\x8c\xbc") == "\\xf0\\x80\\x8c\\xbc"); + CHECK(json_escape_utf8("\xf2\x28\x8c\xbc") == "\\xf2(\\x8c\\xbc"); + CHECK(json_escape_utf8("\xf4\x90\x8c\xbc") == "\\xf4\\x90\\x8c\\xbc"); + + // Invalid 4 Octet Sequence (in 3rd Octet) + CHECK(json_escape_utf8("\xf0\x90\x28\xbc") == "\\xf0\\x90(\\xbc"); + + // Invalid 4 Octet Sequence (in 4th Octet) + CHECK(json_escape_utf8("\xf0\x28\x8c\x28") == "\\xf0(\\x8c("); + + // Invalid 4 Octet Sequence (too short) + CHECK(json_escape_utf8("\xf4\x80\x8c") == "\\xf4\\x80\\x8c"); + CHECK(json_escape_utf8("\xf0") == "\\xf0"); } string json_escape_utf8(const string& val) From 23f551876cc21ce98d9d180d95f81ae6d28c9e13 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Wed, 8 Jan 2020 12:08:32 -0700 Subject: [PATCH 08/12] Optimize json_escape_utf8 a bit by removing repeated calls to string methods --- src/util.cc | 46 +++++++++++++++++++++++++--------------------- src/util.h | 2 +- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/util.cc b/src/util.cc index 16ec14515a..d7a699ab6e 100644 --- a/src/util.cc +++ b/src/util.cc @@ -2248,50 +2248,54 @@ TEST_CASE("util json_escape_utf8") string json_escape_utf8(const string& val) { - string result; - result.reserve(val.length()); - auto val_data = reinterpret_cast(val.c_str()); + auto val_size = val.length(); + + // Reserve at least the size of the existing string to avoid resizing the string in the best-case + // scenario where we don't have any multi-byte characters. + string result; + result.reserve(val_size); size_t idx; - for ( idx = 0; idx < val.length(); ) + for ( idx = 0; idx < val_size; ) { - // Normal ASCII characters plus a few of the control characters can be inserted directly. The rest of - // the control characters should be escaped as regular bytes. - if ( ( val[idx] >= 32 && val[idx] <= 127 ) || - val[idx] == '\b' || val[idx] == '\f' || val[idx] == '\n' || val[idx] == '\r' || val[idx] == '\t' ) + char ch = val[idx]; + + // Normal ASCII characters plus a few of the control characters can be inserted directly. The + // rest of the control characters should be escaped as regular bytes. + if ( ( ch >= 32 && ch <= 127 ) || + ch == '\b' || ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' ) { - result.push_back(val[idx]); + result.push_back(ch); ++idx; continue; } - else if ( val[idx] >= 0 && val[idx] < 32 ) + else if ( ch >= 0 && ch < 32 ) { - result.append(json_escape_byte(val[idx])); + result.append(json_escape_byte(ch)); ++idx; continue; } // Find out how long the next character should be. - unsigned int char_size = getNumBytesForUTF8(val[idx]); + unsigned int char_size = getNumBytesForUTF8(ch); - // If it says that it's a single character or it's not an invalid string UTF8 sequence, insert the one - // escaped byte into the string, step forward one, and go to the next character. - if ( char_size == 0 || idx+char_size > val.length() || isLegalUTF8Sequence(val_data+idx, val_data+idx+char_size) == 0 ) + // If it says that it's a single character or it's not an valid string UTF8 sequence, insert + // the one escaped byte into the string, step forward one, and go to the next character. + if ( char_size == 0 || idx+char_size > val_size || isLegalUTF8Sequence(val_data+idx, val_data+idx+char_size) == 0 ) { - result.append(json_escape_byte(val[idx])); + result.append(json_escape_byte(ch)); ++idx; continue; } - for ( size_t step = 0; step < char_size; step++, idx++ ) - result.push_back(val[idx]); + result.append(val, idx, char_size); + idx += char_size; } // Insert any of the remaining bytes into the string as escaped bytes - if ( idx != val.length() ) - for ( ; idx < val.length(); ++idx ) - result.append(json_escape_byte(val[idx])); + for ( ; idx < val_size; ++idx ) + result.append(json_escape_byte(val[idx])); return result; } diff --git a/src/util.h b/src/util.h index 3665518f96..5a5a8c5159 100644 --- a/src/util.h +++ b/src/util.h @@ -118,7 +118,7 @@ std::string extract_ip_and_len(const std::string& i, int* len); inline void bytetohex(unsigned char byte, char* hex_out) { - static const char hex_chars[] = "0123456789abcdef"; + static constexpr char hex_chars[] = "0123456789abcdef"; hex_out[0] = hex_chars[(byte & 0xf0) >> 4]; hex_out[1] = hex_chars[byte & 0x0f]; } From 227d29db80f0769216de526a9fad83f6adfa5623 Mon Sep 17 00:00:00 2001 From: Tim Wojtulewicz Date: Tue, 14 Jan 2020 08:29:32 -0700 Subject: [PATCH 09/12] Use the list of files from clang-tidy when searching for unit tests The previous method for searching for these files included everything from src/3rdparty, which breaks when rapidjson is included. We don't want to include that directory anyways. We already had a good list of files to scan from the previous clang-tidy and adding any that are missing is an easy task. --- src/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c64f9608fa..0a2cfa388a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -438,9 +438,8 @@ create_clang_tidy_target() # Scan all .cc files for TEST_CASE macros and generate CTest targets. if (ENABLE_ZEEK_UNIT_TESTS) - file(GLOB_RECURSE all_cc_files "*.cc") set(test_cases "") - foreach (cc_file ${all_cc_files}) + foreach (cc_file ${TIDY_SRCS}) file (STRINGS ${cc_file} test_case_lines REGEX "TEST_CASE") foreach (line ${test_case_lines}) string(REGEX REPLACE "TEST_CASE\\(\"(.+)\"\\)" "\\1" test_case "${line}") From 1db7a222a02e30bf8faefd6140cb68d2f65a0b72 Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Wed, 15 Jan 2020 12:43:16 -0800 Subject: [PATCH 10/12] Handle invalid Base64 encodings in FTP ADAT analyzer --- src/analyzer/protocol/ftp/FTP.cc | 12 ++++++++++-- .../weird.log | 11 +++++++++++ .../Traces/globus-url-copy-bad-encoding.trace | Bin 0 -> 21556 bytes .../base/protocols/ftp/bad-adat-encoding.zeek | 2 ++ 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.ftp.bad-adat-encoding/weird.log create mode 100644 testing/btest/Traces/globus-url-copy-bad-encoding.trace create mode 100644 testing/btest/scripts/base/protocols/ftp/bad-adat-encoding.zeek diff --git a/src/analyzer/protocol/ftp/FTP.cc b/src/analyzer/protocol/ftp/FTP.cc index 39d034c616..97ce54c481 100644 --- a/src/analyzer/protocol/ftp/FTP.cc +++ b/src/analyzer/protocol/ftp/FTP.cc @@ -224,8 +224,16 @@ void FTP_ADAT_Analyzer::DeliverStream(int len, const u_char* data, bool orig) // framing is supposed to be required for the initial context // token, but GSI doesn't do that and starts right in on a // TLS/SSL handshake, so look for that to identify it. - const u_char* msg = decoded_adat->Bytes(); - int msg_len = decoded_adat->Len(); + const u_char* msg = nullptr; + int msg_len = 0; + + if ( decoded_adat ) + { + msg = decoded_adat->Bytes(); + msg_len = decoded_adat->Len(); + } + else + Weird("ftp_adat_bad_first_token_encoding"); // Just check that it looks like a viable TLS/SSL handshake // record from the first byte (content type of 0x16) and diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.bad-adat-encoding/weird.log b/testing/btest/Baseline/scripts.base.protocols.ftp.bad-adat-encoding/weird.log new file mode 100644 index 0000000000..a64ac860c3 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.bad-adat-encoding/weird.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path weird +#open 2020-01-15-20-41-16 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer +#types time string addr port addr port string string bool string +1348168976.514202 CHhAvVGS1DHFjwGM9 192.168.57.103 60108 192.168.57.101 2811 base64_illegal_encoding character 32 ignored by Base64 decoding F zeek +1348168976.514202 CHhAvVGS1DHFjwGM9 192.168.57.103 60108 192.168.57.101 2811 ftp_adat_bad_first_token_encoding - F zeek +#close 2020-01-15-20-41-16 diff --git a/testing/btest/Traces/globus-url-copy-bad-encoding.trace b/testing/btest/Traces/globus-url-copy-bad-encoding.trace new file mode 100644 index 0000000000000000000000000000000000000000..1a6d84c9ee5f5a60d2b989ddf6410e282bfa2628 GIT binary patch literal 21556 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 tX^HEO2J`%gH|p~BGbGNMnKciLb$n))j#q$D Date: Fri, 17 Jan 2020 11:43:00 +0000 Subject: [PATCH 11/12] Updating submodule(s). [nomail] --- aux/btest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/btest b/aux/btest index 37f8619c8a..f7bd3a7809 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit 37f8619c8ac89e7e9bcda6c167e8972a05d8e286 +Subproject commit f7bd3a78092a0807d69e9cc54ac41fbe1908cc21 From 270702cacbef264593f9b880cfc14a16437aebd0 Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Sat, 18 Jan 2020 14:32:30 +0000 Subject: [PATCH 12/12] Updating CHANGES and VERSION. --- CHANGES | 14 ++++++++++++++ VERSION | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 37448e56c4..ca3b76006b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,18 @@ +3.1.0-dev.389 | 2020-01-18 10:49:15 +0000 + + * GHI-595: Convert from nlohmann/json to RapidJSON for performance + reasons. (Tim Wojtulewicz, Corelight) + + * Optimize json_escape_utf8() and expand its unit tests. (Tim + Wojtulewicz, Corelight) + + * Convert type-checking macros to actual functions. (Tim + Wojtulewicz, Corelight) + + * Use the list of files from clang-tidy when searching for unit + tests. (Tim Wojtulewicz, Corelight) + 3.1.0-dev.383 | 2020-01-17 11:51:01 +0000 * Various code modernization cleanup. (Tim Wojtulewicz, Corelight) diff --git a/VERSION b/VERSION index e23f0788a6..31ca6dd848 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.0-dev.383 +3.1.0-dev.389