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 050c4cff Require the SQL used by ODBCAppender to be a single statement
(#564)
050c4cff is described below
commit 050c4cff6cfcdfecce09cee4d2b88de2ec41fdf8
Author: Stephen Webb <[email protected]>
AuthorDate: Tue Nov 25 11:10:19 2025 +1100
Require the SQL used by ODBCAppender to be a single statement (#564)
* Add web-site nudge to protect the configuration file
---
src/main/cpp/odbcappender.cpp | 24 ++++++++++++++++++++++++
src/main/include/log4cxx/db/odbcappender.h | 3 ++-
src/site/markdown/configuration-samples.md | 5 +++++
src/test/cpp/db/odbcappendertestcase.cpp | 9 ++++++---
4 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/src/main/cpp/odbcappender.cpp b/src/main/cpp/odbcappender.cpp
index 20ca4d55..24a2c528 100644
--- a/src/main/cpp/odbcappender.cpp
+++ b/src/main/cpp/odbcappender.cpp
@@ -267,6 +267,7 @@ void ODBCAppender::append(const spi::LoggingEventPtr&
event, LOG4CXX_NS::helpers
#endif
}
+#if LOG4CXX_ABI_VERSION <= 15
LogString ODBCAppender::getLogStatement(const spi::LoggingEventPtr& event,
LOG4CXX_NS::helpers::Pool& p) const
{
return LogString();
@@ -275,6 +276,7 @@ LogString ODBCAppender::getLogStatement(const
spi::LoggingEventPtr& event, LOG4C
void ODBCAppender::execute(const LogString& sql, LOG4CXX_NS::helpers::Pool& p)
{
}
+#endif
/* The default behavior holds a single connection open until the appender
is closed (typically when garbage collected).*/
@@ -613,6 +615,28 @@ void ODBCAppender::flushBuffer(Pool& p)
void ODBCAppender::setSql(const LogString& s)
{
+ const logchar doubleQuote{ 0x22 };
+ const logchar singleQuote{ 0x27 };
+ const logchar semiColan{ 0x3b };
+ // A basic check which disallows multiple SQL statements - for
defense-in-depth security.
+ // Allow a semicolan in a quoted context or as the last character.
+ logchar currentQuote{ 0 };
+ int charCount{ 0 };
+ for (auto ch : s)
+ {
+ ++charCount;
+ if (currentQuote == ch)
+ currentQuote = 0;
+ else if (currentQuote == 0)
+ {
+ if (doubleQuote == ch || singleQuote == ch)
+ currentQuote = ch;
+ else if (semiColan == ch && s.size() != charCount)
+ throw IllegalArgumentException(LOG4CXX_STR("SQL
statement cannot contain a ';'"));
+ }
+ }
+ if (0 != currentQuote)
+ throw IllegalArgumentException(LogString(LOG4CXX_STR("Unmatched
")) + currentQuote + LOG4CXX_STR(" in SQL statement"));
_priv->sqlStatement = s;
}
diff --git a/src/main/include/log4cxx/db/odbcappender.h
b/src/main/include/log4cxx/db/odbcappender.h
index 8aa496e4..5a58cb3c 100644
--- a/src/main/include/log4cxx/db/odbcappender.h
+++ b/src/main/include/log4cxx/db/odbcappender.h
@@ -187,6 +187,7 @@ class LOG4CXX_EXPORT ODBCAppender : public AppenderSkeleton
void append(const spi::LoggingEventPtr& event, helpers::Pool&)
override;
protected:
+#if LOG4CXX_ABI_VERSION <= 15
/**
* To be removed.
*/
@@ -199,7 +200,7 @@ class LOG4CXX_EXPORT ODBCAppender : public AppenderSkeleton
* */
virtual void execute(const LogString& sql,
LOG4CXX_NS::helpers::Pool& p) /*throw(SQLException)*/;
-
+#endif
/**
* Override this to return the connection to a pool, or to clean
up the
* resource.
diff --git a/src/site/markdown/configuration-samples.md
b/src/site/markdown/configuration-samples.md
index 30cbbaca..48741276 100644
--- a/src/site/markdown/configuration-samples.md
+++ b/src/site/markdown/configuration-samples.md
@@ -27,6 +27,11 @@ specify the instantiated appender/layout/filter classes and
the properties of those class instances
without recompiling and rebuilding.
+The configuration file must be protected from modification by untrusted
parties.
+Use restrictive file system permissions to ensure
+untrusted parties do not have write access.
+Do not load the configuration file from an untrusted location.
+
As Log4cxx was designed to be extendable,
property names and values are not constrained by the core library.
The configuration file parsers,
diff --git a/src/test/cpp/db/odbcappendertestcase.cpp
b/src/test/cpp/db/odbcappendertestcase.cpp
index 2e7dec99..42483aea 100644
--- a/src/test/cpp/db/odbcappendertestcase.cpp
+++ b/src/test/cpp/db/odbcappendertestcase.cpp
@@ -39,7 +39,10 @@ class ODBCAppenderTestCase : public AppenderSkeletonTestCase
//
LOGUNIT_TEST(testDefaultThreshold);
LOGUNIT_TEST(testSetOptionThreshold);
- //LOGUNIT_TEST(testConnectUsingDSN);
+//#define DataSourceName_Log4cxxTest_Is_Valid
+#ifdef DataSourceName_Log4cxxTest_Is_Valid
+ LOGUNIT_TEST(testConnectUsingDSN);
+#endif
LOGUNIT_TEST_SUITE_END();
@@ -72,7 +75,7 @@ class ODBCAppenderTestCase : public AppenderSkeletonTestCase
//
// CREATE TABLE [dbo].[UnitTestLog](
// [Item] [bigint] IDENTITY(1,1) NOT NULL, /* auto incremented */
-// [Thread] [nchar](20) NULL
+// [Thread] [nchar](20) NULL,
// [LogTime] [datetime] NOT NULL,
// [LogName] [nchar](50) NULL,
// [LogLevel] [nchar](10) NULL,
@@ -90,7 +93,7 @@ class ODBCAppenderTestCase : public AppenderSkeletonTestCase
for (int i = 0; i < 100; ++i)
{
LOG4CXX_INFO(odbc, "Message '" << i << "'");
- apr_sleep(30000);
+ apr_sleep(30000); // 30 milliseconds
}
LOG4CXX_INFO(odbc, "Last message");
}