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 7831d5d1 UTF-8 recovery loop end-of-input handling (#695)
7831d5d1 is described below
commit 7831d5d196e0ccdc0e7437bb0fead37aba186e8f
Author: jmestwa-coder <[email protected]>
AuthorDate: Mon Jun 1 07:11:23 2026 +0530
UTF-8 recovery loop end-of-input handling (#695)
---
src/main/cpp/charsetencoder.cpp | 7 +++-
src/test/cpp/helpers/charsetencodertestcase.cpp | 45 +++++++++++++++++++++++++
2 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/src/main/cpp/charsetencoder.cpp b/src/main/cpp/charsetencoder.cpp
index f153008d..ce93dc9d 100644
--- a/src/main/cpp/charsetencoder.cpp
+++ b/src/main/cpp/charsetencoder.cpp
@@ -623,7 +623,12 @@ void CharsetEncoder::encode(CharsetEncoderPtr& enc,
#elif LOG4CXX_LOGCHAR_IS_UTF8
// advance past this character and all continuation characters
- while ((*(++iter) & 0xC0) == 0x80);
+ do
+ {
+ ++iter;
+ }
+ while (iter != src.end() &&
+ (*iter & 0xC0) == 0x80);
#else
#error logchar is unrecognized
diff --git a/src/test/cpp/helpers/charsetencodertestcase.cpp
b/src/test/cpp/helpers/charsetencodertestcase.cpp
index 0b86915a..8d1430e4 100644
--- a/src/test/cpp/helpers/charsetencodertestcase.cpp
+++ b/src/test/cpp/helpers/charsetencodertestcase.cpp
@@ -21,6 +21,11 @@
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/outputstream.h>
+#include <log4cxx/helpers/fileoutputstream.h>
+#include <log4cxx/helpers/fileinputstream.h>
+#include <log4cxx/file.h>
#include <apr.h>
#include <apr_errno.h>
#include <condition_variable>
@@ -38,6 +43,7 @@ LOGUNIT_CLASS(CharsetEncoderTestCase)
LOGUNIT_TEST(encode3);
LOGUNIT_TEST(encode4);
LOGUNIT_TEST(encode5);
+ LOGUNIT_TEST(utf8Recovery);
LOGUNIT_TEST(thread1);
LOGUNIT_TEST_SUITE_END();
@@ -235,6 +241,45 @@ public:
}
}
+ /**
+ * Regression test: write malformed UTF-8 through OutputStreamWriter
+ * using a non-trivial encoder and assert the replacement character
+ * is emitted (Transcoder::LOSSCHAR). This is deterministic and does
+ * not rely on process crash.
+ */
+ void utf8Recovery()
+ {
+ File(LOG4CXX_STR("output")).mkdirs();
+
+ // Use FileOutputStream + OutputStreamWriter with US-ASCII
encoder
+ OutputStreamPtr fos = FileOutputStreamPtr(
+ new
FileOutputStream(LOG4CXX_STR("output/utf8Recovery.txt")));
+ CharsetEncoderPtr
enc(CharsetEncoder::getEncoder(LOG4CXX_STR("US-ASCII")));
+ OutputStreamWriterPtr osw = OutputStreamWriterPtr(
+ new OutputStreamWriter(fos, enc));
+
+ // Minimal malformed UTF-8: a single lead byte 0xC2 with no
continuation
+ LogString s;
+ s.append(1, static_cast<logchar>(0xC2));
+
+ // Write and flush
+ osw->write(s);
+ osw->flush();
+ fos->close();
+
+ // Read back the raw byte and assert the encoder emitted
LOSSCHAR.
+ InputStreamPtr fis = FileInputStreamPtr(
+ new
FileInputStream(LOG4CXX_STR("output/utf8Recovery.txt")));
+ char raw[4] = { 0, 0, 0, 0 };
+ ByteBuffer buf(raw, sizeof(raw));
+ int read = fis->read(buf);
+
+ LOGUNIT_ASSERT_EQUAL(1, read);
+ LOGUNIT_ASSERT_EQUAL((size_t)1, buf.position());
+ LOGUNIT_ASSERT_EQUAL((unsigned char) Transcoder::LOSSCHAR,
+ (unsigned char) raw[0]);
+ }
+
class ThreadPackage
{
public: