This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Guard against time and year overflows
authorH.Merijn Brand <merijn@tux.site>
Sat, 18 Oct 2008 10:01:33 +0000 (12:01 +0200)
committerH.Merijn Brand <merijn@tux.site>
Sat, 18 Oct 2008 10:01:33 +0000 (12:01 +0200)
U/perl/time_size.U

index 21a9486..c2e737a 100644 (file)
@@ -71,10 +71,12 @@ int i;
 struct tm *tmp;
 time_t pt;
 
-void gm_check (time_t t)
+void gm_check (time_t t, int min_year, int max_year)
 {
     tmp = gmtime (&t);
-    if (tmp == NULL || tmp->tm_year < -1900)
+    if ( tmp == NULL ||
+       /* Check tm_year overflow */
+        tmp->tm_year < min_year || tmp->tm_year > max_year)
        tmp = NULL;
     else
        pt = t;
@@ -85,13 +87,13 @@ int check_max ()
     tmp = NULL;
     pt  = 0;
 #ifdef MAXLONG
-    gm_check (MAXLONG);
+    gm_check (MAXLONG, 69, 0x7fffffff);
 #endif
     if (tmp == NULL || tmp->tm_year < 0) {
        for (i = 63; i >= 0; i--) {
            time_t x = pt | ((time_t)1 << i);
-           if (x < 0) continue;
-           gm_check (x);
+           if (x < 0 || x < pt) continue;
+           gm_check (x, 69, 0x7fffffff);
            }
        }
     printf ("sGMTIME_max=%ld\n", pt);
@@ -103,13 +105,13 @@ int check_min ()
     tmp = NULL;
     pt  = 0;
 #ifdef MINLONG
-    gm_check (MINLONG);
+    gm_check (MINLONG, -1900, 70);
 #endif
     if (tmp == NULL) {
        for (i = 36; i >= 0; i--) {
            time_t x = pt - ((time_t)1 << i);
            if (x > 0) continue;
-           gm_check (x);
+           gm_check (x, -1900, 70);
            }
        }
     printf ("sGMTIME_min=%ld\n", pt);
@@ -148,13 +150,15 @@ int i;
 struct tm *tmp;
 time_t pt;
 
-void local_check (time_t t)
+void local_check (time_t t, int min_year, int max_year)
 {
     if (sizeof (time_t) > 4 && t > 0x7ffffffffffff000LL)
        tmp = NULL;
     else
        tmp = localtime (&t);
-    if (tmp == NULL || tmp->tm_year < -1900)
+    if ( tmp == NULL ||
+       /* Check tm_year overflow */
+        tmp->tm_year < min_year || tmp->tm_year > max_year)
        tmp = NULL;
     else
        pt = t;
@@ -165,13 +169,13 @@ int check_max ()
     tmp = NULL;
     pt  = 0;
 #ifdef MAXLONG
-    local_check (MAXLONG);
+    local_check (MAXLONG, 69, 0x7fffffff);
 #endif
     if (tmp == NULL || tmp->tm_year < 0) {
        for (i = 63; i >= 0; i--) {
            time_t x = pt | ((time_t)1 << i);
-           if (x < 0) continue;
-           local_check (x);
+           if (x < 0 || x < pt) continue;
+           local_check (x, 69, 0x7fffffff);
            }
        }
     printf ("sLOCALTIME_max=%ld\n", pt);
@@ -183,13 +187,13 @@ int check_min ()
     tmp = NULL;
     pt  = 0;
 #ifdef MINLONG
-    local_check (MINLONG);
+    local_check (MINLONG, -1900, 70);
 #endif
     if (tmp == NULL) {
        for (i = 36; i >= 0; i--) {
            time_t x = pt - ((time_t)1 << i);
            if (x > 0) continue;
-           local_check (x);
+           local_check (x, -1900, 70);
            }
        }
     printf ("sLOCALTIME_min=%ld\n", pt);