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 fc675993 #643 Log complete messages with embedded nul characters in
console writers (#658)
fc675993 is described below
commit fc6759932937898121663542bdf63951cc45a36f
Author: Elliot <[email protected]>
AuthorDate: Mon May 18 22:32:16 2026 -0400
#643 Log complete messages with embedded nul characters in console writers
(#658)
---
src/main/cpp/CMakeLists.txt | 1 +
.../cpp/{systemerrwriter.cpp => consolewriter.cpp} | 68 +++++--------------
src/main/cpp/systemerrwriter.cpp | 45 ++-----------
src/main/cpp/systemoutwriter.cpp | 46 ++-----------
src/main/include/log4cxx/helpers/systemerrwriter.h | 1 -
src/main/include/log4cxx/helpers/systemoutwriter.h | 1 -
.../include/log4cxx/private/consolewriter_priv.h | 34 ++++++++++
src/test/cpp/helpers/CMakeLists.txt | 3 +-
src/test/cpp/helpers/consolewritertestcase.cpp | 77 ++++++++++++++++++++++
9 files changed, 137 insertions(+), 139 deletions(-)
diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index a672f9b0..92f04995 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -108,6 +108,7 @@ target_sources(log4cxx
colorendpatternconverter.cpp
configurator.cpp
consoleappender.cpp
+ consolewriter.cpp
cyclicbuffer.cpp
date.cpp
dateformat.cpp
diff --git a/src/main/cpp/systemerrwriter.cpp b/src/main/cpp/consolewriter.cpp
similarity index 55%
copy from src/main/cpp/systemerrwriter.cpp
copy to src/main/cpp/consolewriter.cpp
index 869c38d5..52118d90 100644
--- a/src/main/cpp/systemerrwriter.cpp
+++ b/src/main/cpp/consolewriter.cpp
@@ -15,82 +15,44 @@
* limitations under the License.
*/
-#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/systemerrwriter.h>
+#include <log4cxx/private/consolewriter_priv.h>
#include <log4cxx/helpers/transcoder.h>
-#include <stdio.h>
#if !defined(LOG4CXX)
#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>
using namespace LOG4CXX_NS;
-using namespace LOG4CXX_NS::helpers;
-IMPLEMENT_LOG4CXX_OBJECT(SystemErrWriter)
-
-SystemErrWriter::SystemErrWriter()
-{
-}
-
-SystemErrWriter::~SystemErrWriter()
-{
-}
-
-void SystemErrWriter::close( LOG4CXX_CLOSE_WRITER_FORMAL_PARAMETERS )
-{
-}
-
-void SystemErrWriter::flush( LOG4CXX_FLUSH_WRITER_FORMAL_PARAMETERS )
-{
- fflush(stderr);
-}
-
-void SystemErrWriter::write( LOG4CXX_WRITE_WRITER_FORMAL_PARAMETERS )
-{
-#if LOG4CXX_WCHAR_T_API
- if (isWide())
- {
- LOG4CXX_ENCODE_WCHAR(msg, str);
- fputws(msg.c_str(), stderr);
- return;
- }
-
-#endif
- LOG4CXX_ENCODE_CHAR(msg, str);
- fputs(msg.c_str(), stderr);
-}
-
-bool SystemErrWriter::isWide()
+static bool isConsoleWide(FILE *file)
{
#if LOG4CXX_FORCE_WIDE_CONSOLE
return true;
#elif LOG4CXX_FORCE_BYTE_CONSOLE || !LOG4CXX_HAS_FWIDE
return false;
#else
- return fwide(stderr, 0) > 0;
+ return fwide(file, 0) > 0;
#endif
}
-#if LOG4CXX_ABI_VERSION <= 15
-void SystemErrWriter::write(const LogString& str)
+size_t helpers::writeToConsole(const LogString& str, FILE *file)
{
#if LOG4CXX_WCHAR_T_API
-
- if (isWide())
+ if (isConsoleWide(file))
{
LOG4CXX_ENCODE_WCHAR(msg, str);
- fputws(msg.c_str(), stderr);
- return;
+ int status = fputws(msg.c_str(), file);
+ return status == EOF ? 0 : msg.size();
}
-
#endif
+
LOG4CXX_ENCODE_CHAR(msg, str);
- fputs(msg.c_str(), stderr);
-}
-void SystemErrWriter::flush()
-{
- fflush(stderr);
+ //
+ // We can't use fputs, fprintf, or even a `%.*s` specifier
+ // as the message may contain embedded null bytes, which would cause the
+ // message to be prematurely truncated.
+ //
+ msg.append("\n");
+ return fwrite(msg.data(), 1, msg.size(), file);
}
-#endif
\ No newline at end of file
diff --git a/src/main/cpp/systemerrwriter.cpp b/src/main/cpp/systemerrwriter.cpp
index 869c38d5..7ca4a21a 100644
--- a/src/main/cpp/systemerrwriter.cpp
+++ b/src/main/cpp/systemerrwriter.cpp
@@ -15,14 +15,9 @@
* limitations under the License.
*/
-#include <log4cxx/logstring.h>
#include <log4cxx/helpers/systemerrwriter.h>
-#include <log4cxx/helpers/transcoder.h>
#include <stdio.h>
-#if !defined(LOG4CXX)
- #define LOG4CXX 1
-#endif
-#include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/private/consolewriter_priv.h>
using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
@@ -48,49 +43,17 @@ void SystemErrWriter::flush(
LOG4CXX_FLUSH_WRITER_FORMAL_PARAMETERS )
void SystemErrWriter::write( LOG4CXX_WRITE_WRITER_FORMAL_PARAMETERS )
{
-#if LOG4CXX_WCHAR_T_API
- if (isWide())
- {
- LOG4CXX_ENCODE_WCHAR(msg, str);
- fputws(msg.c_str(), stderr);
- return;
- }
-
-#endif
- LOG4CXX_ENCODE_CHAR(msg, str);
- fputs(msg.c_str(), stderr);
-}
-
-bool SystemErrWriter::isWide()
-{
-#if LOG4CXX_FORCE_WIDE_CONSOLE
- return true;
-#elif LOG4CXX_FORCE_BYTE_CONSOLE || !LOG4CXX_HAS_FWIDE
- return false;
-#else
- return fwide(stderr, 0) > 0;
-#endif
+ helpers::writeToConsole(str, stderr);
}
#if LOG4CXX_ABI_VERSION <= 15
void SystemErrWriter::write(const LogString& str)
{
-#if LOG4CXX_WCHAR_T_API
-
- if (isWide())
- {
- LOG4CXX_ENCODE_WCHAR(msg, str);
- fputws(msg.c_str(), stderr);
- return;
- }
-
-#endif
- LOG4CXX_ENCODE_CHAR(msg, str);
- fputs(msg.c_str(), stderr);
+ helpers::writeToConsole(str, stderr);
}
void SystemErrWriter::flush()
{
fflush(stderr);
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/main/cpp/systemoutwriter.cpp b/src/main/cpp/systemoutwriter.cpp
index 343ea649..dea990b5 100644
--- a/src/main/cpp/systemoutwriter.cpp
+++ b/src/main/cpp/systemoutwriter.cpp
@@ -15,14 +15,8 @@
* limitations under the License.
*/
-#include <log4cxx/logstring.h>
#include <log4cxx/helpers/systemoutwriter.h>
-#include <log4cxx/helpers/transcoder.h>
-#include <stdio.h>
-#if !defined(LOG4CXX)
- #define LOG4CXX 1
-#endif
-#include <log4cxx/private/log4cxx_private.h>
+#include <log4cxx/private/consolewriter_priv.h>
using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
@@ -48,49 +42,17 @@ void SystemOutWriter::flush(
LOG4CXX_FLUSH_WRITER_FORMAL_PARAMETERS )
void SystemOutWriter::write( LOG4CXX_WRITE_WRITER_FORMAL_PARAMETERS )
{
-#if LOG4CXX_WCHAR_T_API
- if (isWide())
- {
- LOG4CXX_ENCODE_WCHAR(msg, str);
- fputws(msg.c_str(), stdout);
- return;
- }
-
-#endif
- LOG4CXX_ENCODE_CHAR(msg, str);
- fputs(msg.c_str(), stdout);
-}
-
-bool SystemOutWriter::isWide()
-{
-#if LOG4CXX_FORCE_WIDE_CONSOLE
- return true;
-#elif LOG4CXX_FORCE_BYTE_CONSOLE || !LOG4CXX_HAS_FWIDE
- return false;
-#else
- return fwide(stdout, 0) > 0;
-#endif
+ helpers::writeToConsole(str, stdout);
}
#if LOG4CXX_ABI_VERSION <= 15
void SystemOutWriter::write(const LogString& str)
{
-#if LOG4CXX_WCHAR_T_API
-
- if (isWide())
- {
- LOG4CXX_ENCODE_WCHAR(msg, str);
- fputws(msg.c_str(), stdout);
- return;
- }
-
-#endif
- LOG4CXX_ENCODE_CHAR(msg, str);
- fputs(msg.c_str(), stdout);
+ helpers::writeToConsole(str, stdout);
}
void SystemOutWriter::flush()
{
fflush(stdout);
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/main/include/log4cxx/helpers/systemerrwriter.h
b/src/main/include/log4cxx/helpers/systemerrwriter.h
index 33c702a9..1107ecb3 100644
--- a/src/main/include/log4cxx/helpers/systemerrwriter.h
+++ b/src/main/include/log4cxx/helpers/systemerrwriter.h
@@ -54,7 +54,6 @@ class LOG4CXX_EXPORT SystemErrWriter : public Writer
private:
SystemErrWriter(const SystemErrWriter&);
SystemErrWriter& operator=(const SystemErrWriter&);
- static bool isWide();
};
} // namespace helpers
diff --git a/src/main/include/log4cxx/helpers/systemoutwriter.h
b/src/main/include/log4cxx/helpers/systemoutwriter.h
index 00b81375..6e4f9e06 100644
--- a/src/main/include/log4cxx/helpers/systemoutwriter.h
+++ b/src/main/include/log4cxx/helpers/systemoutwriter.h
@@ -54,7 +54,6 @@ class LOG4CXX_EXPORT SystemOutWriter : public Writer
private:
SystemOutWriter(const SystemOutWriter&);
SystemOutWriter& operator=(const SystemOutWriter&);
- static bool isWide();
};
} // namespace helpers
diff --git a/src/main/include/log4cxx/private/consolewriter_priv.h
b/src/main/include/log4cxx/private/consolewriter_priv.h
new file mode 100644
index 00000000..89ca1244
--- /dev/null
+++ b/src/main/include/log4cxx/private/consolewriter_priv.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef LOG4CXX_CONSOLEWRITER_PRIVATE_H
+#define LOG4CXX_CONSOLEWRITER_PRIVATE_H
+
+#include <log4cxx/logstring.h>
+#include <stdio.h>
+
+namespace LOG4CXX_NS
+{
+namespace helpers
+{
+
+LOG4CXX_EXPORT size_t writeToConsole(const LogString& str, FILE *file);
+
+} // namespace helpers
+
+} // namespace log4cxx
+
+#endif /* LOG4CXX_CONSOLEWRITER_PRIVATE_H */
diff --git a/src/test/cpp/helpers/CMakeLists.txt
b/src/test/cpp/helpers/CMakeLists.txt
index fe07d973..97ce7454 100644
--- a/src/test/cpp/helpers/CMakeLists.txt
+++ b/src/test/cpp/helpers/CMakeLists.txt
@@ -15,12 +15,13 @@
# limitations under the License.
#
-set(HELPER_TESTS
+set(HELPER_TESTS
absolutetimedateformattestcase
cacheddateformattestcase
casttestcase
charsetdecodertestcase
charsetencodertestcase
+ consolewritertestcase
cyclicbuffertestcase
datetimedateformattestcase
filewatchdogtest
diff --git a/src/test/cpp/helpers/consolewritertestcase.cpp
b/src/test/cpp/helpers/consolewritertestcase.cpp
new file mode 100644
index 00000000..e44e23ff
--- /dev/null
+++ b/src/test/cpp/helpers/consolewritertestcase.cpp
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../logunit.h"
+
+#include <log4cxx/private/consolewriter_priv.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <apr_file_io.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+
+LOGUNIT_CLASS(ConsoleWriterTest)
+{
+ LOGUNIT_TEST_SUITE(ConsoleWriterTest);
+ LOGUNIT_TEST(testWriteEmbeddedNullCharacters);
+ LOGUNIT_TEST_SUITE_END();
+
+public:
+ /**
+ * Tests writing to an unknown host.
+ */
+ void testWriteEmbeddedNullCharacters()
+ {
+ Pool p;
+ const char* tmpdir = NULL;
+ apr_status_t stat = apr_temp_dir_get(&tmpdir, p.getAPRPool());
+ LOGUNIT_ASSERT_EQUAL(APR_SUCCESS, stat);
+
+ std::string path = tmpdir;
+ path += "/log4cxx.test.log";
+
+ remove(path.c_str());
+
+ std::string message{"Hello\0World!", 12};
+
+ {
+ FILE *fp = fopen(path.c_str(), "wb");
+ LOG4CXX_DECODE_CHAR(lsMessage, message);
+ size_t written = helpers::writeToConsole(lsMessage, fp);
+ LOGUNIT_ASSERT_EQUAL(message.size() + 1, written);
+ fclose(fp);
+ }
+
+ std::string content;
+
+ {
+ FILE *fp = fopen(path.c_str(), "rb");
+ content.resize(1024);
+ size_t count = fread((void*)content.data(), 1,
content.size(), fp);
+ content.resize(count);
+ fclose(fp);
+ }
+
+ LOGUNIT_ASSERT_EQUAL(content, message + "\n");
+ }
+
+};
+
+
+LOGUNIT_TEST_SUITE_REGISTRATION(ConsoleWriterTest);