This is an automated email from the ASF dual-hosted git repository.

rmiddleton 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 2cbae954 Fix possible invalid cast (#470)
2cbae954 is described below

commit 2cbae9546303bdfbbf05c7635a3079720b22fd96
Author: Robert Middleton <[email protected]>
AuthorDate: Sun Feb 2 10:26:35 2025 -0500

    Fix possible invalid cast (#470)
    
    If a user attempts to load a config file with an improper level set such
    that a non-level class is attempted to be used, throw an exception instead
    of accessing invalid memory.
---
 src/main/cpp/optionconverter.cpp                 | 15 +++++++++++++--
 src/test/cpp/xml/domtestcase.cpp                 |  8 ++++++++
 src/test/resources/input/xml/DOMInvalidLevel.xml | 11 +++++++++++
 3 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/main/cpp/optionconverter.cpp b/src/main/cpp/optionconverter.cpp
index 59343410..be7dee76 100644
--- a/src/main/cpp/optionconverter.cpp
+++ b/src/main/cpp/optionconverter.cpp
@@ -343,8 +343,13 @@ LevelPtr OptionConverter::toLevel(const LogString& value,
 
        try
        {
-               Level::LevelClass& levelClass =
-                       (Level::LevelClass&)Loader::loadClass(clazz);
+               // Note: the dynamic_cast could fail across DLL boundaries.
+               // However, without the dynamic_cast a poorly formed XML file
+               // could attempt to load an invalid class as a filter, causing
+               // a crash.  If it can't be converted, a std::bad_cast should be
+               // thrown(and caught by the exception handler below)
+               const Level::LevelClass& levelClass =
+                       dynamic_cast<const 
Level::LevelClass&>(Loader::loadClass(clazz));
                return levelClass.toLevel(levelName);
        }
        catch (ClassNotFoundException&)
@@ -358,6 +363,12 @@ LevelPtr OptionConverter::toLevel(const LogString& value,
                        LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("], level 
[") + levelName +
                        LOG4CXX_STR("] conversion) failed."), oops);
        }
+       catch(const std::bad_cast&)
+       {
+               LogLog::warn(
+                       LOG4CXX_STR("class [") + clazz + LOG4CXX_STR("] unable 
to be converted to "
+                       "Level::LevelClass"));
+       }
        catch (...)
        {
                LogLog::warn(
diff --git a/src/test/cpp/xml/domtestcase.cpp b/src/test/cpp/xml/domtestcase.cpp
index e254868b..29d83a48 100644
--- a/src/test/cpp/xml/domtestcase.cpp
+++ b/src/test/cpp/xml/domtestcase.cpp
@@ -53,6 +53,7 @@ LOGUNIT_CLASS(DOMTestCase)
 #endif
        LOGUNIT_TEST(test3);
        LOGUNIT_TEST(test4);
+       LOGUNIT_TEST(invalidLevel);
        LOGUNIT_TEST_SUITE_END();
 
        LoggerPtr root;
@@ -226,6 +227,13 @@ public:
                bool exists = file.exists(p);
                LOGUNIT_ASSERT(exists);
        }
+
+       void invalidLevel()
+       {
+               // Load an XML file that attempts to use a filter as a level.
+               // We should not crash when loading this file.
+               
DOMConfigurator::configure(LOG4CXX_TEST_STR("input/xml/DOMInvalidLevel.xml"));
+       }
 };
 
 LOGUNIT_TEST_SUITE_REGISTRATION(DOMTestCase);
diff --git a/src/test/resources/input/xml/DOMInvalidLevel.xml 
b/src/test/resources/input/xml/DOMInvalidLevel.xml
new file mode 100644
index 00000000..d5a1ca48
--- /dev/null
+++ b/src/test/resources/input/xml/DOMInvalidLevel.xml
@@ -0,0 +1,11 @@
+<log4j:configuration xmlns:log4j=' '>
+  <appender name="TEMP" class="FileAppender">
+    <filter class="LevelMatchFilter">
+      <param name="LevelToMatch" value=" #Filter"/>
+    </filter>
+  </appender>
+
+  <root>
+    <appender-ref ref="TEMP"/>
+  </root>
+</log4j:configuration>

Reply via email to