diff --git a/src/Desc.cc b/src/Desc.cc index ce6083800c..c15a461bb2 100644 --- a/src/Desc.cc +++ b/src/Desc.cc @@ -207,41 +207,71 @@ void ODesc::Indent() } } -static const char hex_chars[] = "0123456789ABCDEF"; +static const char hex_chars[] = "0123456789abcdef"; + +static const char* find_first_unprintable(ODesc* d, const char* bytes, unsigned int n) + { + if ( d->IsBinary() ) + return 0; + + while ( n-- ) + { + if ( ! isprint(*bytes) ) + return bytes; + ++bytes; + } + + return 0; + } void ODesc::AddBytes(const void* bytes, unsigned int n) { - if ( ! escape ) - return AddBytesRaw(bytes, n); - const char* s = (const char*) bytes; const char* e = (const char*) bytes + n; while ( s < e ) { - const char* t = (const char*) memchr(s, escape[0], e - s); + const char* t1 = escape ? (const char*) memchr(s, escape[0], e - s) : e; + const char* t2 = find_first_unprintable(this, s, t1 ? e - t1 : e - s); - if ( ! t ) + if ( t2 && (t2 < t1 || ! t1) ) + { + AddBytesRaw(s, t2 - s); + + char hex[6] = "\\x00"; + hex[2] = hex_chars[((*t2) & 0xf0) >> 4]; + hex[3] = hex_chars[(*t2) & 0x0f]; + AddBytesRaw(hex, sizeof(hex)); + + s = t2 + 1; + continue; + } + + if ( ! escape ) break; - if ( memcmp(t, escape, escape_len) != 0 ) + if ( ! t1 ) break; - AddBytesRaw(s, t - s); + if ( memcmp(t1, escape, escape_len) != 0 ) + break; + + AddBytesRaw(s, t1 - s); for ( int i = 0; i < escape_len; ++i ) { char hex[5] = "\\x00"; - hex[2] = hex_chars[(*t) >> 4]; - hex[3] = hex_chars[(*t) & 0x0f]; + hex[2] = hex_chars[((*t1) & 0xf0) >> 4]; + hex[3] = hex_chars[(*t1) & 0x0f]; AddBytesRaw(hex, sizeof(hex)); - ++t; + ++t1; } - s = t; + s = t1; } - AddBytesRaw(s, e - s); + if ( s < e ) + AddBytesRaw(s, e - s); } void ODesc::AddBytesRaw(const void* bytes, unsigned int n) diff --git a/src/LogWriterAscii.cc b/src/LogWriterAscii.cc index 4c54e76715..d831960a3c 100644 --- a/src/LogWriterAscii.cc +++ b/src/LogWriterAscii.cc @@ -223,7 +223,7 @@ bool LogWriterAscii::DoWrite(int num_fields, const LogField* const * fields, return false; } - desc.Add("\n"); + desc.AddRaw("\n", 1); if ( fwrite(desc.Bytes(), desc.Len(), 1, file) != 1 ) { diff --git a/testing/btest/Baseline/logging.ascii-binary/ssh.log b/testing/btest/Baseline/logging.ascii-binary/ssh.log new file mode 100644 index 0000000000..84a2cc609e Binary files /dev/null and b/testing/btest/Baseline/logging.ascii-binary/ssh.log differ diff --git a/testing/btest/Baseline/logging.ascii-escape/ssh.log b/testing/btest/Baseline/logging.ascii-escape/ssh.log index 6797e1e302..aa08625281 100644 Binary files a/testing/btest/Baseline/logging.ascii-escape/ssh.log and b/testing/btest/Baseline/logging.ascii-escape/ssh.log differ diff --git a/testing/btest/logging/ascii-binary.bro b/testing/btest/logging/ascii-binary.bro new file mode 100644 index 0000000000..6f095db0c7 --- /dev/null +++ b/testing/btest/logging/ascii-binary.bro @@ -0,0 +1,25 @@ +# +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { SSH }; + + type Log: record { + data: string; + data2: string; + } &log; +} + +redef LogAscii::separator = "|"; + +event bro_init() +{ + Log::create_stream(SSH, [$columns=Log]); + Log::write(SSH, [$data="abc\n\xffdef", $data2="DATA2"]); + Log::write(SSH, [$data="abc|\xffdef", $data2="DATA2"]); + Log::write(SSH, [$data="abc\xff|def", $data2="DATA2"]); +} +