* NEWS: Document this. * gzip.c (get_method): Warn about out-of-range MTIME, and ignore it instead of relying on possibly-undefined behavior. * tests/Makefile.am (TESTS): Add timestamp. * tests/timestamp: New test. * zip.c (zip): Warn about out-of-range file time stamp. --- NEWS | 6 ++++++ gzip.c | 11 +++++++++-- tests/Makefile.am | 1 + tests/timestamp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ zip.c | 12 +++++++++--- 5 files changed, 77 insertions(+), 5 deletions(-) create mode 100755 tests/timestamp
diff --git a/NEWS b/NEWS index 8c81f5c..6532550 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,12 @@ GNU gzip NEWS -*- outline -*- ** Bug fixes + gzip now warns about file time stamps out of gzip range, or out of + time_t range, instead of silently continuing, sometimes with + undefined behavior. This affects time stamps before 1970 or after + 2106, and time stamps after 2038 on 32-bit platforms. + [bug present since the beginning] + Support for VMS and Amiga has been removed. It was not working anyway, and it reportedly caused file name glitches on MS-Windowsish platforms. diff --git a/gzip.c b/gzip.c index 0d0953c..0fca5a3 100644 --- a/gzip.c +++ b/gzip.c @@ -1537,8 +1537,15 @@ local int get_method(in) stamp |= ((ulg)get_byte()) << 24; if (stamp != 0 && !no_time) { - time_stamp.tv_sec = stamp; - time_stamp.tv_nsec = 0; + if (stamp <= TYPE_MAXIMUM (time_t)) + { + time_stamp.tv_sec = stamp; + time_stamp.tv_nsec = 0; + } + else + WARN ((stderr, + "%s: %s: MTIME %lu out of range for this platform\n", + program_name, ifname, stamp)); } magic[8] = get_byte (); /* Ignore extra flags. */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 71cf4ad..1c24886 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,6 +25,7 @@ TESTS = \ mixed \ null-suffix-clobber \ stdin \ + timestamp \ trailing-nul \ unpack-invalid \ z-suffix \ diff --git a/tests/timestamp b/tests/timestamp new file mode 100755 index 0000000..c488760 --- /dev/null +++ b/tests/timestamp @@ -0,0 +1,52 @@ +#!/bin/sh +# Exercise timestamps. + +# Copyright 2016 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# limit so don't run it by default. + +. "${srcdir=.}/init.sh"; path_prepend_ .. + +TZ=UTC0 +export TZ + +# On platforms supporting time stamps outside gzip's range, +# test that gzip warns when converting them to gzip format. +for time in 190101010000 196912312359.59 197001010000 210602070628.16; do + if touch -t $time in; then + gzip in + test $? = 2 || fail=1 + fi + rm -f in in.gz +done + +# Test that time stamps in range for gzip do not generate warnings. +for time in 197001010000.01 203801190314.07 203801190314.08 210602070628.15; do + if touch -t $time in; then + gzip in || fail=1 + fi + rm -f in in.gz +done + +# On platforms that fail to support time stamps within gzip's range, +# test that gzip warns when converting them from gzip format. +touch -t 210602070628.15 in || { + printf '\037\213\10\0\377\377\377\377\0\377\3\0\0\0\0\0\0\0\0\0' >y2106.gz || + framework_failure_ + gzip -Nlv <y2106.gz + test $? = 2 || fail=1 +} + +Exit $fail diff --git a/zip.c b/zip.c index 793cf42..eb60409 100644 --- a/zip.c +++ b/zip.c @@ -54,9 +54,15 @@ int zip(in, out) flags |= ORIG_NAME; } put_byte(flags); /* general flags */ - stamp = (0 <= time_stamp.tv_sec && time_stamp.tv_sec <= 0xffffffff - ? (ulg) time_stamp.tv_sec - : (ulg) 0); + if (0 < time_stamp.tv_sec && time_stamp.tv_sec <= 0xffffffff) + stamp = time_stamp.tv_sec; + else + { + /* It's intended that time stamp 0 generates this warning, + since gzip format reserves 0 for something else. */ + warning ("file time stamp out of range for gzip format"); + stamp = 0; + } put_long (stamp); /* Write deflated file to zip file */ -- 2.7.4