[libc-commits] [libc] 784b74c - [libc] Fix off by one error in strftime (#165711)
via libc-commits
libc-commits at lists.llvm.org
Thu Oct 30 10:35:46 PDT 2025
Author: Marcell Leleszi
Date: 2025-10-30T10:35:42-07:00
New Revision: 784b74c6ef8a7f6ffaa7ab250eb35696dd833426
URL: https://github.com/llvm/llvm-project/commit/784b74c6ef8a7f6ffaa7ab250eb35696dd833426
DIFF: https://github.com/llvm/llvm-project/commit/784b74c6ef8a7f6ffaa7ab250eb35696dd833426.diff
LOG: [libc] Fix off by one error in strftime (#165711)
This patch fixes a bug in strftime's return value when the formatted
output exactly fills the buffer, not including the null terminator. The
previous check failed to account for the null terminator in this case,
incorrectly returning the written count instead of 0.
Added:
Modified:
libc/src/time/strftime.cpp
libc/src/time/strftime_l.cpp
libc/test/src/time/strftime_test.cpp
Removed:
################################################################################
diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp
index f36091bc9736e..89b7d9bb7c1b9 100644
--- a/libc/src/time/strftime.cpp
+++ b/libc/src/time/strftime.cpp
@@ -26,7 +26,7 @@ LLVM_LIBC_FUNCTION(size_t, strftime,
int ret = strftime_core::strftime_main(&writer, format, timeptr);
if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
wb.buff[wb.buff_cur] = '\0';
- return (ret < 0 || static_cast<size_t>(ret) > buffsz) ? 0 : ret;
+ return (ret < 0 || static_cast<size_t>(ret) >= buffsz) ? 0 : ret;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp
index 201b85da39ee2..409f8683b7289 100644
--- a/libc/src/time/strftime_l.cpp
+++ b/libc/src/time/strftime_l.cpp
@@ -29,7 +29,7 @@ LLVM_LIBC_FUNCTION(size_t, strftime_l,
int ret = strftime_core::strftime_main(&writer, format, timeptr);
if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
wb.buff[wb.buff_cur] = '\0';
- return (ret < 0 || static_cast<size_t>(ret) > buffsz) ? 0 : ret;
+ return (ret < 0 || static_cast<size_t>(ret) >= buffsz) ? 0 : ret;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/time/strftime_test.cpp b/libc/test/src/time/strftime_test.cpp
index cac7560b2b945..38176f77804d5 100644
--- a/libc/test/src/time/strftime_test.cpp
+++ b/libc/test/src/time/strftime_test.cpp
@@ -2326,3 +2326,23 @@ TEST(LlvmLibcStrftimeTest, TimeFormatFullDateTime) {
// size_t written = 0;
// SimplePaddedNum spn;
// }
+
+TEST(LlvmLibcStrftimeTest, BufferTooSmall) {
+ struct tm time;
+ char buffer[1];
+
+ time.tm_year = get_adjusted_year(2025);
+ time.tm_mon = 10;
+ time.tm_mday = 24;
+
+ size_t written =
+ LIBC_NAMESPACE::strftime(buffer, sizeof(buffer), "%F", &time);
+ EXPECT_EQ(written, size_t{0});
+
+ char buffer2[10];
+
+ // The string "2025-11-24" is 10 chars,
+ // so strftime needs 10 + 1 bytes to write the string and the null terminator.
+ written = LIBC_NAMESPACE::strftime(buffer, sizeof(buffer2), "%F", &time);
+ EXPECT_EQ(written, size_t{0});
+}
More information about the libc-commits
mailing list