diff --git a/src/threading/formatters/Ascii.cc b/src/threading/formatters/Ascii.cc index f1cbac783f..2f0868f589 100644 --- a/src/threading/formatters/Ascii.cc +++ b/src/threading/formatters/Ascii.cc @@ -9,6 +9,22 @@ 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() { separator = "SHOULD_NOT_BE_USED"; @@ -116,23 +132,13 @@ bool Ascii::Describe(ODesc* desc, threading::Value* val, const string& name) con break; } - if ( size == (int)separators.unset_field.size() && memcmp(data, separators.unset_field.data(), size) == 0 ) - { - // 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); + if ( escapeReservedContent(desc, separators.unset_field, data, size) ) + break; - ++data; - --size; - } - - if ( size ) - desc->AddN(data, size); + if ( escapeReservedContent(desc, separators.empty_field, data, size) ) + break; + desc->AddN(data, size); break; } diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-empty-str/test.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-empty-str/test.log new file mode 100644 index 0000000000..5ca5787f4e --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-empty-str/test.log @@ -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 diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-escape-empty-str.bro b/testing/btest/scripts/base/frameworks/logging/ascii-escape-empty-str.bro new file mode 100644 index 0000000000..e18926a194 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-escape-empty-str.bro @@ -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") + ]); +}