[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