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 6f791f0d Prevent potential infinite loop in MbstowcsCharsetDecoder 
(#589)
6f791f0d is described below

commit 6f791f0dc49248cdbdbd9d22b978349ae36d3182
Author: OxBat <[email protected]>
AuthorDate: Tue Apr 7 02:32:46 2026 +0200

    Prevent potential infinite loop in MbstowcsCharsetDecoder (#589)
    
    * add unit test for mbsrtowcs infinite loop
---
 src/main/cpp/charsetdecoder.cpp                 | 11 +++++++++
 src/test/cpp/helpers/charsetdecodertestcase.cpp | 30 ++++++++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/main/cpp/charsetdecoder.cpp b/src/main/cpp/charsetdecoder.cpp
index ed79d440..7b364c08 100644
--- a/src/main/cpp/charsetdecoder.cpp
+++ b/src/main/cpp/charsetdecoder.cpp
@@ -208,6 +208,17 @@ class MbstowcsCharsetDecoder : public CharsetDecoder
                                        }
                                        else
                                        {
+                                               // FIX: Check for incomplete 
sequence infinite loop.
+                                               // If mbsrtowcs returns success 
(>=0) but converted 0 bytes while data remains,
+                                               // we are stuck (e.g. 
incomplete multibyte char at EOF).
+                                               if (converted == 0 && 
in.remaining() > 0)
+                                               {
+                                                       LogString 
msg(LOG4CXX_STR("Incomplete multibyte sequence at end of buffer"));
+                                                       LogLog::warn(msg);
+                                                       stat = APR_BADCH;
+                                                       break; // Break the 
infinite loop
+                                               }
+
                                                wbuf[wCharCount] = 0;
                                                stat = append(out, wbuf);
                                        }
diff --git a/src/test/cpp/helpers/charsetdecodertestcase.cpp 
b/src/test/cpp/helpers/charsetdecodertestcase.cpp
index 81497a7a..c99366fa 100644
--- a/src/test/cpp/helpers/charsetdecodertestcase.cpp
+++ b/src/test/cpp/helpers/charsetdecodertestcase.cpp
@@ -38,6 +38,9 @@ LOGUNIT_CLASS(CharsetDecoderTestCase)
        LOGUNIT_TEST(decode2);
        LOGUNIT_TEST(decode3);
        LOGUNIT_TEST(decode4);
+#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
+    LOGUNIT_TEST(testMbstowcsInfiniteLoop);
+#endif
        LOGUNIT_TEST_SUITE_END();
 
        enum { BUFSIZE = 256 };
@@ -147,7 +150,32 @@ public:
                }
        }
 
-
+#if LOG4CXX_LOGCHAR_IS_WCHAR && LOG4CXX_HAS_MBSRTOWCS
+    /**
+     * Tests that we don't loop infinitely when mbsrtowcs refuses to consume
+     * an incomplete multibyte sequence at the end of the buffer.
+     */
+    void testMbstowcsInfiniteLoop()
+    {
+        // 1. setup: buffer ending with a partial multibyte sequence.
+        // 0xC2 is a generic start byte for a 2-byte sequence in UTF-8.
+        char input[] = { 'A', (char)0xC2, 0 }; 
+        ByteBuffer in(input, 2);
+        LogString out;
+
+        // 2. execution:
+        // this decoder is the default on WCHAR builds.
+        CharsetDecoderPtr decoder = CharsetDecoder::getDefaultDecoder();
+        
+        // without fix: infinite loop.
+        // with fix: detects the stall and breaks/returns error.
+        decoder->decode(in, out);
+        
+        // 3. verify: We survived the call.
+        LOGUNIT_ASSERT(true);
+    }
+#endif
+       
 };
 
 LOGUNIT_TEST_SUITE_REGISTRATION(CharsetDecoderTestCase);

Reply via email to