From nobody@FreeBSD.org  Sun Nov  9 01:56:55 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 26B4E1065670
	for <freebsd-gnats-submit@FreeBSD.org>; Sun,  9 Nov 2008 01:56:55 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 175568FC0A
	for <freebsd-gnats-submit@FreeBSD.org>; Sun,  9 Nov 2008 01:56:55 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id mA91usAl035664
	for <freebsd-gnats-submit@FreeBSD.org>; Sun, 9 Nov 2008 01:56:54 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id mA91ussJ035663;
	Sun, 9 Nov 2008 01:56:54 GMT
	(envelope-from nobody)
Message-Id: <200811090156.mA91ussJ035663@www.freebsd.org>
Date: Sun, 9 Nov 2008 01:56:54 GMT
From: Vladimir Timfeev <vovkasm@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: gmtime infinty loop
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         128714
>Category:       kern
>Synopsis:       gmtime(3) infine loop
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Nov 09 02:00:08 UTC 2008
>Closed-Date:    Thu Sep 29 14:56:14 UTC 2011
>Last-Modified:  Thu Sep 29 14:56:14 UTC 2011
>Originator:     Vladimir Timfeev
>Release:        6.2
>Organization:
>Environment:
FreeBSD zoo.rambler.ru 6.2-RELEASE-p1 FreeBSD 6.2-RELEASE-p1 #1: Thu Feb 15 17:00:27 MSK 2007     root@zoo.rambler.ru:/usr/obj/usr/src/sys/ZOO  amd64
>Description:
On amd64 platforms (tested with 6.2 and 7.0).
gmtime from libc doesn't returns to program if called with arg < -33884019326476800
May be we should return NULL?
>How-To-Repeat:
Simple program to test... first call return, second - loop forever...

#include <time.h>
#include <stdio.h>

void test(time_t t) {
    struct tm *date;
    printf("try %ld\n",t);
    date = gmtime(&t);
    printf(" ok\n");
}

int main(void) {
    time_t time_ok = -33884019326476800LL;
    time_t time_err = -33884019326476801LL;
    test(time_ok);
    test(time_err);
    return 0;
}
>Fix:


>Release-Note:
>Audit-Trail:

From: Giorgos Keramidas <keramida@freebsd.org>
To: Vladimir Timfeev <vovkasm@gmail.com>
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: kern/128714: gmtime infinty loop
Date: Mon, 10 Nov 2008 08:21:32 +0200

 On Sun, 9 Nov 2008 01:56:54 GMT, Vladimir Timfeev <vovkasm@gmail.com> wrote:
 > On amd64 platforms (tested with 6.2 and 7.0).
 > gmtime from libc doesn't returns to program if called with
 > arg < -33884019326476800
 > May be we should return NULL?
 
 > #include <time.h>
 > #include <stdio.h>
 >
 > void test(time_t t) {
 >     struct tm *date;
 >     printf("try %ld\n",t);
 >     date = gmtime(&t);
 >     printf(" ok\n");
 > }
 >
 > int main(void) {
 >     time_t time_ok = -33884019326476800LL;
 >     time_t time_err = -33884019326476801LL;
 >     test(time_ok);
 >     test(time_err);
 >     return 0;
 > }
 
 GCC warns about overflow when this is compiled with WARNS=6:
 
   foo.c:12: warning: overflow in implicit constant conversion
   foo.c:13: warning: overflow in implicit constant conversion
 
 Maybe that's part of the problem.  On i386 it seems to work FWIW, but it
 does print bogus results (because of the implicit truncation that
 happens when a huge negative number is assigned to time_t -- which is
 equivalent to int32_t on i386):
 
   $ ./foo
   try -126116352
    ok # Sun Jan  2 07:40:48 1966
   try -126116353
    ok # Sun Jan  2 07:40:47 1966
 

From: Giorgos Keramidas <keramida@freebsd.org>
To: Bruce Cran <bruce@cran.org.uk>
Cc: bug-followup@freebsd.org
Subject: Re: kern/128714: gmtime infinty loop
Date: Tue, 11 Nov 2008 07:00:06 +0200

 On Mon, 10 Nov 2008 07:45:37 -0800, Bruce Cran <bruce@cran.org.uk> wrote:
 > On an 8-CURRENT amd64 machine I get the stack trace:
 >
 > #0  0x00000008007053df in atexit () from /lib/libc.so.7
 > #1  0x0000000800706c8e in timeoff () from /lib/libc.so.7
 > #2  0x0000000800707355 in gmtime () from /lib/libc.so.7
 > #3  0x0000000000400638 in test (t=-33884019326476801) at test.c:7
 > #4  0x0000000000400686 in main () at test.c:15
 
 This looks like an exit() handler, running after ^C was pressed or
 similar.  The real bug seems to be in localtime.ctimesub().  When the
 last second of a non-leap year is passed to timesub() it starts
 'oscillating' between days = -1 and days = 365:
 
   $ env LD_PRELOAD=$HOME/obj-amd64/$HOME/ws/head/lib/libc/libc.so.7 \
       ./foo 2>&1 | head -30
   days        -392176149613 : y                 1970 yleap 1 ylen 366
   days            260555599 : y          -1074453235 yleap 0 ylen 365
   days              -172760 : y          -1073739385 yleap 0 ylen 365
   days                  365 : y          -1073739859 yleap 0 ylen 365
   days                   -1 : y          -1073739858 yleap 0 ylen 365
   days                  365 : y          -1073739859 yleap 0 ylen 365
   days                   -1 : y          -1073739858 yleap 0 ylen 365
   [repeat...]
 
 The following patch fixes this for me on ref8-amd64 at freebsd.org, but
 I want to write a mode detailed description of the changes, and test it
 a bit more before it is anywhere near 'committable' state.  A slightly
 less "hacky" version of the patch is probably a good idea too.  I don't
 like the exception of ``days == year_lengths[yleap]'' near line 1380,
 and there's probably a slightly cleaner way to make sure the iteration
 converges to the correct date after a finite number of iterations.
 
 The patch is...
 
 %%%
 Try to avoid 'oscillating' between -1 and 365 days in timesub().
 
 XXX: A more detailed explanation of why this happens is needed here.
 
 Submitted by:	Vladimir Timfeev
 PR:		kern/128714
 
 Index: lib/libc/stdtime/localtime.c
 ===================================================================
 --- lib/libc/stdtime/localtime.c	(revision 184823)
 +++ lib/libc/stdtime/localtime.c	(working copy)
 @@ -1366,7 +1366,7 @@
  		tmp->tm_wday += DAYSPERWEEK;
  	y = EPOCH_YEAR;
  #define LEAPS_THRU_END_OF(y)	((y) / 4 - (y) / 100 + (y) / 400)
 -	while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
 +	while (days < 0 || days > (long)year_lengths[yleap = isleap(y)]) {
  		long	newy;
  
  		newy = y + days / DAYSPERNYEAR;
 @@ -1377,6 +1377,8 @@
  			LEAPS_THRU_END_OF(y - 1);
  		y = newy;
  	}
 +	if (days == (long)year_lengths[yleap])
 +		days--;
  	tmp->tm_year = y - TM_YEAR_BASE;
  	tmp->tm_yday = (int) days;
  	ip = mon_lengths[yleap];
 %%%
State-Changed-From-To: open->feedback 
State-Changed-By: jh 
State-Changed-When: Fri Sep 23 20:16:18 UTC 2011 
State-Changed-Why:  
I couldn't reproduce this on 8.2. I guess that this might have been fixed 
in r192625 or r214411. 

Can you confirm that the problem has been fixed? 

http://www.freebsd.org/cgi/query-pr.cgi?pr=128714 
State-Changed-From-To: feedback->closed 
State-Changed-By: jh 
State-Changed-When: Thu Sep 29 14:56:13 UTC 2011 
State-Changed-Why:  
Apparently already fixed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=128714 
>Unformatted:
