This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug time/16141] strptime %z offset restriction


https://sourceware.org/bugzilla/show_bug.cgi?id=16141

--- Comment #7 from cvs-commit at gcc dot gnu.org <cvs-commit at gcc dot gnu.org> ---
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  be13f5a4baa40af3611208edc77fd588ff2c0fab (commit)
       via  cccc95f28ace0be4fe97537dbd867c08fbf71a8e (commit)
      from  315267abcd2eeb467820a3fada43874e35bbcd3d (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=be13f5a4baa40af3611208edc77fd588ff2c0fab

commit be13f5a4baa40af3611208edc77fd588ff2c0fab
Author: James Perkins <james@loowit.net>
Date:   Mon Aug 17 13:48:39 2015 -0700

    time/tst-strptime2.c: test full input range +/- 0-9999

    strptime's %z specifier parses a string consisting of a sign ('+'
    or '-'), two hours digits, and optionally two minutes digits, into a
    tm.tm_gmtoff field containing the signed number of seconds the time
    zone is offset from UTC time.

    The time/tst-strptime2.c program passes a short list of strings through
    strptime, validating that either the gmtoff value returned matches an
    expected value, or that strptime returns an expected NULL for invalid
    strings (for example, when the minutes portion of the string is outside
    of the range 00 to 59, or the sign is missing before the hours digits).

    In review of strptime fixes, Carlos O'Donell expressed a wish that
    the test function iterate through the entire range of all possible
    numeric strings (-9999 to +9999) which could be passed to strptime %z,
    and validate the correct response.

    Specifically, the test will look for a NULL response from strptime
    when:

      * sign ('+' or '-') is not present before the first digit (invalid
        format).
      * A sign and no digits are found (invalid format).
      * A sign and one digit are found (invalid format).
      * A sign and three digits are found (invalid format).
      * A sign and four digits (-9999 to +9999) are found but the last
        two digits (minutes) are in the range 60 to 99.

    The test will look for a success response from strptime with
    tm.tm_gmtoff matching the calculated tm_gmtoff value when:

      * A sign and four digits are found (-9999 to +9999), and the last
        two digits (minutes) are in the range 00 to 59.
      * A sign and two digit strings are found (-99 to +99).

    The test's iteration over the possible digit values results in 22223
    test strings prepared, tested, and passed by strptime.

    The test supports a --verbose command line option which will show
    the test results of every test input, and a final summary of all
    tests. Here is some sample output:

      PASS: input "1113472456  1030", expected: invalid, return value NULL
      PASS: input "1113472456 +", expected: invalid, return value NULL
      PASS: input "1113472456 -", expected: invalid, return value NULL
      PASS: input "1113472456 +0", expected: invalid, return value NULL
      PASS: input "1113472456 -0", expected: invalid, return value NULL
      PASS: input "1113472456 +1", expected: invalid, return value NULL
      ...
      PASS: input "1113472456 +9", expected: invalid, return value NULL
      PASS: input "1113472456 -9", expected: invalid, return value NULL
      PASS: input "1113472456 +00", expected: valid, tm.tm_gmtoff 0
      PASS: input "1113472456 -00", expected: valid, tm.tm_gmtoff 0
      PASS: input "1113472456 +01", expected: valid, tm.tm_gmtoff 3600
      PASS: input "1113472456 -01", expected: valid, tm.tm_gmtoff -3600
      PASS: input "1113472456 +02", expected: valid, tm.tm_gmtoff 7200
      ...
      PASS: input "1113472456 +99", expected: valid, tm.tm_gmtoff 356400
      PASS: input "1113472456 -99", expected: valid, tm.tm_gmtoff -356400
      PASS: input "1113472456 +000", expected: invalid, return value NULL
      PASS: input "1113472456 -000", expected: invalid, return value NULL
      PASS: input "1113472456 +001", expected: invalid, return value NULL
      ...
      PASS: input "1113472456 +999", expected: invalid, return value NULL
      PASS: input "1113472456 -999", expected: invalid, return value NULL
      PASS: input "1113472456 +0000", expected: valid, tm.tm_gmtoff 0
      PASS: input "1113472456 -0000", expected: valid, tm.tm_gmtoff 0
      PASS: input "1113472456 +0001", expected: valid, tm.tm_gmtoff 60
      PASS: input "1113472456 -0001", expected: valid, tm.tm_gmtoff -60
      ...
      PASS: input "1113472456 +0059", expected: valid, tm.tm_gmtoff 3540
      PASS: input "1113472456 -0059", expected: valid, tm.tm_gmtoff -3540
      PASS: input "1113472456 +0060", expected: invalid, return value NULL
      PASS: input "1113472456 -0060", expected: invalid, return value NULL
      ...
      PASS: input "1113472456 +0099", expected: invalid, return value NULL
      PASS: input "1113472456 -0099", expected: invalid, return value NULL
      PASS: input "1113472456 +0100", expected: valid, tm.tm_gmtoff 3600
      PASS: input "1113472456 -0100", expected: valid, tm.tm_gmtoff -3600
      PASS: input "1113472456 +0101", expected: valid, tm.tm_gmtoff 3660
      ...
      PASS: input "1113472456 +9999", expected: invalid, return value NULL
      PASS: input "1113472456 -9999", expected: invalid, return value NULL
      PASS: 22223 input strings: 0 fail, 22223 pass

    Any failing test will result in printing the failed line to stdout, and
    will trigger the printing of the summary line at the of all tests. For
    example:

      FAIL: input "1113472456  1030", expected: invalid, return value NULL,
        got: valid, tm.tm_gmtoff 37800
      FAIL: 22223 input strings: 1 fail, 22222 pass

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=cccc95f28ace0be4fe97537dbd867c08fbf71a8e

commit cccc95f28ace0be4fe97537dbd867c08fbf71a8e
Author: James Perkins <james@loowit.net>
Date:   Mon Aug 17 13:48:38 2015 -0700

    strptime %z: fix rounding, extend range to +/-9959 [BZ #16141]

    Topic: strptime supports a %z input field descriptor, which parses a
    time zone offset from UTC time into the broken-out time field tm_gmtoff.

    Problems:

    1) In the current implementation, the minutes portion calculation is
    correct only for minutes evenly divisible by 3. This is because the
    minutes value is converted to decimal time, but inadequate precision
    leads to rounding which calculates results that are too low for
    some values.

    For example, due to rounding, a +1159 offset string results in an
    incorrect tm_gmtoff of 43128 (== 11 * 3600 + 58.8 * 60) seconds,
    instead of 43140 (== 11 * 3600 + 59 * 60) seconds. In contrast,
    a +1157 offset (minutes divisible by 3) does not cause the bug,
    and results in a correct tm_gmtoff of 43020.

    2) strptime's %z specifier will not parse time offsets less than
    -1200 or greater than +1200, or if only hour digits are present, less
    than -12 or greater than +12. It will return NULL for offsets outside
    that range. These limits do not meet historical and modern use cases:

      * Present day exceeds the +1200 limit:
        - Pacific/Auckland (New Zealand) summer time is +1300.
        - Pacific/Kiritimati (Christmas Island) is +1400.
        - Pacific/Apia (Samoa) summer time is +1400.
      * Historical offsets exceeded +1500/-1500.
      * POSIX supports -2459 to +2559.
      * Offsets up to +/-9959 may occasionally be useful.
      * Paul Eggert's notes provide additional detail:
        - https://sourceware.org/ml/libc-alpha/2014-12/msg00068.html
        - https://sourceware.org/ml/libc-alpha/2014-12/msg00072.html

    3) tst-strptime2, part of the 'make check' test suite, does not test
    for the above problems.

    Corrective actions:

    1) In time/strptime_l.c, calculate the offset from the hour and
    minute portions directly, without the rounding errors introduced by
    decimal time.

    2) Remove the +/-1200 range limit, permitting strptime to parse offsets
    from -9959 through +9959.

    3) Add zone offset values to time/tst-strptime2.c.

      * Test minutes evenly divisible by three (+1157) and not evenly
        divisible by three (+1158 and +1159).
      * Test offsets near the old and new range limits (-1201, -1330, -2459,
        -2500, -99, -9959, +1201, +1330, +1400, +1401, +2559, +2600, +99,
        and +9959)

    The revised strptime passes all old and new tst-strptime2 tests.

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog            |   21 +++++
 NEWS                 |    8 +-
 time/strptime_l.c    |   12 +--
 time/tst-strptime2.c |  214 +++++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 206 insertions(+), 49 deletions(-)

-- 
You are receiving this mail because:
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]