tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mick Sear <mick.s...@succeed.co.uk>
Subject Possible bug in Tomcat Date header handling
Date Fri, 26 Aug 2011 15:25:32 GMT

Tomcat 7.0.20
Windows XP
JDK 1.6.0_20

I think there is a bug in Tomcat's handling of the Date HTTP header. I'm
mailing this list because there is a minor suggested code change at the
bottom to fix.

When the system clock time is advanced and then put back, with an HTTP
request being handled in between those two actions, Tomcat will send the
later of the two times in the response headers until the later time is
reached.

I think the problem is in the following code:


package org.apache.tomcat.util.http;

...

public final class FastHttpDateFormat {
...

/**
* Get the current date in HTTP format.
*/
public static final String getCurrentDate() {

    long now = System.currentTimeMillis();
    if ((now - currentDateGenerated) > 1000) {
        synchronized (format) {
            if ((now - currentDateGenerated) > 1000) {
                currentDate = format.format(new Date(now));
                currentDateGenerated = now;
            }
        }
    }
    return currentDate;

}


So, when the clock is advanced, currentDateGenerated becomes 'now'.
However, when it is retarded, now-currentDateGenerated will typically be a
negative number, and so the current date is never updated.

This is causing us a problem since we have systems that sync off the date
header.  I have tried to work around the problem with a ServletFilter:

HttpServletResponse httpResp = (HttpServletResponse) resp;
		
DateFormat df = new SimpleDateFormat(HTTP_RESPONSE_DATE_HEADER, Locale.US);
df.setTimeZone(GMT_ZONE);
httpResp.setHeader("Date", df.format(new
Date(System.currentTimeMillis())));

However, it looks like Tomcat is overriding the Date header later in the
request lifecycle than a ServetFilter can intercept.

I understand that the 'getCurrentDate()' method in the code above means
that Tomcat only needs to do a DateFormat.format() on a long value once
every second at most and so was clearly introduced to improve performance,
but this makes Tomcat susceptible to incorrect system dates and will also
be returning an invalid time for (typically) one hour when clocks go back
in the autumn / fall.

It would be better to check for a negative number in this method and
regenerate 'currentDateGenerated' if this is the case:

...
    if ((now - currentDateGenerated) > 1000 || (now -
currentDateGenerated) < 0) {
        synchronized (format) {
            if ((now - currentDateGenerated) > 1000) {
                currentDate = format.format(new Date(now));
                currentDateGenerated = now;
            }
        }
    }
    return currentDate;
...


Please let me know if there is a workaround or if I'm wrong in my reading
of the situation.

Thanks,
Mick Sear



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message