You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
time-util: rework localtime_or_gmtime() into localtime_or_gmtime_usec()
We typically want to deal in usec_t, hence let's change the prototype
accordingly, and do proper range checks. Also, make sure are not
confused by negative times.
Do something similar for mktime_or_timegm().
This is a more comprehensive alternative to #34065
Replaces: #34065
Copy file name to clipboardExpand all lines: src/basic/time-util.c
+51-19Lines changed: 51 additions & 19 deletions
Original file line number
Diff line number
Diff line change
@@ -332,7 +332,6 @@ char* format_timestamp_style(
332
332
333
333
structtmtm;
334
334
boolutc, us;
335
-
time_tsec;
336
335
size_tn;
337
336
338
337
assert(buf);
@@ -375,9 +374,7 @@ char* format_timestamp_style(
375
374
returnstrcpy(buf, xxx[style]);
376
375
}
377
376
378
-
sec= (time_t) (t / USEC_PER_SEC); /* Round down */
379
-
380
-
if (!localtime_or_gmtime_r(&sec, &tm, utc))
377
+
if (localtime_or_gmtime_usec(t, utc, &tm) <0)
381
378
returnNULL;
382
379
383
380
/* Start with the week day */
@@ -665,7 +662,6 @@ static int parse_timestamp_impl(
665
662
unsignedfractional=0;
666
663
constchar*k;
667
664
structtmtm, copy;
668
-
time_tsec;
669
665
670
666
/* Allowed syntaxes:
671
667
*
@@ -778,10 +774,9 @@ static int parse_timestamp_impl(
778
774
}
779
775
}
780
776
781
-
sec= (time_t) (usec / USEC_PER_SEC);
782
-
783
-
if (!localtime_or_gmtime_r(&sec, &tm, utc))
784
-
return-EINVAL;
777
+
r=localtime_or_gmtime_usec(usec, utc, &tm);
778
+
if (r<0)
779
+
returnr;
785
780
786
781
tm.tm_isdst=isdst;
787
782
@@ -939,11 +934,11 @@ static int parse_timestamp_impl(
939
934
} else
940
935
minus=gmtoff*USEC_PER_SEC;
941
936
942
-
sec=mktime_or_timegm(&tm, utc);
943
-
if (sec<0)
944
-
return-EINVAL;
937
+
r=mktime_or_timegm_usec(&tm, utc, &usec);
938
+
if (r<0)
939
+
returnr;
945
940
946
-
usec=usec_add(sec*USEC_PER_SEC, fractional);
941
+
usec=usec_add(usec, fractional);
947
942
948
943
finish:
949
944
usec=usec_add(usec, plus);
@@ -1625,17 +1620,54 @@ int get_timezone(char **ret) {
1625
1620
returnstrdup_to(ret, e);
1626
1621
}
1627
1622
1628
-
time_tmktime_or_timegm(structtm*tm, boolutc) {
1623
+
intmktime_or_timegm_usec(
1624
+
structtm*tm, /* input + normalized output */
1625
+
boolutc,
1626
+
usec_t*ret) {
1627
+
1628
+
time_tt;
1629
+
1629
1630
assert(tm);
1630
1631
1631
-
returnutc ? timegm(tm) : mktime(tm);
1632
+
if (tm->tm_year<69) /* early check for negative (i.e. before 1970) time_t (Note that in some timezones the epoch is in the year 1969!)*/
1633
+
return-ERANGE;
1634
+
if ((usec_t) tm->tm_year>CONST_MIN(USEC_INFINITY / USEC_PER_YEAR, (usec_t) TIME_T_MAX / (365U*24U*60U*60U)) -1900) /* early check for possible overrun of usec_t or time_t */
1635
+
return-ERANGE;
1636
+
1637
+
/* timegm()/mktime() is a bit weird to use, since it returns -1 in two cases: on error as well as a
1638
+
* valid time indicating one second before the UNIX epoch. Let's treat both cases the same here, and
1639
+
* return -ERANGE for anything negative, since usec_t is unsigned, and we can thus not express
1640
+
* negative times anyway. */
1641
+
1642
+
t=utc ? timegm(tm) : mktime(tm);
1643
+
if (t<0) /* Refuse negative times and errors */
1644
+
return-ERANGE;
1645
+
if ((usec_t) t >= USEC_INFINITY / USEC_PER_SEC) /* Never return USEC_INFINITY by accident (or overflow) */
0 commit comments