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");
                }

Reply via email to