summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibC/time.cpp
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-08-01 14:59:17 -0400
committerLinus Groh <mail@linusgroh.de>2022-08-02 21:10:44 +0100
commite683ca00ccc17816b7af1b5311baf406552c6331 (patch)
tree13027ad2949d3ff86b64aeea143f3b5a2e1bb473 /Userland/Libraries/LibC/time.cpp
parent91e3a2aaca740e70279508d17f5f12805ca78bc7 (diff)
downloadserenity-e683ca00ccc17816b7af1b5311baf406552c6331.zip
LibC: Split time_t range validation to separate helper function
Right now, the tm_to_time helper invokes time_to_tm to validate the time_t it creates. Soon, both tm_to_time and time_to_tm will perform some TZDB lookups to handle DST. This isn't a huge cost, but let's avoid the double lookup here.
Diffstat (limited to 'Userland/Libraries/LibC/time.cpp')
-rw-r--r--Userland/Libraries/LibC/time.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/Userland/Libraries/LibC/time.cpp b/Userland/Libraries/LibC/time.cpp
index f43b8ad32f..c1df69c6a5 100644
--- a/Userland/Libraries/LibC/time.cpp
+++ b/Userland/Libraries/LibC/time.cpp
@@ -102,13 +102,19 @@ char* ctime_r(time_t const* t, char* buf)
static int const __seconds_per_day = 60 * 60 * 24;
-static struct tm* time_to_tm(struct tm* tm, time_t t)
+static bool is_valid_time(time_t timestamp)
{
// Note: these correspond to the number of seconds from epoch to the dates "Jan 1 00:00:00 -2147483648" and "Dec 31 23:59:59 2147483647",
// respectively, which are the smallest and biggest representable dates without overflowing tm->tm_year, if it is an int.
constexpr time_t smallest_possible_time = -67768040609740800;
constexpr time_t biggest_possible_time = 67768036191676799;
- if (t < smallest_possible_time || t > biggest_possible_time) {
+
+ return (timestamp >= smallest_possible_time) && (timestamp <= biggest_possible_time);
+}
+
+static struct tm* time_to_tm(struct tm* tm, time_t t)
+{
+ if (!is_valid_time(t)) {
errno = EOVERFLOW;
return nullptr;
}
@@ -162,8 +168,12 @@ static time_t tm_to_time(struct tm* tm, long timezone_adjust_seconds)
tm->tm_yday = day_of_year(1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
time_t days_since_epoch = years_to_days_since_epoch(1900 + tm->tm_year) + tm->tm_yday;
auto timestamp = ((days_since_epoch * 24 + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec + timezone_adjust_seconds;
- if (!time_to_tm(tm, timestamp))
+
+ if (!is_valid_time(timestamp)) {
+ errno = EOVERFLOW;
return -1;
+ }
+
return timestamp;
}