[libc-commits] [libc] 80225af - [libc] Fix overflow check for 32 bit long time_t (#65394)
via libc-commits
libc-commits at lists.llvm.org
Thu Sep 7 06:18:28 PDT 2023
Author: Mikhail R. Gadelha
Date: 2023-09-07T09:18:23-04:00
New Revision: 80225af4c1445c7818c6a71121d83bcc8ed7dd3b
URL: https://github.com/llvm/llvm-project/commit/80225af4c1445c7818c6a71121d83bcc8ed7dd3b
DIFF: https://github.com/llvm/llvm-project/commit/80225af4c1445c7818c6a71121d83bcc8ed7dd3b.diff
LOG: [libc] Fix overflow check for 32 bit long time_t (#65394)
This patch fixes the overflow check in update_from_seconds, used by
gmtime, gmtime_r and mktime.
In update_from_seconds, total_seconds is a int64_t and the previous
overflow check for when sizeof(time_t) == 4 would check if it was <
0x80000000 and > 0x7FFFFFFF, however, this check would cause the
following issues:
1. Valid negative numbers would be discarded, e.g., -1 is
0xffffffffffffffff as a int64_t, outside the range of the overflow
check.
2. Some valid positive numbers would be discarded because the hex
constants were being implicitly converted to int64_t, e.g., 0x80000000
would be implicitly converted to 2147483648, instead of -2147483648.
The fix for both cases was to static_cast total_seconds and the
constants to time_t if sizeof(time_t) == 4. The behaviour is not changed
in systems with sizeof(time_t) == 8.
---------
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
Added:
Modified:
libc/src/time/mktime.cpp
libc/src/time/time_utils.cpp
libc/src/time/time_utils.h
Removed:
################################################################################
diff --git a/libc/src/time/mktime.cpp b/libc/src/time/mktime.cpp
index ea748ce4ab72737..3b3ea339f850f96 100644
--- a/libc/src/time/mktime.cpp
+++ b/libc/src/time/mktime.cpp
@@ -53,9 +53,9 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) {
// Years are ints. A 32-bit year will fit into a 64-bit time_t.
// A 64-bit year will not.
- static_assert(sizeof(int) == 4,
- "ILP64 is unimplemented. This implementation requires "
- "32-bit integers.");
+ static_assert(
+ sizeof(int) == 4,
+ "ILP64 is unimplemented. This implementation requires 32-bit integers.");
// Calculate number of months and years from tm_mon.
int64_t month = tm_out->tm_mon;
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 2cb0f071e6ce111..fadd26f97dfc228 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -48,20 +48,20 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) {
static const char daysInMonth[] = {31 /* Mar */, 30, 31, 30, 31, 31,
30, 31, 30, 31, 31, 29};
- if (sizeof(time_t) == 4) {
- if (total_seconds < 0x80000000)
- return time_utils::out_of_range();
- if (total_seconds > 0x7FFFFFFF)
- return time_utils::out_of_range();
- } else {
- if (total_seconds <
- INT_MIN * static_cast<int64_t>(
- TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR) ||
- total_seconds >
- INT_MAX * static_cast<int64_t>(
- TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR))
- return time_utils::out_of_range();
- }
+ constexpr time_t time_min =
+ (sizeof(time_t) == 4)
+ ? INT_MIN
+ : INT_MIN * static_cast<int64_t>(
+ TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR);
+ constexpr time_t time_max =
+ (sizeof(time_t) == 4)
+ ? INT_MAX
+ : INT_MAX * static_cast<int64_t>(
+ TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR);
+
+ time_t ts = static_cast<time_t>(total_seconds);
+ if (ts < time_min || ts > time_max)
+ return time_utils::out_of_range();
int64_t seconds =
total_seconds - TimeConstants::SECONDS_UNTIL2000_MARCH_FIRST;
diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h
index 8075bfe32027ae6..424e7521504d917 100644
--- a/libc/src/time/time_utils.h
+++ b/libc/src/time/time_utils.h
@@ -92,7 +92,7 @@ extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm);
// POSIX.1-2017 requires this.
LIBC_INLINE time_t out_of_range() {
libc_errno = EOVERFLOW;
- return static_cast<time_t>(-1);
+ return TimeConstants::OUT_OF_RANGE_RETURN_VALUE;
}
LIBC_INLINE void invalid_value() { libc_errno = EINVAL; }
More information about the libc-commits
mailing list