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 86977806 Reduce overhead when formatting quoted values into a message 
(#742)
86977806 is described below

commit 86977806f21f631852089526cbb87eea169c82ca
Author: Stephen Webb <[email protected]>
AuthorDate: Thu Aug 27 11:25:53 2026 +1000

    Reduce overhead when formatting quoted values into a message (#742)
---
 src/main/cpp/mdcpatternconverter.cpp     | 19 +++++++++++++++----
 src/main/cpp/messagepatternconverter.cpp |  2 +-
 src/test/cpp/mdctestcase.cpp             | 11 +++++++++++
 3 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/src/main/cpp/mdcpatternconverter.cpp 
b/src/main/cpp/mdcpatternconverter.cpp
index c3386117..aafd4a3a 100644
--- a/src/main/cpp/mdcpatternconverter.cpp
+++ b/src/main/cpp/mdcpatternconverter.cpp
@@ -83,11 +83,22 @@ void MDCPatternConverter::format( 
LOG4CXX_FORMAT_EVENT_FORMAL_PARAMETERS ) const
        if (!m_priv->style.empty()) // In a quoted context?
        {
                auto quote = m_priv->style.front();
-               size_t endIndex;
-               while ((endIndex = toAppendTo.find(quote, startIndex)) != 
toAppendTo.npos)
+               if (toAppendTo.find(quote, startIndex) != toAppendTo.npos)
                {
-                       toAppendTo.insert(endIndex + 1, 1, quote);
-                       startIndex = endIndex + 2;
+                       // Duplicate each quote character in a single linear 
pass:
+                       // repeated single-character insert() shifts the tail 
of the
+                       // output buffer on every quote, which is quadratic in 
the
+                       // (attacker-controllable) MDC content length.
+                       LogString input = toAppendTo.substr(startIndex);
+                       toAppendTo.resize(startIndex);
+                       size_t endIndex, index = 0;
+                       while ((endIndex = input.find(quote, index)) != 
input.npos)
+                       {
+                               toAppendTo.append(input, index, endIndex - 
index + 1);
+                               toAppendTo += quote;
+                               index = endIndex + 1;
+                       }
+                       toAppendTo.append(input, index, LogString::npos);
                }
        }
 }
diff --git a/src/main/cpp/messagepatternconverter.cpp 
b/src/main/cpp/messagepatternconverter.cpp
index 8ee3b4b1..aae8f915 100644
--- a/src/main/cpp/messagepatternconverter.cpp
+++ b/src/main/cpp/messagepatternconverter.cpp
@@ -52,7 +52,7 @@ class QuotedMessagePatternConverter : public 
LoggingEventPatternConverter
                                toAppendTo += m_quote;
                                startIndex = endIndex + 1;
                        }
-                       toAppendTo.append(input.substr(startIndex));
+                       toAppendTo.append(input, startIndex, input.npos);
                }
 };
 }
diff --git a/src/test/cpp/mdctestcase.cpp b/src/test/cpp/mdctestcase.cpp
index ccefcd6a..afdc4049 100644
--- a/src/test/cpp/mdctestcase.cpp
+++ b/src/test/cpp/mdctestcase.cpp
@@ -36,6 +36,7 @@ LOGUNIT_CLASS(MDCTestCase)
        LOGUNIT_TEST(test1);
        LOGUNIT_TEST(test2);
        LOGUNIT_TEST(test3);
+       LOGUNIT_TEST(test4);
        LOGUNIT_TEST_SUITE_END();
 
 public:
@@ -91,6 +92,16 @@ public:
                converter.format(e, output);
                LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR(""), output);
        }
+
+       /// A quote character in MDC content must be doubled in a quoted 
context.
+       void test4()
+       {
+               MDC item1("key1", "it's");
+               LogString output;
+               PatternLayout l{ LOG4CXX_STR("%J{'}") };
+               l.format(output, 
std::make_shared<spi::LoggingEvent>(LOG4CXX_STR("MDC.LayoutTest"), 
Level::getInfo(), LOG4CXX_STR("Message"), 
spi::LocationInfo::getLocationUnavailable()));
+               LOGUNIT_ASSERT_EQUAL(LOG4CXX_STR("{\"key1\":\"it''s\"}"), 
output);
+       }
 };
 
 LOGUNIT_TEST_SUITE_REGISTRATION(MDCTestCase);

Reply via email to