Date: Wed, 28 Nov 2001 21:42:54 -0800 (PST) From: David Wolfskill <dhw@whistle.com> To: FreeBSD-gnats-submit@freebsd.org Cc: thomasoniii@yahoo.com Subject: ports/32372: Broken timezone specification generated by Bulkmail.pm Message-ID: <200111290542.fAT5gsg16522@pau-amma.whistle.com>
next in thread | raw e-mail | index | archive | help
>Number: 32372 >Category: ports >Synopsis: Broken timezone specification generated by Bulkmail.pm >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Nov 28 21:50:01 PST 2001 >Closed-Date: >Last-Modified: >Originator: David Wolfskill >Release: FreeBSD 4.1.1-STABLE i386 >Organization: Whistle Communications >Environment: Use the /usr/ports/mail/p5-Mail-Bulkmail (Mail::Bulkmail) port. >Description: The Bulkmail.pm module generates its own Date: header for the messages it sends. One of the fields in the Date: header is the time specification, which includes a "timezone" specification, which denotes the number of hours and minutes the time in question is offset from UTC (GMT), as well as the direction of that offset. The module has a function ("Tz", starting at line 703) to compute the above-mentioned offset. The function will, under some circumstances, produce and return values that are not within the range -1200 to +1200, and has the (slight!) possibility of returning a value that is otherwise incorrect. (This latter is highly improbable, but easily fixed.) The Tz() function works by using the "hours" and "minutes" part of the current time; in particular, it examines and uses the difference between the "localtime()" and the "gmtime()" results. There are some problems, though: * There is code to check to see if the magnitude of the difference exceeds 12 hours. However, in such a case, the result is adjusted by 12 hours, rather than the 24 hours that would be correct. (For example, sending a message at 1703 hrs. local time, from a time zone that is 8 hrs. west of GMT -- so that the time in question is 0103 hrs. UTC/GMT the following day -- would yield a difference of 16 hrs. Since this is >12, the code then subtracts that difference (16) from 12, yielding -4. Rather, the code should subtract 24 from the difference in the ">12" case, yielding -8 hrs., which is correct.) * Even though the "difference" is "corrected" (albeit incorrectly, per the above), there is a sprintf() call immediately afterward that clobbers the "correction" anyway, so the reported offset in the above example will be "1600", which is outside the range of -1200 to +1200. Note that the extent to which this result will be in error depends on the magnitude of the offset between local time and UTC/GMT, as well as the time of day of the experiment. * There is no provision to ensure that an offset that has a non-zero "minutes" component actually has the direction of the minutes component that agrees with the direction of the hours component. (For 0- or 30-minute offsets, this isn't likely to matter much.) * Finally, the exceedingly improbable error is caused by the use of two *different* calls to Perl's time() function (one for the localtime() call; the other for the gmtime() call). It is possible, though (very!) unlikely that the two calls will be made at times such that the results could be on either side of a minute (or even hour) boundary. The cure for this is to invoke time() but once, save the value, and use that for each of the localtime() and gmtime() calls. >How-To-Repeat: Well, here are the salient headers from an example such as the one described above: Received: from us.ibm.com (pau-amma.whistle.com [207.76.205.64]) by gatekeeper.whistle.com (8.11.1/8.11.1) with SMTP id fAS13NE20829 for <dhw@whistle.com>; Tue, 27 Nov 2001 17:03:23 -0800 (PST) Message-Id: <200111280103.fAS13NE20829@gatekeeper.whistle.com> Date: Tue, 27 Nov 2001 17:03:23 +1600 Note the timezone specification in the Date: header vs. that in the Received: header. Had this been done between 0000 - 1559 hrs. PST (8 hrs. west of GMT), the error would not have been apparent. >Fix: Apply the following patch to Bulkmail.pm: --- Bulkmail.pm.orig Fri Sep 7 12:28:16 2001 +++ Bulkmail.pm Wed Nov 28 07:27:50 2001 @@ -704,16 +704,31 @@ my $self = shift or undef; - my ($min, $hour, $isdst) = (localtime(time))[1,2,-1]; - my ($gmin, $ghour, $gsdst) = (gmtime(time))[1,2, -1]; + my $now = time; + my ($min, $hour, $isdst) = (localtime($now))[1,2,-1]; + my ($gmin, $ghour, $gsdst) = (gmtime($now))[1,2, -1]; - my $diffhour = $hour - $ghour; - $diffhour = 12 - $diffhour if $diffhour > 12; - $diffhour = 12 + $diffhour if $diffhour < -12; + my $diffmin = ($hour - $ghour) * 60 + ($min - $gmin); + my $diffhour = int($diffmin / 60); + $diffmin -= $diffhour * 60; + if ($diffhour > 12) { + $diffhour -= 24; + if ($diffmin) { + $diffhour += 1; + $diffmin -= 60; + } + } elsif ($diffhour < -12) { + $diffhour += 24; + if ($diffmin) { + $diffhour -= 1; + $diffmin += 60; + } + } + $diffmin = abs($diffmin); - ($diffhour = sprintf("%03d", $hour - $ghour)) =~ s/^0/\+/; + ($diffhour = sprintf("%03d%02d", $diffhour, $diffmin)) =~ s/^0/\+/; - return $diffhour . sprintf("%02d", $min - $gmin); + return $diffhour; }; >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200111290542.fAT5gsg16522>