Bug 260137

Summary: mail/heirloom-mailx: wrong UTC offset in Date header for Europe/Dublin
Product: Ports & Packages Reporter: Andrea Biardi <a.biardi>
Component: Individual Port(s)Assignee: Cy Schubert <cy>
Status: Closed FIXED    
Severity: Affects Some People Flags: bugzilla: maintainer-feedback? (cy)
cy: merge-quarterly+
Priority: ---    
Version: Latest   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
correct calculation of GMT/UTC offset none

Description Andrea Biardi 2021-11-30 10:28:34 UTC
Created attachment 229808 [details]
correct calculation of GMT/UTC offset

I am reporting this bug with the following disclaimer:
- I am aware that the default /bin/mail is from a different package, and probably not many people would install the heirloom-mailx port.
- I understand heirloom mailx is no longer maintained upstream, hence no chance of getting a patch accepted upstream (I have submitted a patch to its successor s-nail, whose current code now behaves correctly).

The problem is that sending out an email using Heirloom mailx produces a "Date:" header that is incorrect when the system is in the Europe/Dublin timezone (email appears to have been sent 2 hours earlier).

My testcase is as follows (forgive a bit of dark magic here):

root@mybsd:~ # make -C /usr/ports/mail/heirloom-mailx/ all install clean PREFIX=/test
[...]

root@mybsd:~ # date -R
Mon, 29 Nov 2021 18:59:29 +0000

root@mybsd:~ # rm -f ~/dead.letter; env TZ=Europe/Dublin /test/bin/mailx -S sendmail=no-thank-you root < /dev/null; cat ~/dead.letter
No message, no subject; hope that's ok
no-thank-you: No such file or directory
"/root/dead.letter" 8/195
. . . message not sent.
Date: Mon, 29 Nov 2021 18:59:29 +0200
To: root
User-Agent: Heirloom mailx 12.4 7/29/08
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

=

The "Date:" header is wrong (compare with "date -R) because of a naive/incorrect handling of tm->tm_isdst that assumes that DST implies +1h. It turns out that this is not necessarily a correct assumption.

A patch is attached. In the interest of readability, I've tried not to be too clever about optimizing out unnecessary variables, etc. (incidentally, the latest version of heirloom mailx is 12.5; I'm not sure where the official sources are now kept, but both https://ftp.debian.org/debian/pool/main/h/heirloom-mailx/heirloom-mailx_12.5.orig.tar.gz  and https://mirrors.kernel.org/slackware/slackware64-14.2/source/n/mailx/mailx-12.5.tar.xz look authentic to me; the latter is slightly more recent).

The rest of the text below provides background and context info that might be useful to others in the future.

Somewhere around 2018, the tzdata maintainers (IANA) corrected a historical mistake with the Europe/Dublin timezone. The mistake was rooted in a misunderstanding of whether IST meant "Irish Summer Time" or "Irish Standard Time".

The problem was discussed at great length (http://mm.icann.org/pipermail/tz/2018-January/thread.html) and it was concluded that IST really meant Irish *Standard* Time (in constrast with, say, British *Summer* Time), and that this standard time is defined as UTC+0100.

This corresponds to the article at https://en.wikipedia.org/wiki/Time_in_the_Republic_of_Ireland and the notes at https://en.wikipedia.org/wiki/Winter_time_(clock_lag); the source archive of tzdata has a long section dedicated to this problem and a large set of official references and links to www.irishstatutebook.ie.

Once the question was settled, the only possible solution for keeping the Irish local time in sync with the rest of the world (timezones aside, the local time in Ireland - as understood by common people - is the same as in London and Belfast) was for IANA to _reverse_ the functioning of the DST flag for Ireland. The result is that in the current IANA timezone database (2021e), Europe/Dublin has DST applied in *winter*, with an adjustment of -1h (that is, negative).

Digging deeper, one uncovers that there are a few other countries that have (or once had) the same time-switch mechanism as Ireland; amongst others, https://github.com/MenoData/Time4J/issues/742 also concedes that negative DST is a reality.

In heirloom mailx, the logic that works out the UTC offset does the right thing up to a point (November 2021, Ireland = UTC+0100), but then upon inspecting tm->tm_isdst it sees that DST is in effect (remember, flag has been reversed, so DST in Ireland is on in winter time) it adds one hour (it should subtract one, because the adjustment is negative, but mailx doesn't know).

That's why I get a +0200 instead of +0000 out of mailx.

You may wonder why this problem hasn't been noticed by Irish people in the past three years (hey, there's quite an IT industry over here!).

It turns out that the introduction of a negative DST adjustment caused all sorts of bugs back in 2018 (mostly with Java); in the source distribution of IANA's tzdata, one can spot this inside ./europe:

  # In January 2018 we discovered that the negative SAVE values in the
  # Eire rules cause problems with tests for ICU [...] and with tests
  # for OpenJDK [...]
  # To work around this problem, the build procedure can translate the
  # following data into two forms, one with negative SAVE values and the
  # other form with a traditional approximation for Irish timestamps
  # after 1971-10-31 02:00 UTC; although this approximation has tm_isdst
  # flags that are reversed, its UTC offsets are correct and this often
  # suffices. [...]

So, a temporary hack was put in place so that downstream maintainers could choose whether to retain the old broken convention of IST and support buggy software ("make DATAFORM=rearguard"), but it is clear that the current (and technically, and politically, correct) implementation of a negative DST adjustment for Ireland is there to stay (for example, see "PS." under: https://mm.icann.org/pipermail/tz-announce/2019-March/000055.html).

FreeBSD is using the correct tzdata representation (aka "vanguard") which exposes the bug in mailx.

The solution boils down to correctly calculating the offset between local time and UTC. Having studied the way this is done in a couple of other programs (for example, postfix) I have concluded that although manual calculation is the only portable approach, perhaps the best way to address this is to use tm->tm_gmtoff. I know it is a non-standard extension, but I believe it's been there in BSD and GNU's glibc for over a decade and there's little reason to reinvent the wheel.
Comment 1 Cy Schubert freebsd_committer freebsd_triage 2022-01-27 01:17:40 UTC
In other words DST means the opposite for Europe/Dublin.
Comment 2 commit-hook freebsd_committer freebsd_triage 2022-01-27 02:38:31 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/ports/commit/?id=c4f80928aed6891068ad6cf9be8c4aaff2a62e24

commit c4f80928aed6891068ad6cf9be8c4aaff2a62e24
Author:     Andrea Biardi <a.biardi@tiscali.it>
AuthorDate: 2022-01-27 02:29:51 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2022-01-27 02:36:59 +0000

    mail/heirloom-mailx: Fix wrong UTC offset for Europe/Dublin

    Somewhere around 2018, the tzdata maintainers (IANA) corrected a
    historical mistake with the Europe/Dublin timezone. The mistake was
    rooted in a misunderstanding of whether IST meant "Irish Summer Time"
    or "Irish Standard Time".

    The problem was discussed at great length
    (http://mm.icann.org/pipermail/tz/2018-January/thread.html) and it was
    concluded that IST really meant Irish *Standard* Time (in constrast with,
    say, British *Summer* Time), and that this standard time is defined as
    UTC+0100.

    This corresponds to the article at
    https://en.wikipedia.org/wiki/Time_in_the_Republic_of_Ireland and the
    notes at https://en.wikipedia.org/wiki/Winter_time_(clock_lag); the
    source archive of tzdata has a long section dedicated to this problem and
    a large set of official references and links to www.irishstatutebook.ie.

    Once the question was settled, the only possible solution for keeping
    the Irish local time in sync with the rest of the world (timezones aside,
    the local time in Ireland - as understood by common people - is the same
    as in London and Belfast) was for IANA to _reverse_ the functioning of
    the DST flag for Ireland. The result is that in the current IANA timezone
    database (2021e), Europe/Dublin has DST applied in *winter*, with an
    adjustment of -1h (that is, negative).

    Digging deeper, one uncovers that there are a few other countries that
    have (or once had) the same time-switch mechanism as Ireland; amongst
    others, https://github.com/MenoData/Time4J/issues/742 also concedes that
    negative DST is a reality.

    In heirloom mailx, the logic that works out the UTC offset does the right
    thing up to a point (November 2021, Ireland = UTC+0100), but then upon
    inspecting tm->tm_isdst it sees that DST is in effect (remember, flag has
    been reversed, so DST in Ireland is on in winter time) it adds one hour
    (it should subtract one, because the adjustment is negative, but mailx
    doesn't know).

    PR:             260137
    Submitted by:   Andrea Biardi <a.biardi@tiscali.it>
    Reported by:    Andrea Biardi <a.biardi@tiscali.it>
    MFH:            2022Q1

 mail/heirloom-mailx/Makefile                 |  2 +-
 mail/heirloom-mailx/files/patch-head.c (new) | 14 +++++++++++++
 mail/heirloom-mailx/files/patch-imap.c (new) | 30 +++++++++++++++++++++++++++
 mail/heirloom-mailx/files/patch-sendout.c    | 31 ++++++++++++++++++++++++++--
 4 files changed, 74 insertions(+), 3 deletions(-)
Comment 3 commit-hook freebsd_committer freebsd_triage 2022-01-27 05:10:53 UTC
A commit in branch 2022Q1 references this bug:

URL: https://cgit.FreeBSD.org/ports/commit/?id=4f66dd04e532307bfe9ce8c80454b4e530d5bcd8

commit 4f66dd04e532307bfe9ce8c80454b4e530d5bcd8
Author:     Andrea Biardi <a.biardi@tiscali.it>
AuthorDate: 2022-01-27 02:29:51 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2022-01-27 02:43:09 +0000

    mail/heirloom-mailx: Fix wrong UTC offset for Europe/Dublin

    Somewhere around 2018, the tzdata maintainers (IANA) corrected a
    historical mistake with the Europe/Dublin timezone. The mistake was
    rooted in a misunderstanding of whether IST meant "Irish Summer Time"
    or "Irish Standard Time".

    The problem was discussed at great length
    (http://mm.icann.org/pipermail/tz/2018-January/thread.html) and it was
    concluded that IST really meant Irish *Standard* Time (in constrast with,
    say, British *Summer* Time), and that this standard time is defined as
    UTC+0100.

    This corresponds to the article at
    https://en.wikipedia.org/wiki/Time_in_the_Republic_of_Ireland and the
    notes at https://en.wikipedia.org/wiki/Winter_time_(clock_lag); the
    source archive of tzdata has a long section dedicated to this problem and
    a large set of official references and links to www.irishstatutebook.ie.

    Once the question was settled, the only possible solution for keeping
    the Irish local time in sync with the rest of the world (timezones aside,
    the local time in Ireland - as understood by common people - is the same
    as in London and Belfast) was for IANA to _reverse_ the functioning of
    the DST flag for Ireland. The result is that in the current IANA timezone
    database (2021e), Europe/Dublin has DST applied in *winter*, with an
    adjustment of -1h (that is, negative).

    Digging deeper, one uncovers that there are a few other countries that
    have (or once had) the same time-switch mechanism as Ireland; amongst
    others, https://github.com/MenoData/Time4J/issues/742 also concedes that
    negative DST is a reality.

    In heirloom mailx, the logic that works out the UTC offset does the right
    thing up to a point (November 2021, Ireland = UTC+0100), but then upon
    inspecting tm->tm_isdst it sees that DST is in effect (remember, flag has
    been reversed, so DST in Ireland is on in winter time) it adds one hour
    (it should subtract one, because the adjustment is negative, but mailx
    doesn't know).

    PR:             260137
    Submitted by:   Andrea Biardi <a.biardi@tiscali.it>
    Reported by:    Andrea Biardi <a.biardi@tiscali.it>
    MFH:            2022Q1

    (cherry picked from commit c4f80928aed6891068ad6cf9be8c4aaff2a62e24)

 mail/heirloom-mailx/Makefile                 |  2 +-
 mail/heirloom-mailx/files/patch-head.c (new) | 14 +++++++++++++
 mail/heirloom-mailx/files/patch-imap.c (new) | 30 +++++++++++++++++++++++++++
 mail/heirloom-mailx/files/patch-sendout.c    | 31 ++++++++++++++++++++++++++--
 4 files changed, 74 insertions(+), 3 deletions(-)
Comment 4 Cy Schubert freebsd_committer freebsd_triage 2022-01-27 05:12:23 UTC
Committed. Thanks for the patch.