This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
The following commit(s) were added to refs/heads/master by this push:
new e20cab01 Improve robustness when logging large message strings (#593)
e20cab01 is described below
commit e20cab0192fed4c53142bd5656644877f41baba1
Author: Stephen Webb <[email protected]>
AuthorDate: Fri Feb 13 10:01:22 2026 +1100
Improve robustness when logging large message strings (#593)
* Add a compiler warning when the deprecated method is used
* Make MDC JSON pattern layout formatting skip entries that exceed the
maximum field length
* Add deprecation status to html docs
---
src/fuzzers/cpp/PatternParserFuzzer.cpp | 9 +-----
src/main/cpp/classnamepatternconverter.cpp | 6 ----
src/main/cpp/filelocationpatternconverter.cpp | 3 +-
src/main/cpp/formattinginfo.cpp | 4 ++-
src/main/cpp/fulllocationpatternconverter.cpp | 3 +-
src/main/cpp/integerpatternconverter.cpp | 3 +-
src/main/cpp/levelpatternconverter.cpp | 3 +-
src/main/cpp/linelocationpatternconverter.cpp | 3 +-
src/main/cpp/lineseparatorpatternconverter.cpp | 3 +-
src/main/cpp/loggerpatternconverter.cpp | 6 ----
src/main/cpp/mdcpatternconverter.cpp | 34 +++++++++++++++-------
src/main/cpp/messagepatternconverter.cpp | 10 +++++--
src/main/cpp/methodlocationpatternconverter.cpp | 3 +-
src/main/cpp/ndcpatternconverter.cpp | 14 +++++++--
src/main/cpp/patternconverter.cpp | 9 ++++++
src/main/cpp/patternlayout.cpp | 26 ++++-------------
src/main/cpp/patternparser.cpp | 29 ++++++++++--------
src/main/cpp/propertiespatternconverter.cpp | 3 +-
src/main/cpp/rollingpolicybase.cpp | 19 +++---------
src/main/cpp/shortfilelocationpatternconverter.cpp | 3 +-
src/main/cpp/threadpatternconverter.cpp | 3 +-
src/main/cpp/threadusernamepatternconverter.cpp | 3 +-
.../cpp/throwableinformationpatternconverter.cpp | 6 ++--
.../include/log4cxx/pattern/patternconverter.h | 11 +++++++
src/main/include/log4cxx/pattern/patternparser.h | 19 ++++++++++--
.../log4cxx/private/patternconverter_priv.h | 6 ++++
.../log4cxx/private/rollingpolicybase_priv.h | 5 ----
.../include/log4cxx/rolling/rollingpolicybase.h | 1 -
src/test/cpp/mdctestcase.cpp | 17 +++++++++--
src/test/cpp/ndctestcase.cpp | 15 ++++++++++
src/test/cpp/pattern/patternparsertestcase.cpp | 13 +++------
src/test/cpp/patternlayouttest.cpp | 17 +++++++++++
src/test/cpp/rolling/filenamepatterntestcase.cpp | 13 +++------
33 files changed, 182 insertions(+), 140 deletions(-)
diff --git a/src/fuzzers/cpp/PatternParserFuzzer.cpp
b/src/fuzzers/cpp/PatternParserFuzzer.cpp
index 4b1f2865..a5d96db1 100644
--- a/src/fuzzers/cpp/PatternParserFuzzer.cpp
+++ b/src/fuzzers/cpp/PatternParserFuzzer.cpp
@@ -131,14 +131,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data,
size_t size) {
log4cxx::spi::LoggingEventPtr event = log4cxx::spi::LoggingEventPtr(
new log4cxx::spi::LoggingEvent(
logger, level, contentLogString, LOG4CXX_LOCATION));
-
-
- log4cxx::helpers::Pool p;
- PatternMap patternMap = getFormatSpecifiers();
- std::vector<PatternConverterPtr> converters;
- std::vector<FormattingInfoPtr> fields;
-
- PatternParser::parse(patternLogString, converters, fields, patternMap);
+ auto converters = PatternParser::parse(patternLogString,
getFormatSpecifiers());
return 0;
}
diff --git a/src/main/cpp/classnamepatternconverter.cpp
b/src/main/cpp/classnamepatternconverter.cpp
index 27226aaf..4af44420 100644
--- a/src/main/cpp/classnamepatternconverter.cpp
+++ b/src/main/cpp/classnamepatternconverter.cpp
@@ -37,12 +37,6 @@ ClassNamePatternConverter::ClassNamePatternConverter(
PatternConverterPtr ClassNamePatternConverter::newInstance(
const std::vector<LogString>& options)
{
- if (options.size() == 0)
- {
- static WideLife<PatternConverterPtr> def =
std::make_shared<ClassNamePatternConverter>(options);
- return def;
- }
-
return std::make_shared<ClassNamePatternConverter>(options);
}
diff --git a/src/main/cpp/filelocationpatternconverter.cpp
b/src/main/cpp/filelocationpatternconverter.cpp
index efb40664..93a9e0d0 100644
--- a/src/main/cpp/filelocationpatternconverter.cpp
+++ b/src/main/cpp/filelocationpatternconverter.cpp
@@ -35,8 +35,7 @@ FileLocationPatternConverter::FileLocationPatternConverter() :
PatternConverterPtr FileLocationPatternConverter::newInstance(
const std::vector<LogString>& /* options */ )
{
- static WideLife<PatternConverterPtr> instance =
std::make_shared<FileLocationPatternConverter>();
- return instance;
+ return std::make_shared<FileLocationPatternConverter>();
}
void FileLocationPatternConverter::format(
diff --git a/src/main/cpp/formattinginfo.cpp b/src/main/cpp/formattinginfo.cpp
index 2f62545a..56ef54a8 100644
--- a/src/main/cpp/formattinginfo.cpp
+++ b/src/main/cpp/formattinginfo.cpp
@@ -79,7 +79,9 @@ FormattingInfoPtr FormattingInfo::getDefault()
*/
void FormattingInfo::format(const int fieldStart, LogString& buffer) const
{
- int rawLength = int(buffer.length() - fieldStart);
+ if (INT_MAX < buffer.length())
+ return;
+ int rawLength = static_cast<int>(buffer.length()) - fieldStart;
if (rawLength > m_priv->maxLength)
{
diff --git a/src/main/cpp/fulllocationpatternconverter.cpp
b/src/main/cpp/fulllocationpatternconverter.cpp
index 50505275..ffec5abf 100644
--- a/src/main/cpp/fulllocationpatternconverter.cpp
+++ b/src/main/cpp/fulllocationpatternconverter.cpp
@@ -37,8 +37,7 @@ FullLocationPatternConverter::FullLocationPatternConverter() :
PatternConverterPtr FullLocationPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> instance =
std::make_shared<FullLocationPatternConverter>();
- return instance;
+ return std::make_shared<FullLocationPatternConverter>();
}
void FullLocationPatternConverter::format(
diff --git a/src/main/cpp/integerpatternconverter.cpp
b/src/main/cpp/integerpatternconverter.cpp
index 3e8d3c58..6e9d3ae3 100644
--- a/src/main/cpp/integerpatternconverter.cpp
+++ b/src/main/cpp/integerpatternconverter.cpp
@@ -35,8 +35,7 @@ IntegerPatternConverter::IntegerPatternConverter() :
PatternConverterPtr IntegerPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> instance =
std::make_shared<IntegerPatternConverter>();
- return instance;
+ return std::make_shared<IntegerPatternConverter>();
}
void IntegerPatternConverter::format(
diff --git a/src/main/cpp/levelpatternconverter.cpp
b/src/main/cpp/levelpatternconverter.cpp
index 137543fc..725a8cb0 100644
--- a/src/main/cpp/levelpatternconverter.cpp
+++ b/src/main/cpp/levelpatternconverter.cpp
@@ -38,8 +38,7 @@ LevelPatternConverter::LevelPatternConverter() :
PatternConverterPtr LevelPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> def =
std::make_shared<LevelPatternConverter>();
- return def;
+ return std::make_shared<LevelPatternConverter>();
}
void LevelPatternConverter::format(
diff --git a/src/main/cpp/linelocationpatternconverter.cpp
b/src/main/cpp/linelocationpatternconverter.cpp
index bf1f42f9..693611fc 100644
--- a/src/main/cpp/linelocationpatternconverter.cpp
+++ b/src/main/cpp/linelocationpatternconverter.cpp
@@ -37,8 +37,7 @@ LineLocationPatternConverter::LineLocationPatternConverter() :
PatternConverterPtr LineLocationPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> instance =
std::make_shared<LineLocationPatternConverter>();
- return instance;
+ return std::make_shared<LineLocationPatternConverter>();
}
void LineLocationPatternConverter::format(
diff --git a/src/main/cpp/lineseparatorpatternconverter.cpp
b/src/main/cpp/lineseparatorpatternconverter.cpp
index 871ccaec..63cfc540 100644
--- a/src/main/cpp/lineseparatorpatternconverter.cpp
+++ b/src/main/cpp/lineseparatorpatternconverter.cpp
@@ -36,8 +36,7 @@
LineSeparatorPatternConverter::LineSeparatorPatternConverter() :
PatternConverterPtr LineSeparatorPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> instance =
std::make_shared<LineSeparatorPatternConverter>();
- return instance;
+ return std::make_shared<LineSeparatorPatternConverter>();
}
void LineSeparatorPatternConverter::format(
diff --git a/src/main/cpp/loggerpatternconverter.cpp
b/src/main/cpp/loggerpatternconverter.cpp
index 70e9aa1b..326390e8 100644
--- a/src/main/cpp/loggerpatternconverter.cpp
+++ b/src/main/cpp/loggerpatternconverter.cpp
@@ -37,12 +37,6 @@ LoggerPatternConverter::LoggerPatternConverter(
PatternConverterPtr LoggerPatternConverter::newInstance(
const std::vector<LogString>& options)
{
- if (options.size() == 0)
- {
- static WideLife<PatternConverterPtr> def =
std::make_shared<LoggerPatternConverter>(options);
- return def;
- }
-
return std::make_shared<LoggerPatternConverter>(options);
}
diff --git a/src/main/cpp/mdcpatternconverter.cpp
b/src/main/cpp/mdcpatternconverter.cpp
index 25db86b8..a70bc69e 100644
--- a/src/main/cpp/mdcpatternconverter.cpp
+++ b/src/main/cpp/mdcpatternconverter.cpp
@@ -38,10 +38,7 @@ PatternConverterPtr MDCPatternConverter::newInstance(
const std::vector<LogString>& options)
{
if (options.empty())
- {
- static helpers::WideLife<PatternConverterPtr> def =
std::make_shared<MDCPatternConverter>();
- return def;
- }
+ return std::make_shared<MDCPatternConverter>();
return std::make_shared<MDCPatternConverter>(LogString(),
options.front());
}
@@ -52,24 +49,39 @@ void MDCPatternConverter::format
) const
{
size_t startIndex = toAppendTo.size();
+ auto& info = getFormattingInfo();
if (m_priv->name.empty()) // Full MDC required?
{
- bool first = true;
+ const size_t separCount = 2;
+ const size_t quoteCount = 2;
+ LogString separ = LOG4CXX_STR("{");
+ size_t remainingLength = info.getMaxLength() - 1;
for (auto key : event->getMDCKeySet())
{
- toAppendTo.append(first ? LOG4CXX_STR("{") :
LOG4CXX_STR(","));
- JSONLayout::appendItem(key, toAppendTo);
- toAppendTo.append(LOG4CXX_STR(":"));
LogString value;
event->getMDC(key, value);
+ auto itemLength = separCount + key.length() +
quoteCount + value.length() + quoteCount;
+ if (remainingLength < itemLength)
+ break;
+ toAppendTo.append(separ);
+ JSONLayout::appendItem(key, toAppendTo);
+ toAppendTo.append(LOG4CXX_STR(":"));
JSONLayout::appendItem(value, toAppendTo);
- first = false;
+ separ = LOG4CXX_STR(",");
+ remainingLength -= itemLength;
}
- if (!first)
+ if (LOG4CXX_STR(",") == separ)
toAppendTo.append(LOG4CXX_STR("}"));
}
else
- event->getMDC(m_priv->name, toAppendTo);
+ {
+ LogString value;
+ event->getMDC(m_priv->name, value);
+ if (info.getMaxLength() < value.length())
+ toAppendTo.append(value.substr(value.length() -
info.getMaxLength()));
+ else
+ toAppendTo.append(value);
+ }
if (!m_priv->style.empty()) // In a quoted context?
{
auto quote = m_priv->style.front();
diff --git a/src/main/cpp/messagepatternconverter.cpp
b/src/main/cpp/messagepatternconverter.cpp
index 6b0712ff..f31ba448 100644
--- a/src/main/cpp/messagepatternconverter.cpp
+++ b/src/main/cpp/messagepatternconverter.cpp
@@ -72,8 +72,7 @@ PatternConverterPtr MessagePatternConverter::newInstance(
{
if (options.empty() || options.front().empty())
{
- static helpers::WideLife<PatternConverterPtr> def =
std::make_shared<MessagePatternConverter>();
- return def;
+ return std::make_shared<MessagePatternConverter>();
}
return
std::make_shared<QuotedMessagePatternConverter>(options.front().front());
}
@@ -84,6 +83,11 @@ void MessagePatternConverter::format
, helpers::Pool& /* p */
) const
{
- toAppendTo.append(event->getRenderedMessage());
+ auto& msg = event->getRenderedMessage();
+ auto& info = getFormattingInfo();
+ if (info.getMaxLength() < msg.length())
+ toAppendTo.append(&msg[msg.length() - info.getMaxLength()],
info.getMaxLength());
+ else
+ toAppendTo.append(msg);
}
diff --git a/src/main/cpp/methodlocationpatternconverter.cpp
b/src/main/cpp/methodlocationpatternconverter.cpp
index 2e479c8b..db0cb7aa 100644
--- a/src/main/cpp/methodlocationpatternconverter.cpp
+++ b/src/main/cpp/methodlocationpatternconverter.cpp
@@ -36,8 +36,7 @@
MethodLocationPatternConverter::MethodLocationPatternConverter() :
PatternConverterPtr MethodLocationPatternConverter::newInstance(
const std::vector<LogString>& /* options */ )
{
- static WideLife<PatternConverterPtr> def =
std::make_shared<MethodLocationPatternConverter>();
- return def;
+ return std::make_shared<MethodLocationPatternConverter>();
}
void MethodLocationPatternConverter::format(
diff --git a/src/main/cpp/ndcpatternconverter.cpp
b/src/main/cpp/ndcpatternconverter.cpp
index 6b05759c..c8a6b500 100644
--- a/src/main/cpp/ndcpatternconverter.cpp
+++ b/src/main/cpp/ndcpatternconverter.cpp
@@ -36,8 +36,7 @@ NDCPatternConverter::NDCPatternConverter() :
PatternConverterPtr NDCPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> def =
std::make_shared<NDCPatternConverter>();
- return def;
+ return std::make_shared<NDCPatternConverter>();
}
void NDCPatternConverter::format(
@@ -45,7 +44,16 @@ void NDCPatternConverter::format(
LogString& toAppendTo,
Pool& /* p */) const
{
- if (!event->getNDC(toAppendTo))
+ LogString value;
+ if (event->getNDC(value))
+ {
+ auto& info = getFormattingInfo();
+ if (info.getMaxLength() < value.length())
+ toAppendTo.append(value.substr(value.length() -
info.getMaxLength()));
+ else
+ toAppendTo.append(value);
+ }
+ else
{
toAppendTo.append(LOG4CXX_STR("null"));
}
diff --git a/src/main/cpp/patternconverter.cpp
b/src/main/cpp/patternconverter.cpp
index 5fe92c3e..c1120da0 100644
--- a/src/main/cpp/patternconverter.cpp
+++ b/src/main/cpp/patternconverter.cpp
@@ -58,3 +58,12 @@ void PatternConverter::append(LogString& toAppendTo, const
std::string& src)
toAppendTo.append(decoded);
}
+const FormattingInfo& PatternConverter::getFormattingInfo() const
+{
+ return *m_priv->info;
+}
+
+void PatternConverter::setFormattingInfo(const FormattingInfoPtr& newValue)
+{
+ m_priv->info = newValue;
+}
diff --git a/src/main/cpp/patternlayout.cpp b/src/main/cpp/patternlayout.cpp
index 68d43c5e..6a29183d 100644
--- a/src/main/cpp/patternlayout.cpp
+++ b/src/main/cpp/patternlayout.cpp
@@ -75,11 +75,6 @@ struct PatternLayout::PatternLayoutPrivate
*/
LoggingEventPatternConverterList patternConverters;
- /**
- * Field widths and alignment corresponding to pattern converters.
- */
- FormattingInfoList patternFields;
-
LogString m_fatalColor = LOG4CXX_STR("\\x1B[35m"); //magenta
LogString m_errorColor = LOG4CXX_STR("\\x1B[31m"); //red
LogString m_warnColor = LOG4CXX_STR("\\x1B[33m"); //yellow
@@ -124,17 +119,13 @@ void PatternLayout::format(LogString& output,
{
auto& lsMsg = event->getRenderedMessage();
output.reserve(m_priv->expectedPatternLength + lsMsg.size());
- std::vector<FormattingInfoPtr>::const_iterator formatterIter =
- m_priv->patternFields.begin();
- for (std::vector<LoggingEventPatternConverterPtr>::const_iterator
- converterIter = m_priv->patternConverters.begin();
- converterIter != m_priv->patternConverters.end();
- converterIter++, formatterIter++)
+ for (auto item : m_priv->patternConverters)
{
- int startField = (int)output.length();
- (*converterIter)->format(event, output, pool);
- (*formatterIter)->format(startField, output);
+ auto startField = output.length();
+ item->format(event, output, pool);
+ if (startField < INT_MAX)
+
item->getFormattingInfo().format(static_cast<int>(startField), output);
}
}
@@ -189,12 +180,7 @@ void PatternLayout::activateOptions(Pool&)
}
m_priv->patternConverters.erase(m_priv->patternConverters.begin(),
m_priv->patternConverters.end());
- m_priv->patternFields.erase(m_priv->patternFields.begin(),
m_priv->patternFields.end());
- std::vector<PatternConverterPtr> converters;
- PatternParser::parse(pat,
- converters,
- m_priv->patternFields,
- getFormatSpecifiers());
+ auto converters = PatternParser::parse(pat, getFormatSpecifiers());
//
// strip out any pattern converters that don't handle LoggingEvents
diff --git a/src/main/cpp/patternparser.cpp b/src/main/cpp/patternparser.cpp
index d27ba07e..ded7a37d 100644
--- a/src/main/cpp/patternparser.cpp
+++ b/src/main/cpp/patternparser.cpp
@@ -112,13 +112,23 @@ size_t PatternParser::extractOptions(const LogString&
pattern, LogString::size_t
return i;
}
+#if LOG4CXX_ABI_VERSION <= 15
void PatternParser::parse(
const LogString& pattern,
std::vector<PatternConverterPtr>& patternConverters,
std::vector<FormattingInfoPtr>& formattingInfos,
const PatternMap& rules)
{
+ patternConverters = parse(pattern, rules);
+}
+#endif
+PatternConverterList PatternParser::parse
+ ( const LogString& pattern
+ , const PatternMap& rules
+ )
+{
+ PatternConverterList patternConverters;
LogString currentLiteral;
size_t patternLength = pattern.length();
@@ -126,7 +136,7 @@ void PatternParser::parse(
logchar c;
size_t i = 0;
int minDigitCount{ 0 }, maxDigitCount{ 0 };
- FormattingInfoPtr formattingInfo(FormattingInfo::getDefault());
+ auto formattingInfo = FormattingInfo::getDefault();
while (i < patternLength)
{
@@ -158,7 +168,6 @@ void PatternParser::parse(
{
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
-
formattingInfos.push_back(FormattingInfo::getDefault());
currentLiteral.erase(currentLiteral.begin(), currentLiteral.end());
}
@@ -205,7 +214,7 @@ void PatternParser::parse(
{
i = finalizeConverter(
c,
pattern, i, currentLiteral, formattingInfo,
- rules,
patternConverters, formattingInfos);
+ rules,
patternConverters);
// Next pattern is
assumed to be a literal.
state = LITERAL_STATE;
@@ -239,7 +248,7 @@ void PatternParser::parse(
{
i = finalizeConverter(
c, pattern, i,
currentLiteral, formattingInfo,
- rules,
patternConverters, formattingInfos);
+ rules,
patternConverters);
state = LITERAL_STATE;
formattingInfo =
FormattingInfo::getDefault();
@@ -285,7 +294,7 @@ void PatternParser::parse(
{
i = finalizeConverter(
c, pattern, i,
currentLiteral, formattingInfo,
- rules,
patternConverters, formattingInfos);
+ rules,
patternConverters);
state = LITERAL_STATE;
formattingInfo =
FormattingInfo::getDefault();
@@ -304,8 +313,8 @@ void PatternParser::parse(
{
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
- formattingInfos.push_back(FormattingInfo::getDefault());
}
+ return patternConverters;
}
@@ -340,8 +349,7 @@ size_t PatternParser::finalizeConverter(
logchar c, const LogString& pattern, size_t i,
LogString& currentLiteral, const FormattingInfoPtr& formattingInfo,
const PatternMap& rules,
- std::vector<PatternConverterPtr>& patternConverters,
- std::vector<FormattingInfoPtr>& formattingInfos)
+ PatternConverterList& patternConverters)
{
LogString convBuf;
i = extractConverter(c, pattern, i, convBuf, currentLiteral);
@@ -351,7 +359,6 @@ size_t PatternParser::finalizeConverter(
LogLog::error(LOG4CXX_STR("Empty conversion specifier"));
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
- formattingInfos.push_back(FormattingInfo::getDefault());
}
else
{
@@ -372,18 +379,16 @@ size_t PatternParser::finalizeConverter(
LogLog::error(msg);
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
- formattingInfos.push_back(FormattingInfo::getDefault());
}
else
{
patternConverters.push_back(pc);
- formattingInfos.push_back(formattingInfo);
+ pc->setFormattingInfo(formattingInfo);
if (currentLiteral.length() > 0)
{
patternConverters.push_back(
LiteralPatternConverter::newInstance(currentLiteral));
-
formattingInfos.push_back(FormattingInfo::getDefault());
}
}
}
diff --git a/src/main/cpp/propertiespatternconverter.cpp
b/src/main/cpp/propertiespatternconverter.cpp
index ef9c3521..46b148bc 100644
--- a/src/main/cpp/propertiespatternconverter.cpp
+++ b/src/main/cpp/propertiespatternconverter.cpp
@@ -56,9 +56,8 @@ PatternConverterPtr PropertiesPatternConverter::newInstance(
{
if (options.size() == 0)
{
- static WideLife<PatternConverterPtr> def =
std::make_shared<PropertiesPatternConverter>(
+ return std::make_shared<PropertiesPatternConverter>(
LOG4CXX_STR("Properties"), LOG4CXX_STR(""));
- return def;
}
LogString converterName(LOG4CXX_STR("Property{"));
diff --git a/src/main/cpp/rollingpolicybase.cpp
b/src/main/cpp/rollingpolicybase.cpp
index e6630412..a4560753 100644
--- a/src/main/cpp/rollingpolicybase.cpp
+++ b/src/main/cpp/rollingpolicybase.cpp
@@ -95,12 +95,7 @@ LogString RollingPolicyBase::getFileNamePattern() const
*/
void RollingPolicyBase::parseFileNamePattern()
{
- m_priv->patternConverters.erase(m_priv->patternConverters.begin(),
m_priv->patternConverters.end());
- m_priv->patternFields.erase(m_priv->patternFields.begin(),
m_priv->patternFields.end());
- PatternParser::parse(m_priv->fileNamePatternStr,
- m_priv->patternConverters,
- m_priv->patternFields,
- getFormatSpecifiers());
+ m_priv->patternConverters =
PatternParser::parse(m_priv->fileNamePatternStr, getFormatSpecifiers());
}
/**
@@ -114,17 +109,11 @@ void RollingPolicyBase::formatFileName(
LogString& toAppendTo,
Pool& pool) const
{
- std::vector<FormattingInfoPtr>::const_iterator formatterIter =
- m_priv->patternFields.begin();
-
- for (std::vector<PatternConverterPtr>::const_iterator
- converterIter = m_priv->patternConverters.begin();
- converterIter != m_priv->patternConverters.end();
- converterIter++, formatterIter++)
+ for (auto item : m_priv->patternConverters)
{
auto startField = toAppendTo.length();
- (*converterIter)->format(obj, toAppendTo, pool);
- (*formatterIter)->format((int)startField, toAppendTo);
+ item->format(obj, toAppendTo, pool);
+ item->getFormattingInfo().format((int)startField, toAppendTo);
}
}
diff --git a/src/main/cpp/shortfilelocationpatternconverter.cpp
b/src/main/cpp/shortfilelocationpatternconverter.cpp
index 0bd2ed88..f4f7d7b3 100644
--- a/src/main/cpp/shortfilelocationpatternconverter.cpp
+++ b/src/main/cpp/shortfilelocationpatternconverter.cpp
@@ -34,8 +34,7 @@
ShortFileLocationPatternConverter::ShortFileLocationPatternConverter() :
PatternConverterPtr ShortFileLocationPatternConverter::newInstance(
const std::vector<LogString> & /* options */ ) {
- static WideLife<PatternConverterPtr> instance(new
ShortFileLocationPatternConverter());
- return instance;
+ return PatternConverterPtr(new ShortFileLocationPatternConverter());
}
void ShortFileLocationPatternConverter::format(
diff --git a/src/main/cpp/threadpatternconverter.cpp
b/src/main/cpp/threadpatternconverter.cpp
index 18c054df..9464502a 100644
--- a/src/main/cpp/threadpatternconverter.cpp
+++ b/src/main/cpp/threadpatternconverter.cpp
@@ -36,8 +36,7 @@ ThreadPatternConverter::ThreadPatternConverter() :
PatternConverterPtr ThreadPatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> def =
std::make_shared<ThreadPatternConverter>();
- return def;
+ return std::make_shared<ThreadPatternConverter>();
}
void ThreadPatternConverter::format(
diff --git a/src/main/cpp/threadusernamepatternconverter.cpp
b/src/main/cpp/threadusernamepatternconverter.cpp
index 621393b1..40794e7c 100644
--- a/src/main/cpp/threadusernamepatternconverter.cpp
+++ b/src/main/cpp/threadusernamepatternconverter.cpp
@@ -36,8 +36,7 @@
ThreadUsernamePatternConverter::ThreadUsernamePatternConverter() :
PatternConverterPtr ThreadUsernamePatternConverter::newInstance(
const std::vector<LogString>& /* options */)
{
- static WideLife<PatternConverterPtr> def =
std::make_shared<ThreadUsernamePatternConverter>();
- return def;
+ return std::make_shared<ThreadUsernamePatternConverter>();
}
void ThreadUsernamePatternConverter::format(
diff --git a/src/main/cpp/throwableinformationpatternconverter.cpp
b/src/main/cpp/throwableinformationpatternconverter.cpp
index 45e4fafe..d03d3b29 100644
--- a/src/main/cpp/throwableinformationpatternconverter.cpp
+++ b/src/main/cpp/throwableinformationpatternconverter.cpp
@@ -56,12 +56,10 @@ PatternConverterPtr
ThrowableInformationPatternConverter::newInstance(
{
if (options.size() > 0 && options[0].compare(LOG4CXX_STR("short")) == 0)
{
- static WideLife<PatternConverterPtr> shortConverter =
std::make_shared<ThrowableInformationPatternConverter>(true);
- return shortConverter;
+ return
std::make_shared<ThrowableInformationPatternConverter>(true);
}
- static WideLife<PatternConverterPtr> converter =
std::make_shared<ThrowableInformationPatternConverter>(false);
- return converter;
+ return std::make_shared<ThrowableInformationPatternConverter>(false);
}
void ThrowableInformationPatternConverter::format(
diff --git a/src/main/include/log4cxx/pattern/patternconverter.h
b/src/main/include/log4cxx/pattern/patternconverter.h
index 9bcf8c84..8e4852e5 100644
--- a/src/main/include/log4cxx/pattern/patternconverter.h
+++ b/src/main/include/log4cxx/pattern/patternconverter.h
@@ -21,6 +21,7 @@
#include <log4cxx/helpers/object.h>
#include <log4cxx/logstring.h>
+#include <log4cxx/pattern/formattinginfo.h>
#include <vector>
#define DECLARE_LOG4CXX_PATTERN(cls) DECLARE_ABSTRACT_LOG4CXX_OBJECT(cls)
@@ -95,6 +96,16 @@ class LOG4CXX_EXPORT PatternConverter : public virtual
helpers::Object
*/
virtual LogString getStyleClass(const helpers::ObjectPtr& e)
const;
+ /**
+ * Provides a minimum width, a maximum width and the alignment
+ */
+ const FormattingInfo& getFormattingInfo() const;
+
+ /**
+ * Use \c newValue for the minimum width, a maximum width and the
alignment
+ */
+ void setFormattingInfo(const FormattingInfoPtr& newValue);
+
protected:
/**
* Appends content in the locale code page to a LogString.
diff --git a/src/main/include/log4cxx/pattern/patternparser.h
b/src/main/include/log4cxx/pattern/patternparser.h
index 0cc6ba6e..5b2f39cc 100644
--- a/src/main/include/log4cxx/pattern/patternparser.h
+++ b/src/main/include/log4cxx/pattern/patternparser.h
@@ -33,7 +33,7 @@ namespace pattern
typedef std::function<PatternConverterPtr(const std::vector<LogString>&
options)> PatternConstructor;
typedef std::map<LogString, PatternConstructor> PatternMap;
-
+LOG4CXX_LIST_DEF(PatternConverterList, PatternConverterPtr);
// Contributors: Nelson Minar <([email protected]>
// Igor E. Poteryaev <[email protected]>
@@ -100,18 +100,31 @@ class LOG4CXX_EXPORT PatternParser
std::vector<LogString>& options);
public:
+#if LOG4CXX_ABI_VERSION <= 15
/**
* Parse a format specifier.
+ * @deprecated This function is deprecated and will be removed
in a future version.
* @param pattern pattern to parse.
* @param patternConverters list to receive pattern converters.
* @param formattingInfos list to receive field specifiers
corresponding to pattern converters.
* @param rules map of stock pattern converters keyed by format
specifier.
*/
+ [[ deprecated( "Parsing into two vectors is longer supported" )
]]
static void parse(
const LogString& pattern,
std::vector<PatternConverterPtr>& patternConverters,
std::vector<FormattingInfoPtr>& formattingInfos,
const PatternMap& rules);
+#endif
+ /**
+ * Convert \c pattern to converters using \c rules.
+ * @param pattern a string specifying the conversion types and
their properties.
+ * @param rules a map of stock pattern converters keyed by name.
+ */
+ static PatternConverterList parse
+ ( const LogString& pattern
+ , const PatternMap& rules
+ );
private:
/**
@@ -148,8 +161,8 @@ class LOG4CXX_EXPORT PatternParser
logchar c, const LogString& pattern, size_t i,
LogString& currentLiteral, const FormattingInfoPtr&
formattingInfo,
const PatternMap& rules,
- std::vector<PatternConverterPtr>& patternConverters,
- std::vector<FormattingInfoPtr>& formattingInfos);
+ PatternConverterList& patternConverter
+ );
static bool isUnicodeIdentifierStart(logchar c);
static bool isUnicodeIdentifierPart(logchar c);
diff --git a/src/main/include/log4cxx/private/patternconverter_priv.h
b/src/main/include/log4cxx/private/patternconverter_priv.h
index 0027ad5a..9e7b8aeb 100644
--- a/src/main/include/log4cxx/private/patternconverter_priv.h
+++ b/src/main/include/log4cxx/private/patternconverter_priv.h
@@ -17,6 +17,7 @@
#ifndef LOG4CXX_PATTERNCONVERTER_PRIVATE_H
#define LOG4CXX_PATTERNCONVERTER_PRIVATE_H
#include <log4cxx/pattern/patternconverter.h>
+#include <log4cxx/pattern/formattinginfo.h>
namespace LOG4CXX_NS
{
@@ -44,6 +45,11 @@ struct PatternConverter::PatternConverterPrivate
* Converter style name.
*/
const LogString style;
+
+ /**
+ * Provides field size limits
+ */
+ FormattingInfoPtr info{ FormattingInfo::getDefault() };
};
}
diff --git a/src/main/include/log4cxx/private/rollingpolicybase_priv.h
b/src/main/include/log4cxx/private/rollingpolicybase_priv.h
index 829bb036..467fa448 100644
--- a/src/main/include/log4cxx/private/rollingpolicybase_priv.h
+++ b/src/main/include/log4cxx/private/rollingpolicybase_priv.h
@@ -35,11 +35,6 @@ struct RollingPolicyBase::RollingPolicyBasePrivate {
*/
PatternConverterList patternConverters;
- /**
- * File name field specifiers.
- */
- FormattingInfoList patternFields;
-
/**
* File name pattern.
*/
diff --git a/src/main/include/log4cxx/rolling/rollingpolicybase.h
b/src/main/include/log4cxx/rolling/rollingpolicybase.h
index 9399286f..e2f85534 100644
--- a/src/main/include/log4cxx/rolling/rollingpolicybase.h
+++ b/src/main/include/log4cxx/rolling/rollingpolicybase.h
@@ -31,7 +31,6 @@ namespace LOG4CXX_NS
namespace rolling
{
LOG4CXX_LIST_DEF(PatternConverterList,
LOG4CXX_NS::pattern::PatternConverterPtr);
-LOG4CXX_LIST_DEF(FormattingInfoList, LOG4CXX_NS::pattern::FormattingInfoPtr);
/**
* Implements methods common to most, it not all, rolling
diff --git a/src/test/cpp/mdctestcase.cpp b/src/test/cpp/mdctestcase.cpp
index 06f4f3ac..c17082bf 100644
--- a/src/test/cpp/mdctestcase.cpp
+++ b/src/test/cpp/mdctestcase.cpp
@@ -19,7 +19,7 @@
#include <log4cxx/mdc.h>
#include <log4cxx/file.h>
#include <log4cxx/logger.h>
-#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/patternlayout.h>
#include "insertwide.h"
#include "logunit.h"
#include "util/compare.h"
@@ -32,6 +32,7 @@ LOGUNIT_CLASS(MDCTestCase)
{
LOGUNIT_TEST_SUITE(MDCTestCase);
LOGUNIT_TEST(test1);
+ LOGUNIT_TEST(test2);
LOGUNIT_TEST_SUITE_END();
public:
@@ -57,11 +58,23 @@ public:
{
std::string key("key1");
std::string expected("value2");
- MDC::put(key, "value1");
+ MDC item1(key, "value1");
MDC::put(key, expected);
std::string actual(MDC::get(key));
LOGUNIT_ASSERT_EQUAL(expected, actual);
}
+
+ /// Check MDC formatting skips entries that exceed the maximum field
length.
+ void test2()
+ {
+ MDC item1("key1", "value1");
+ MDC item2("key2", "value2");
+ helpers::Pool p;
+ LogString output;
+ PatternLayout l{ LOG4CXX_STR("%-5p %c - %.30J %m") };
+ l.format(output,
std::make_shared<spi::LoggingEvent>(LOG4CXX_STR("MDC.LayoutTest"),
Level::getInfo(), LOG4CXX_STR("Message"),
spi::LocationInfo::getLocationUnavailable()), p);
+ LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR("INFO MDC.LayoutTest -
{\"key1\":\"value1\"} Message"), output);
+ }
};
LOGUNIT_TEST_SUITE_REGISTRATION(MDCTestCase);
diff --git a/src/test/cpp/ndctestcase.cpp b/src/test/cpp/ndctestcase.cpp
index 383f7a71..0d3112c8 100644
--- a/src/test/cpp/ndctestcase.cpp
+++ b/src/test/cpp/ndctestcase.cpp
@@ -20,6 +20,7 @@
#include <log4cxx/file.h>
#include <log4cxx/logger.h>
#include <log4cxx/propertyconfigurator.h>
+#include <log4cxx/patternlayout.h>
#include "insertwide.h"
#include "logunit.h"
#include "util/compare.h"
@@ -37,6 +38,7 @@ LOGUNIT_CLASS(NDCTestCase)
LOGUNIT_TEST(testPushPop);
LOGUNIT_TEST(test1);
LOGUNIT_TEST(testInherit);
+ LOGUNIT_TEST(testFieldPrecision);
LOGUNIT_TEST_SUITE_END();
public:
@@ -113,6 +115,19 @@ public:
LOGUNIT_ASSERT_EQUAL(expected3, NDC::pop());
}
+ /// Check NDC formatting uses to suffix when the maximum field length
is exceeded.
+ void testFieldPrecision()
+ {
+ NDC item1("context1");
+ NDC item2("context2");
+ NDC item3("context3");
+ helpers::Pool p;
+ LogString output;
+ PatternLayout l{ LOG4CXX_STR("%-5p %c - %.20x %m") };
+ l.format(output,
std::make_shared<spi::LoggingEvent>(LOG4CXX_STR("NDC.LayoutTest"),
Level::getInfo(), LOG4CXX_STR("Message"),
spi::LocationInfo::getLocationUnavailable()), p);
+ LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR("INFO NDC.LayoutTest - t1
context2 context3 Message"), output);
+ }
+
};
diff --git a/src/test/cpp/pattern/patternparsertestcase.cpp
b/src/test/cpp/pattern/patternparsertestcase.cpp
index 4a4d88c7..2c030198 100644
--- a/src/test/cpp/pattern/patternparsertestcase.cpp
+++ b/src/test/cpp/pattern/patternparsertestcase.cpp
@@ -170,20 +170,15 @@ public:
const PatternMap & patternMap,
const LogString & expected)
{
- std::vector<PatternConverterPtr> converters;
- std::vector<FormattingInfoPtr> fields;
- PatternParser::parse(pattern, converters, fields, patternMap);
+ auto converters = PatternParser::parse(pattern, patternMap);
Pool p;
LogString actual;
- std::vector<FormattingInfoPtr>::const_iterator fieldIter =
fields.begin();
- for (std::vector<PatternConverterPtr>::const_iterator
converterIter = converters.begin();
- converterIter != converters.end();
- converterIter++, fieldIter++)
+ for (auto item : converters)
{
auto fieldStart = static_cast<int>(actual.length());
- (*converterIter)->format(event, actual, p);
- (*fieldIter)->format(fieldStart, actual);
+ item->format(event, actual, p);
+ item->getFormattingInfo().format(fieldStart, actual);
}
LOGUNIT_ASSERT_EQUAL(expected, actual);
diff --git a/src/test/cpp/patternlayouttest.cpp
b/src/test/cpp/patternlayouttest.cpp
index c142ae04..6301519f 100644
--- a/src/test/cpp/patternlayouttest.cpp
+++ b/src/test/cpp/patternlayouttest.cpp
@@ -63,6 +63,7 @@ using namespace log4cxx::helpers;
LOGUNIT_CLASS(PatternLayoutTest)
{
LOGUNIT_TEST_SUITE(PatternLayoutTest);
+ LOGUNIT_TEST(test2GbMessageFormatting);
LOGUNIT_TEST(test1);
LOGUNIT_TEST(test2);
LOGUNIT_TEST(test3);
@@ -103,6 +104,22 @@ public:
}
}
+ void test2GbMessageFormatting()
+ {
+ LogString msg(size_t(INT_MAX) + 1000, 'E');
+ msg[msg.length() - 1] = 'X';
+ Pool p;
+ LogString output1;
+ PatternLayout l1{ LOG4CXX_STR("%-5p %c{2} - %.30m") };
+ l1.format(output1,
std::make_shared<spi::LoggingEvent>(logger->getName(), Level::getInfo(), msg,
spi::LocationInfo::getLocationUnavailable()), p);
+ LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR("INFO log4j.PatternLayoutTest
- EEEEEEEEEEEEEEEEEEEEEEEEEEEEEX"), output1);
+
+ PatternLayout l2{ LOG4CXX_STR("%p %.30m %p") };
+ LogString output2;
+ l2.format(output2,
std::make_shared<spi::LoggingEvent>(logger->getName(), Level::getDebug(), msg,
spi::LocationInfo::getLocationUnavailable()), p);
+ LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR("DEBUG
EEEEEEEEEEEEEEEEEEEEEEEEEEEEEX DEBUG"), output2);
+ }
+
void test1()
{
auto status =
PropertyConfigurator::configure(LOG4CXX_FILE("input/patternLayout1.properties"));
diff --git a/src/test/cpp/rolling/filenamepatterntestcase.cpp
b/src/test/cpp/rolling/filenamepatterntestcase.cpp
index eb29cbba..01a834fa 100644
--- a/src/test/cpp/rolling/filenamepatterntestcase.cpp
+++ b/src/test/cpp/rolling/filenamepatterntestcase.cpp
@@ -66,23 +66,18 @@ public:
LogString format(const LogString & pattern,
const ObjectPtr & obj)
{
- std::vector<PatternConverterPtr> converters;
- std::vector<FormattingInfoPtr> fields;
PatternMap rules;
rules.insert(PatternMap::value_type(LOG4CXX_STR("d"),
(PatternConstructor) FileDatePatternConverter::newInstance));
rules.insert(PatternMap::value_type(LOG4CXX_STR("i"),
(PatternConstructor) IntegerPatternConverter::newInstance));
- PatternParser::parse(pattern, converters, fields, rules);
+ auto converters = PatternParser::parse(pattern, rules);
LogString result;
Pool pool;
- std::vector<FormattingInfoPtr>::const_iterator fieldIter =
fields.begin();
- for (std::vector<PatternConverterPtr>::const_iterator
converterIter = converters.begin();
- converterIter != converters.end();
- converterIter++, fieldIter++)
+ for (auto item : converters)
{
LogString::size_type i = result.length();
- (*converterIter)->format(obj, result, pool);
- (*fieldIter)->format(i, result);
+ item->format(obj, result, pool);
+ item->getFormattingInfo().format((int)i, result);
}
return result;