[libc-commits] [libc] [libc] Complete hardening of time functions and remove Y2038 limit (PR #203298)
via libc-commits
libc-commits at lists.llvm.org
Thu Jun 11 08:05:45 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Jeff Bailey (kaladron)
<details>
<summary>Changes</summary>
Completed safety and hardening refactoring for time functions, and removed Y2038 limitation:
* Hardening: Refactored update_from_seconds to return ErrorOr<int>
(instead of int64_t status, as it only returns status 0 or error)
and propagated it to entrypoints. Added LIBC_CRASH_ON_NULLPTR to public
boundaries and converted tests to death tests using SIGILL.
* Y2038: Removed the artificial int32_t max check from ctime and ctime_r, allowing them to support timestamps beyond 2038 (up to Year 9999).
* Tests: Updated ctime/ctime_r tests to include Year 2039 test cases and updated overflow test cases to Year 10000.
* Style: Fixed header blocks and added Doxygen comments in converter.h, str_converter.h, and time_utils.h.
* Conventions: Fixed relative includes in converter.h and time_utils.h.
Assisted-by: Automated tooling, human reviewed.
---
Patch is 45.83 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/203298.diff
27 Files Affected:
- (modified) libc/src/time/CMakeLists.txt (+19)
- (modified) libc/src/time/asctime.cpp (+10-2)
- (modified) libc/src/time/asctime_r.cpp (+12-2)
- (modified) libc/src/time/ctime.cpp (+15-4)
- (modified) libc/src/time/ctime_r.cpp (+15-5)
- (modified) libc/src/time/gmtime.cpp (+10-1)
- (modified) libc/src/time/gmtime_r.cpp (+11-1)
- (modified) libc/src/time/localtime.cpp (+7-1)
- (modified) libc/src/time/localtime_r.cpp (+7-1)
- (modified) libc/src/time/mktime.cpp (+13-4)
- (modified) libc/src/time/strftime.cpp (+6)
- (modified) libc/src/time/strftime_core/CMakeLists.txt (+1)
- (modified) libc/src/time/strftime_core/composite_converter.h (+84-18)
- (modified) libc/src/time/strftime_core/converter.h (+18-11)
- (modified) libc/src/time/strftime_core/num_converter.h (+13-6)
- (modified) libc/src/time/strftime_core/str_converter.h (+16-5)
- (modified) libc/src/time/strftime_l.cpp (+6)
- (modified) libc/src/time/time_utils.cpp (+3-3)
- (modified) libc/src/time/time_utils.h (+54-54)
- (modified) libc/test/src/time/asctime_r_test.cpp (+7-12)
- (modified) libc/test/src/time/asctime_test.cpp (+2-4)
- (modified) libc/test/src/time/ctime_r_test.cpp (+19-10)
- (modified) libc/test/src/time/ctime_test.cpp (+12-4)
- (modified) libc/test/src/time/gmtime_r_test.cpp (+12)
- (modified) libc/test/src/time/gmtime_test.cpp (+5)
- (modified) libc/test/src/time/localtime_r_test.cpp (+9-2)
- (modified) libc/test/src/time/localtime_test.cpp (+2-1)
``````````diff
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 4d647c22c3239..f42b9b3723ca0 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -44,6 +44,8 @@ add_entrypoint_object(
.time_constants
libc.include.time
libc.hdr.types.struct_tm
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -57,6 +59,8 @@ add_entrypoint_object(
.time_constants
libc.include.time
libc.hdr.types.struct_tm
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -70,6 +74,8 @@ add_entrypoint_object(
.time_constants
libc.hdr.types.time_t
libc.include.time
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -83,6 +89,8 @@ add_entrypoint_object(
.time_constants
libc.hdr.types.time_t
libc.include.time
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -95,6 +103,8 @@ add_entrypoint_object(
.time_utils
libc.hdr.types.time_t
libc.hdr.types.struct_tm
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -107,6 +117,8 @@ add_entrypoint_object(
.time_utils
libc.hdr.types.time_t
libc.hdr.types.struct_tm
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -131,6 +143,8 @@ add_entrypoint_object(
libc.include.time
libc.hdr.types.time_t
libc.hdr.types.struct_tm
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -144,6 +158,8 @@ add_entrypoint_object(
libc.include.time
libc.hdr.types.time_t
libc.hdr.types.struct_tm
+ libc.src.errno.errno
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -159,6 +175,7 @@ add_entrypoint_object(
libc.src.errno.errno
libc.hdr.types.time_t
libc.hdr.types.struct_tm
+ libc.src.__support.macros.null_check
)
add_subdirectory(strftime_core) #TODO: Move to top
@@ -174,6 +191,7 @@ add_entrypoint_object(
libc.hdr.types.struct_tm
libc.src.stdio.printf_core.writer
libc.src.time.strftime_core.strftime_main
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
@@ -188,6 +206,7 @@ add_entrypoint_object(
libc.hdr.types.struct_tm
libc.src.stdio.printf_core.writer
libc.src.time.strftime_core.strftime_main
+ libc.src.__support.macros.null_check
)
add_entrypoint_object(
diff --git a/libc/src/time/asctime.cpp b/libc/src/time/asctime.cpp
index 2b00c4136f906..8baeeb88b5698 100644
--- a/libc/src/time/asctime.cpp
+++ b/libc/src/time/asctime.cpp
@@ -8,16 +8,24 @@
#include "src/time/asctime.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(char *, asctime, (const struct tm *timeptr)) {
+ LIBC_CRASH_ON_NULLPTR(timeptr);
static char buffer[time_constants::ASCTIME_BUFFER_SIZE];
- return time_utils::asctime(timeptr, buffer,
- time_constants::ASCTIME_MAX_BYTES);
+ auto res =
+ time_utils::asctime(timeptr, buffer, time_constants::ASCTIME_MAX_BYTES);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/asctime_r.cpp b/libc/src/time/asctime_r.cpp
index bf53bfdf2f8c2..1002e4139adf7 100644
--- a/libc/src/time/asctime_r.cpp
+++ b/libc/src/time/asctime_r.cpp
@@ -8,7 +8,9 @@
#include "src/time/asctime_r.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
@@ -16,8 +18,16 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(char *, asctime_r,
(const struct tm *timeptr, char *buffer)) {
- return time_utils::asctime(timeptr, buffer,
- time_constants::ASCTIME_MAX_BYTES);
+ LIBC_CRASH_ON_NULLPTR(timeptr);
+ LIBC_CRASH_ON_NULLPTR(buffer);
+
+ auto res =
+ time_utils::asctime(timeptr, buffer, time_constants::ASCTIME_MAX_BYTES);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp
index ac0ffe5b32ae5..c7efcbffc5123 100644
--- a/libc/src/time/ctime.cpp
+++ b/libc/src/time/ctime.cpp
@@ -7,21 +7,32 @@
//===----------------------------------------------------------------------===//
#include "src/time/ctime.h"
-#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t_ptr)) {
- if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits<int32_t>::max()) {
+ LIBC_CRASH_ON_NULLPTR(t_ptr);
+
+ auto lt_res = time_utils::localtime(t_ptr);
+ if (!lt_res) {
+ libc_errno = lt_res.error();
return nullptr;
}
+
static char buffer[time_constants::ASCTIME_BUFFER_SIZE];
- return time_utils::asctime(time_utils::localtime(t_ptr), buffer,
- time_constants::ASCTIME_MAX_BYTES);
+ auto res = time_utils::asctime(lt_res.value(), buffer,
+ time_constants::ASCTIME_MAX_BYTES);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp
index 7224f7742f139..0c8260b04df2a 100644
--- a/libc/src/time/ctime_r.cpp
+++ b/libc/src/time/ctime_r.cpp
@@ -7,22 +7,32 @@
//===----------------------------------------------------------------------===//
#include "src/time/ctime_r.h"
-#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) {
- if (t_ptr == nullptr || buffer == nullptr ||
- *t_ptr > cpp::numeric_limits<int32_t>::max()) {
+ LIBC_CRASH_ON_NULLPTR(t_ptr);
+ LIBC_CRASH_ON_NULLPTR(buffer);
+
+ auto lt_res = time_utils::localtime(t_ptr);
+ if (!lt_res) {
+ libc_errno = lt_res.error();
return nullptr;
}
- return time_utils::asctime(time_utils::localtime(t_ptr), buffer,
- time_constants::ASCTIME_MAX_BYTES);
+ auto res = time_utils::asctime(lt_res.value(), buffer,
+ time_constants::ASCTIME_MAX_BYTES);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/gmtime.cpp b/libc/src/time/gmtime.cpp
index 6785d18d43e36..32a14b4d53c66 100644
--- a/libc/src/time/gmtime.cpp
+++ b/libc/src/time/gmtime.cpp
@@ -8,14 +8,23 @@
#include "src/time/gmtime.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(struct tm *, gmtime, (const time_t *timer)) {
+ LIBC_CRASH_ON_NULLPTR(timer);
+
static struct tm tm_out;
- return time_utils::gmtime_internal(timer, &tm_out);
+ auto result = time_utils::gmtime_internal(timer, &tm_out);
+ if (!result) {
+ libc_errno = result.error();
+ return nullptr;
+ }
+ return result.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/gmtime_r.cpp b/libc/src/time/gmtime_r.cpp
index d506b526edfb0..6b37d4e3f0990 100644
--- a/libc/src/time/gmtime_r.cpp
+++ b/libc/src/time/gmtime_r.cpp
@@ -8,14 +8,24 @@
#include "src/time/gmtime_r.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(struct tm *, gmtime_r,
(const time_t *timer, struct tm *result)) {
- return time_utils::gmtime_internal(timer, result);
+ LIBC_CRASH_ON_NULLPTR(timer);
+ LIBC_CRASH_ON_NULLPTR(result);
+
+ auto res = time_utils::gmtime_internal(timer, result);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime.cpp b/libc/src/time/localtime.cpp
index 90a296178bae8..84b70e90a9384 100644
--- a/libc/src/time/localtime.cpp
+++ b/libc/src/time/localtime.cpp
@@ -9,6 +9,7 @@
#include "src/time/localtime.h"
#include "hdr/types/struct_tm.h"
#include "hdr/types/time_t.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/null_check.h"
#include "src/time/time_utils.h"
@@ -18,7 +19,12 @@ LLVM_LIBC_FUNCTION(struct tm *, localtime, (const time_t *timer)) {
LIBC_CRASH_ON_NULLPTR(timer);
static struct tm tm_out;
- return time_utils::localtime_internal(timer, &tm_out);
+ auto res = time_utils::localtime_internal(timer, &tm_out);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/localtime_r.cpp b/libc/src/time/localtime_r.cpp
index 70bbbeed271ea..298996b2a21ea 100644
--- a/libc/src/time/localtime_r.cpp
+++ b/libc/src/time/localtime_r.cpp
@@ -9,6 +9,7 @@
#include "src/time/localtime_r.h"
#include "hdr/types/struct_tm.h"
#include "hdr/types/time_t.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/null_check.h"
#include "src/time/time_utils.h"
@@ -19,7 +20,12 @@ LLVM_LIBC_FUNCTION(struct tm *, localtime_r,
LIBC_CRASH_ON_NULLPTR(timer);
LIBC_CRASH_ON_NULLPTR(buf);
- return time_utils::localtime_internal(timer, buf);
+ auto res = time_utils::localtime_internal(timer, buf);
+ if (!res) {
+ libc_errno = res.error();
+ return nullptr;
+ }
+ return res.value();
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/time/mktime.cpp b/libc/src/time/mktime.cpp
index 81652396e7fc2..a20fba4fb0aa1 100644
--- a/libc/src/time/mktime.cpp
+++ b/libc/src/time/mktime.cpp
@@ -8,22 +8,31 @@
#include "src/time/mktime.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/time/time_constants.h"
#include "src/time/time_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) {
+ LIBC_CRASH_ON_NULLPTR(tm_out);
+
auto mktime_result = time_utils::mktime_internal(tm_out);
- if (!mktime_result)
- return time_utils::out_of_range();
+ if (!mktime_result) {
+ libc_errno = EOVERFLOW;
+ return time_constants::OUT_OF_RANGE_RETURN_VALUE;
+ }
time_t seconds = *mktime_result;
// Update the tm structure's year, month, day, etc. from seconds.
- if (time_utils::update_from_seconds(seconds, tm_out) < 0)
- return time_utils::out_of_range();
+ auto status = time_utils::update_from_seconds(seconds, tm_out);
+ if (!status) {
+ libc_errno = status.error();
+ return time_constants::OUT_OF_RANGE_RETURN_VALUE;
+ }
return seconds;
}
diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp
index af0f438d22cab..71e1e99080e56 100644
--- a/libc/src/time/strftime.cpp
+++ b/libc/src/time/strftime.cpp
@@ -11,6 +11,7 @@
#include "hdr/types/struct_tm.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/stdio/printf_core/writer.h"
#include "src/time/strftime_core/strftime_main.h"
@@ -19,6 +20,11 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(size_t, strftime,
(char *__restrict buffer, size_t buffsz,
const char *__restrict format, const tm *timeptr)) {
+ if (buffsz > 0)
+ LIBC_CRASH_ON_NULLPTR(buffer);
+ LIBC_CRASH_ON_NULLPTR(format);
+ LIBC_CRASH_ON_NULLPTR(timeptr);
+
printf_core::DropOverflowBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
auto ret = strftime_core::strftime_main(&writer, format, timeptr);
diff --git a/libc/src/time/strftime_core/CMakeLists.txt b/libc/src/time/strftime_core/CMakeLists.txt
index a9aa573cc9a63..31eb41aa1647f 100644
--- a/libc/src/time/strftime_core/CMakeLists.txt
+++ b/libc/src/time/strftime_core/CMakeLists.txt
@@ -33,6 +33,7 @@ add_header_library(
libc.src.stdio.printf_core.writer
libc.src.__support.CPP.string_view
libc.src.__support.integer_to_string
+ libc.src.__support.error_or
)
add_header_library(
diff --git a/libc/src/time/strftime_core/composite_converter.h b/libc/src/time/strftime_core/composite_converter.h
index 53cb7e536a0e5..0417d8edf1e36 100644
--- a/libc/src/time/strftime_core/composite_converter.h
+++ b/libc/src/time/strftime_core/composite_converter.h
@@ -22,7 +22,7 @@
namespace LIBC_NAMESPACE_DECL {
namespace strftime_core {
-LIBC_INLINE IntFormatSection
+LIBC_INLINE ErrorOr<IntFormatSection>
get_specific_int_format(const tm *timeptr, const FormatSection &base_to_conv,
char new_conv_name, int TRAILING_CONV_LEN = -1) {
// a negative padding will be treated as the default
@@ -32,7 +32,10 @@ get_specific_int_format(const tm *timeptr, const FormatSection &base_to_conv,
new_conv.conv_name = new_conv_name;
new_conv.min_width = NEW_MIN_WIDTH;
- IntFormatSection result = get_int_format(new_conv, timeptr);
+ auto result_or = get_int_format(new_conv, timeptr);
+ if (!result_or)
+ return cpp::unexpected(result_or.error());
+ IntFormatSection result = result_or.value();
// If the user set the padding, but it's below the width of the trailing
// conversions, then there should be no padding.
@@ -54,9 +57,21 @@ LIBC_INLINE int convert_date_us(printf_core::Writer<write_mode> *writer,
IntFormatSection mon_conv;
IntFormatSection mday_conv;
- mon_conv = get_specific_int_format(timeptr, to_conv, 'm', TRAILING_CONV_LEN);
- mday_conv = get_specific_int_format(timeptr, to_conv, 'd');
- year_conv = get_specific_int_format(timeptr, to_conv, 'y');
+ auto mon_conv_or =
+ get_specific_int_format(timeptr, to_conv, 'm', TRAILING_CONV_LEN);
+ if (!mon_conv_or)
+ return -mon_conv_or.error();
+ mon_conv = mon_conv_or.value();
+
+ auto mday_conv_or = get_specific_int_format(timeptr, to_conv, 'd');
+ if (!mday_conv_or)
+ return -mday_conv_or.error();
+ mday_conv = mday_conv_or.value();
+
+ auto year_conv_or = get_specific_int_format(timeptr, to_conv, 'y');
+ if (!year_conv_or)
+ return -year_conv_or.error();
+ year_conv = year_conv_or.value();
RET_IF_RESULT_NEGATIVE(write_padded_int(writer, mon_conv));
RET_IF_RESULT_NEGATIVE(writer->write('/'));
@@ -79,9 +94,21 @@ LIBC_INLINE int convert_date_iso(printf_core::Writer<write_mode> *writer,
IntFormatSection mon_conv;
IntFormatSection mday_conv;
- year_conv = get_specific_int_format(timeptr, to_conv, 'Y', TRAILING_CONV_LEN);
- mon_conv = get_specific_int_format(timeptr, to_conv, 'm');
- mday_conv = get_specific_int_format(timeptr, to_conv, 'd');
+ auto year_conv_or =
+ get_specific_int_format(timeptr, to_conv, 'Y', TRAILING_CONV_LEN);
+ if (!year_conv_or)
+ return -year_conv_or.error();
+ year_conv = year_conv_or.value();
+
+ auto mon_conv_or = get_specific_int_format(timeptr, to_conv, 'm');
+ if (!mon_conv_or)
+ return -mon_conv_or.error();
+ mon_conv = mon_conv_or.value();
+
+ auto mday_conv_or = get_specific_int_format(timeptr, to_conv, 'd');
+ if (!mday_conv_or)
+ return -mday_conv_or.error();
+ mday_conv = mday_conv_or.value();
RET_IF_RESULT_NEGATIVE(write_padded_int(writer, year_conv));
RET_IF_RESULT_NEGATIVE(writer->write('-'));
@@ -107,9 +134,21 @@ LIBC_INLINE int convert_time_am_pm(printf_core::Writer<write_mode> *writer,
const time_utils::TMReader time_reader(timeptr);
- hour_conv = get_specific_int_format(timeptr, to_conv, 'I', TRAILING_CONV_LEN);
- min_conv = get_specific_int_format(timeptr, to_conv, 'M');
- sec_conv = get_specific_int_format(timeptr, to_conv, 'S');
+ auto hour_conv_or =
+ get_specific_int_format(timeptr, to_conv, 'I', TRAILING_CONV_LEN);
+ if (!hour_conv_or)
+ return -hour_conv_or.error();
+ hour_conv = hour_conv_or.value();
+
+ auto min_conv_or = get_specific_int_format(timeptr, to_conv, 'M');
+ if (!min_conv_or)
+ return -min_conv_or.error();
+ min_conv = min_conv_or.value();
+
+ auto sec_conv_or = get_specific_int_format(timeptr, to_conv, 'S');
+ if (!sec_conv_or)
+ return -sec_conv_or.error();
+ sec_conv = sec_conv_or.value();
RET_IF_RESULT_NEGATIVE(write_padded_int(writer, hour_conv));
RET_IF_RESULT_NEGATIVE(writer->write(':'));
@@ -133,8 +172,16 @@ LIBC_INLINE int convert_time_minute(printf_core::Writer<write_mode> *writer,
IntFormatSection hour_conv;
IntFormatSection min_conv;
- hour_conv = get_specific_int_format(timeptr, to_conv, 'H', TRAILING_CONV_LEN);
- min_conv = get_specific_int_format(timeptr, to_conv, 'M');
+ auto hour_conv_or =
+ get_specific_int_format(timeptr, to_conv, 'H', TRAILING_CONV_LEN);
+ if (!hour_conv_or)
+ return -hour_conv_or.error();
+ hour_conv = hour_conv_or.value();
+
+ auto min_conv_or = get_specific_int_format(timeptr, to_conv, 'M');
+ if (!min_conv_or)
+ return -min_conv_or.error();
+ min_conv = min_conv_or.value();
RET_IF_RESULT_NEGATIVE(write_padded_int(writer, hour_conv));
RET_IF_RESULT_NEGATIVE(writer->write(':'));
@@ -155,9 +202,21 @@ LIBC_INLINE int convert_time_second(printf_core::Writer<write_mode> *writer,
IntFormatSection min_conv;
IntFormatSection sec_conv;
- hour_conv = get_specific_int_format(timeptr, to_conv, 'H', TRAILING_CONV_LEN);
- min_conv = get_specific_int_format(timeptr, to_conv, 'M');
- sec_conv = get_specific_int_format(timeptr, to_conv, 'S');
+ auto hour_conv_or =
+ get_specific_int_format(timeptr, to_conv, 'H', TRAILING_CONV_LEN);
+ if (!hour_conv_or)
+ return -hour_conv_or.error();
+ hour_conv = hour_conv_or.value();
+
+ auto min_conv_or = get_specific_int_format(timeptr, to_conv, 'M');
+ if (!min_conv_or)
+ return -min_conv_or.error();
+ min_conv = min_conv_or.value();
+
+ auto sec_conv_or = get_specific_int_format(timeptr, to_conv, 'S');
+ if (!sec_conv_or)
+ return -sec_conv_or.error();
+ sec_conv = sec_conv_or.value();
RET_IF_RESULT_NEGATIVE(write_padded_int(writer, hour_conv));
RET_IF_RESULT_NEGATIVE(writer->write(':'));
@@ -188,8 +247,15 @@ LIBC_INLINE int convert_full_date_time(printf_core::Writer<write_mode> *writer,
IntFormatSection mday_conv;
IntFormatSection year_conv;
- mday_conv = get_specific_int_format(timeptr, to_conv, 'e');
- year_conv = get_specific_int_format(timeptr, to_conv, 'Y');
+ auto mday_conv_or = get_specific_int_format(timeptr, to_conv, 'e');
+ if (!mday_conv_or)
+ return -mday_conv_or.error();
+ mday_conv = mday_conv_or.value();
+
+ auto year_conv_or = get_specific_int_format(timeptr, to_conv, 'Y');
+ if (!year_conv_or)
+ return -year_conv_or.error();
+ year_conv = year_conv_or.value();
FormatSection raw_time_conv = to_conv;
raw_time_conv.conv_name = 'T';
diff --git a/libc/src/time/strftime_core/converter.h b/libc/src/time/strftime_core/converter.h
index ff0faf35bbd90..7fc4b95eb51d5 100644
--- a/libc/src/time/strftime_core/converter.h
+++ b/libc/src/time/strftime_core/converter.h
@@ -1,10 +1,15 @@
-//===-- Format specifier converter for strftime -----------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/203298
More information about the libc-commits
mailing list