From 6a295c7c49ef5f9fcd8fed4c1c9c8feff92bc87c Mon Sep 17 00:00:00 2001 From: OxBat Date: Tue, 27 Jan 2026 18:34:55 +0100 Subject: [PATCH 1/5] Fix integer overflow in OptionConverter (enable 64-bit sizes on Windows) Changed toFileSize signature to return 'long long' instead of 'long'. On Windows (LLP64), 'long' is 32-bit, causing overflow for sizes >= 2GB. Using 'long long' guarantees 64-bit width, preventing negative file sizes and enabling support for large log files. --- src/main/cpp/optionconverter.cpp | 31 +++++++++++-------- .../include/log4cxx/helpers/optionconverter.h | 3 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/main/cpp/optionconverter.cpp b/src/main/cpp/optionconverter.cpp index 17fc221db..b9c0a0a4e 100644 --- a/src/main/cpp/optionconverter.cpp +++ b/src/main/cpp/optionconverter.cpp @@ -279,7 +279,8 @@ int OptionConverter::toInt(const LogString& value, int dEfault) return (int) atol(cvalue.c_str()); } -long OptionConverter::toFileSize(const LogString& s, long dEfault) +// Update implementation to use long long and StringHelper::toInt64 +long long OptionConverter::toFileSize(const LogString& s, long long dEfault) { if (s.empty()) { @@ -287,29 +288,33 @@ long OptionConverter::toFileSize(const LogString& s, long dEfault) } size_t index = s.find_first_of(LOG4CXX_STR("bB")); - if (index != LogString::npos && index > 0) { - long multiplier = 1; - index--; - - if (s[index] == 0x6B /* 'k' */ || s[index] == 0x4B /* 'K' */) + long long multiplier = 1; + size_t unitIndex = index - 1; + + // Use 1024LL to force 64-bit arithmetic + if (s[unitIndex] == 'k' || s[unitIndex] == 'K') + { + multiplier = 1024LL; + } + else if (s[unitIndex] == 'm' || s[unitIndex] == 'M') { - multiplier = 1024; + multiplier = 1024LL * 1024LL; } - else if (s[index] == 0x6D /* 'm' */ || s[index] == 0x4D /* 'M' */) + else if (s[unitIndex] == 'g' || s[unitIndex] == 'G') { - multiplier = 1024 * 1024; + multiplier = 1024LL * 1024LL * 1024LL; } - else if (s[index] == 0x67 /* 'g'*/ || s[index] == 0x47 /* 'G' */) + else if (s[unitIndex] == 't' || s[unitIndex] == 'T') { - multiplier = 1024 * 1024 * 1024; + multiplier = 1024LL * 1024LL * 1024LL * 1024LL; } - return toInt(s.substr(0, index), 1) * multiplier; + return StringHelper::toInt64(s.substr(0, unitIndex)) * multiplier; } - return toInt(s, 1); + return StringHelper::toInt64(s); } LogString OptionConverter::findAndSubst(const LogString& key, Properties& props) diff --git a/src/main/include/log4cxx/helpers/optionconverter.h b/src/main/include/log4cxx/helpers/optionconverter.h index 009988d2f..bc6f4cf2a 100644 --- a/src/main/include/log4cxx/helpers/optionconverter.h +++ b/src/main/include/log4cxx/helpers/optionconverter.h @@ -72,7 +72,8 @@ class LOG4CXX_EXPORT OptionConverter converts the provided number respectively to kilobytes, megabytes and gigabytes. For example, the value "10KB" will be interpreted as 10240. */ - static long toFileSize(const LogString& value, long defaultValue); + // Use long long to ensure 64-bit capacity on Windows (LLP64) and Linux (LP64) + static long long toFileSize(const LogString& value, long long defaultValue); /** The Level indicated by \c value if recognised otherwise \c defaultValue. From 4373708482128e558efb3956a11982a3014070f5 Mon Sep 17 00:00:00 2001 From: OxBat Date: Tue, 27 Jan 2026 22:07:29 +0100 Subject: [PATCH 2/5] Fix ABI breakage in OptionConverter Restored original 'long toFileSize' signature to preserve binary compatibility. Added new 'toFileSize64' method for 64-bit support. Old method now wraps the new one with safety clamping to prevent overflow. --- src/main/cpp/optionconverter.cpp | 19 +++++++++++++++---- .../include/log4cxx/helpers/optionconverter.h | 12 ++++++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/main/cpp/optionconverter.cpp b/src/main/cpp/optionconverter.cpp index b9c0a0a4e..e997447ed 100644 --- a/src/main/cpp/optionconverter.cpp +++ b/src/main/cpp/optionconverter.cpp @@ -43,6 +43,7 @@ #include #include #include +#include namespace { @@ -279,8 +280,18 @@ int OptionConverter::toInt(const LogString& value, int dEfault) return (int) atol(cvalue.c_str()); } -// Update implementation to use long long and StringHelper::toInt64 -long long OptionConverter::toFileSize(const LogString& s, long long dEfault) +long OptionConverter::toFileSize(const LogString& s, long dEfault) +{ + long long val = toFileSize64(s, dEfault); + + if (val > std::numeric_limits::max()) { + return std::numeric_limits::max(); + } + + return (long) val; +} + +long long OptionConverter::toFileSize64(const LogString& s, long long dEfault) { if (s.empty()) { @@ -288,12 +299,12 @@ long long OptionConverter::toFileSize(const LogString& s, long long dEfault) } size_t index = s.find_first_of(LOG4CXX_STR("bB")); + if (index != LogString::npos && index > 0) { long long multiplier = 1; size_t unitIndex = index - 1; - - // Use 1024LL to force 64-bit arithmetic + if (s[unitIndex] == 'k' || s[unitIndex] == 'K') { multiplier = 1024LL; diff --git a/src/main/include/log4cxx/helpers/optionconverter.h b/src/main/include/log4cxx/helpers/optionconverter.h index bc6f4cf2a..e9967c70d 100644 --- a/src/main/include/log4cxx/helpers/optionconverter.h +++ b/src/main/include/log4cxx/helpers/optionconverter.h @@ -72,8 +72,16 @@ class LOG4CXX_EXPORT OptionConverter converts the provided number respectively to kilobytes, megabytes and gigabytes. For example, the value "10KB" will be interpreted as 10240. */ - // Use long long to ensure 64-bit capacity on Windows (LLP64) and Linux (LP64) - static long long toFileSize(const LogString& value, long long defaultValue); + /** + * @deprecated Use toFileSize64 instead. + */ + static long toFileSize(const LogString& value, long defaultValue); + + /** + * The numeric equivalent of \c value if it is not empty, otherwise \c defaultValue. + * Supports 64-bit values for file sizes > 2GB. + */ + static long long toFileSize64(const LogString& value, long long defaultValue); /** The Level indicated by \c value if recognised otherwise \c defaultValue. From 8009ff8b793c099d0af87c801988a8cc7c71f8d7 Mon Sep 17 00:00:00 2001 From: OxBat <80096477+OxBat@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:12:27 +0100 Subject: [PATCH 3/5] Update to use standard C++ [[deprecated]] attribute --- src/main/include/log4cxx/helpers/optionconverter.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/include/log4cxx/helpers/optionconverter.h b/src/main/include/log4cxx/helpers/optionconverter.h index e9967c70d..cb5e2eaba 100644 --- a/src/main/include/log4cxx/helpers/optionconverter.h +++ b/src/main/include/log4cxx/helpers/optionconverter.h @@ -72,9 +72,7 @@ class LOG4CXX_EXPORT OptionConverter converts the provided number respectively to kilobytes, megabytes and gigabytes. For example, the value "10KB" will be interpreted as 10240. */ - /** - * @deprecated Use toFileSize64 instead. - */ + [[deprecated("Use toFileSize64 instead")]] static long toFileSize(const LogString& value, long defaultValue); /** From ac875d08fa4153a20da75491cead981198bb9b4a Mon Sep 17 00:00:00 2001 From: OxBat <80096477+OxBat@users.noreply.github.com> Date: Mon, 2 Feb 2026 11:58:05 +0100 Subject: [PATCH 4/5] Switch to int64_t for explicit 64-bit size Updated header to use int64_t instead of long long as requested during review. --- src/main/include/log4cxx/helpers/optionconverter.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/include/log4cxx/helpers/optionconverter.h b/src/main/include/log4cxx/helpers/optionconverter.h index cb5e2eaba..5ac180445 100644 --- a/src/main/include/log4cxx/helpers/optionconverter.h +++ b/src/main/include/log4cxx/helpers/optionconverter.h @@ -20,6 +20,7 @@ #include #include +#include namespace LOG4CXX_NS { @@ -79,7 +80,7 @@ class LOG4CXX_EXPORT OptionConverter * The numeric equivalent of \c value if it is not empty, otherwise \c defaultValue. * Supports 64-bit values for file sizes > 2GB. */ - static long long toFileSize64(const LogString& value, long long defaultValue); + static int64_t toFileSize64(const LogString& value, int64_t defaultValue); /** The Level indicated by \c value if recognised otherwise \c defaultValue. From 3c0520ccbbc8ba8179a1e7ab618ddaa564ad0a41 Mon Sep 17 00:00:00 2001 From: OxBat <80096477+OxBat@users.noreply.github.com> Date: Mon, 2 Feb 2026 12:03:16 +0100 Subject: [PATCH 5/5] Update implementation to use int64_t Replaces long long with int64_t to match the header change and ensure explicit sizing --- src/main/cpp/optionconverter.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/cpp/optionconverter.cpp b/src/main/cpp/optionconverter.cpp index e997447ed..028e3fca3 100644 --- a/src/main/cpp/optionconverter.cpp +++ b/src/main/cpp/optionconverter.cpp @@ -6,7 +6,7 @@ * (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 + * 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, @@ -44,6 +44,7 @@ #include #include #include +#include namespace { @@ -282,7 +283,7 @@ int OptionConverter::toInt(const LogString& value, int dEfault) long OptionConverter::toFileSize(const LogString& s, long dEfault) { - long long val = toFileSize64(s, dEfault); + int64_t val = toFileSize64(s, dEfault); if (val > std::numeric_limits::max()) { return std::numeric_limits::max(); @@ -291,7 +292,7 @@ long OptionConverter::toFileSize(const LogString& s, long dEfault) return (long) val; } -long long OptionConverter::toFileSize64(const LogString& s, long long dEfault) +int64_t OptionConverter::toFileSize64(const LogString& s, int64_t dEfault) { if (s.empty()) { @@ -302,7 +303,7 @@ long long OptionConverter::toFileSize64(const LogString& s, long long dEfault) if (index != LogString::npos && index > 0) { - long long multiplier = 1; + int64_t multiplier = 1; size_t unitIndex = index - 1; if (s[unitIndex] == 'k' || s[unitIndex] == 'K')