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 85daf4e9 overflow in toFileSize causing incorrect log rotation limits 
(#646)
85daf4e9 is described below

commit 85daf4e9e24086dad15e25c30b5b83e1583ac776
Author: jmestwa-coder <[email protected]>
AuthorDate: Thu May 7 13:36:57 2026 +0530

    overflow in toFileSize causing incorrect log rotation limits (#646)
---
 src/main/cpp/optionconverter.cpp             | 44 +++++++++++++++++++++-------
 src/test/cpp/rollingfileappendertestcase.cpp | 12 ++++++++
 2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/src/main/cpp/optionconverter.cpp b/src/main/cpp/optionconverter.cpp
index 2b43060e..5935400a 100644
--- a/src/main/cpp/optionconverter.cpp
+++ b/src/main/cpp/optionconverter.cpp
@@ -25,6 +25,8 @@
 #include <log4cxx/helpers/stringhelper.h>
 #include <log4cxx/helpers/exception.h>
 #include <stdlib.h>
+#include <cerrno>
+#include <limits>
 #include <log4cxx/helpers/properties.h>
 #include <log4cxx/helpers/loglog.h>
 #include <log4cxx/level.h>
@@ -281,35 +283,57 @@ int OptionConverter::toInt(const LogString& value, int 
dEfault)
 
 long OptionConverter::toFileSize(const LogString& s, long dEfault)
 {
-       if (s.empty())
+       LogString trimmed(StringHelper::trim(s));
+       if (trimmed.empty())
        {
                return dEfault;
        }
 
-       size_t index = s.find_first_of(LOG4CXX_STR("bB"));
+       size_t index = trimmed.find_first_of(LOG4CXX_STR("bB"));
 
+       long long multiplier = 1;
+       LogString numericPart = trimmed;
        if (index != LogString::npos && index > 0)
        {
-               long multiplier = 1;
-               index--;
-
-               if (s[index] == 0x6B /* 'k' */ || s[index] == 0x4B /* 'K' */)
+               size_t suffixIndex = index - 1;
+               if (trimmed[suffixIndex] == 0x6B /* 'k' */ || 
trimmed[suffixIndex] == 0x4B /* 'K' */)
                {
                        multiplier = 1024;
                }
-               else if (s[index] == 0x6D /* 'm' */ || s[index] == 0x4D /* 'M' 
*/)
+               else if (trimmed[suffixIndex] == 0x6D /* 'm' */ || 
trimmed[suffixIndex] == 0x4D /* 'M' */)
                {
                        multiplier = 1024 * 1024;
                }
-               else if (s[index] == 0x67 /* 'g'*/ || s[index] == 0x47 /* 'G' 
*/)
+               else if (trimmed[suffixIndex] == 0x67 /* 'g'*/ || 
trimmed[suffixIndex] == 0x47 /* 'G' */)
                {
                        multiplier = 1024 * 1024 * 1024;
                }
 
-               return toInt(s.substr(0, index), 1) * multiplier;
+               numericPart = trimmed.substr(0, suffixIndex);
+       }
+
+       LOG4CXX_ENCODE_CHAR(cvalue, numericPart);
+       char* endptr;
+       errno = 0;
+       long long parsed = strtoll(cvalue.c_str(), &endptr, 10);
+
+       if (endptr == cvalue.c_str() || errno == ERANGE || parsed < 0)
+       {
+               return dEfault;
+       }
+
+       if (multiplier != 0 && parsed > std::numeric_limits<long long>::max() / 
multiplier)
+       {
+               return dEfault;
+       }
+
+       long long scaled = parsed * multiplier;
+       if (scaled > std::numeric_limits<long>::max())
+       {
+               return dEfault;
        }
 
-       return toInt(s, 1);
+       return static_cast<long>(scaled);
 }
 
 LogString OptionConverter::findAndSubst(const LogString& key, Properties& 
props)
diff --git a/src/test/cpp/rollingfileappendertestcase.cpp 
b/src/test/cpp/rollingfileappendertestcase.cpp
index f77f116b..f9c4d92b 100644
--- a/src/test/cpp/rollingfileappendertestcase.cpp
+++ b/src/test/cpp/rollingfileappendertestcase.cpp
@@ -32,11 +32,23 @@ class RollingFileAppenderTestCase : public 
FileAppenderAbstractTestCase
                //
                LOGUNIT_TEST(testDefaultThreshold);
                LOGUNIT_TEST(testSetOptionThreshold);
+               LOGUNIT_TEST(testMaxFileSizeOverflow);
 
                LOGUNIT_TEST_SUITE_END();
 
 
        public:
+               void testMaxFileSizeOverflow()
+               {
+                       log4cxx::rolling::RollingFileAppender rfa;
+                       // Set an extremely large value that would cause 
overflow in the buggy version
+                       rfa.setOption(LOG4CXX_STR("MaxFileSize"), 
LOG4CXX_STR("9999999999999999999999GB"));
+                       size_t currentMax = rfa.getMaximumFileSize();
+                       
+                       // In the buggy version, currentMax would be a huge 
positive value (size_t conversion of a negative long)
+                       // In the fixed version, it should return the default 
value or at least be reasonable.
+                       LOGUNIT_ASSERT(currentMax <= (size_t)2000000000ULL);
+               }
 
                FileAppender* createFileAppender() const
                {

Reply via email to