Escape the empty indicator in logs if it occurs literally as a field's

actual content.

Addresses BIT-931.
This commit is contained in:
Robin Sommer 2016-07-05 16:34:24 -07:00
parent 9360112e8a
commit 721693425f
3 changed files with 55 additions and 15 deletions

View file

@ -9,6 +9,22 @@
using namespace threading::formatter; using namespace threading::formatter;
// If the value we'd write out would match exactly the a reserved string, we
// escape the first character so that the output won't be ambigious. If this
// function returns true, it has added an escaped version of data to desc.
static inline bool escapeReservedContent(ODesc* desc, const string& reserved, const char* data, int size)
{
if ( size != (int)reserved.size() || memcmp(data, reserved.data(), size) != 0 )
return false;
char hex[4] = {'\\', 'x', '0', '0'};
bytetohex(*data, hex + 2);
desc->AddRaw(hex, 4);
desc->AddN(data + 1, size - 1);
return true;
}
Ascii::SeparatorInfo::SeparatorInfo() Ascii::SeparatorInfo::SeparatorInfo()
{ {
separator = "SHOULD_NOT_BE_USED"; separator = "SHOULD_NOT_BE_USED";
@ -116,23 +132,13 @@ bool Ascii::Describe(ODesc* desc, threading::Value* val, const string& name) con
break; break;
} }
if ( size == (int)separators.unset_field.size() && memcmp(data, separators.unset_field.data(), size) == 0 ) if ( escapeReservedContent(desc, separators.unset_field, data, size) )
{ break;
// The value we'd write out would match exactly the
// place-holder we use for unset optional fields. We
// escape the first character so that the output
// won't be ambigious.
char hex[4] = {'\\', 'x', '0', '0'};
bytetohex(*data, hex + 2);
desc->AddRaw(hex, 4);
++data; if ( escapeReservedContent(desc, separators.empty_field, data, size) )
--size; break;
}
if ( size )
desc->AddN(data, size);
desc->AddN(data, size);
break; break;
} }

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field EMPTY
#unset_field -
#path test
#open 2016-07-05-23-20-42
#fields ss
#types set[string]
\x45MPTY
#close 2016-07-05-23-20-42

View file

@ -0,0 +1,24 @@
#
# @TEST-EXEC: bro -b %INPUT
# @TEST-EXEC: btest-diff test.log
redef LogAscii::empty_field = "EMPTY";
module test;
export {
redef enum Log::ID += { LOG };
type Log: record {
ss: set[string];
} &log;
}
event bro_init()
{
Log::create_stream(test::LOG, [$columns=Log]);
Log::write(test::LOG, [
$ss=set("EMPTY")
]);
}