Fix some problems with negative and out-of-range integers.
Original problem reported for HP-UX LVM v2.2 by Michael White in <http://lists.gnu.org/archive/html/bug-tar/2012-10/msg00000.html>. This patch fixes some other gotchas that I noticed. * gnulib.modules: Add extern-inline. * src/common.h: Use _GL_INLINE_HEADER_BEGIN, _GL_INLINE_HEADER_END. (COMMON_INLINE, max, min): New macros. (represent_uintmax, valid_timespec): New inline functions. (SYSINT_BUFSIZE): New constant. (sysinttostr, strtosysint, decode_timespec): New decls. * src/create.c (start_private_header): Silently bring the time_t value into range; it is now the caller's responsibility to deal with any overflow error. Use uid 0 and gid 0 rather than the user's uid/gid, since the faked header isn't "owned" by the user and the uid/gid could in theory be out of range. Leave major and minor zeroed. (FILL): Remove. (write_gnu_long_link): Let start_private_header zero things out. * src/create.c (write_gnu_long_link, write_extended): * src/xheader.c (xheader_write_global): Use start_time, not current time; no point hammering on the clock. * src/compare.c (diff_multivol): Check that offset, size are in range. * src/incremen.c (read_incr_db_01, write_directory_file_entry): Allow negative time_t, dev_t, and ino_t. * src/list.c (max): Remove (moved to common.h). (read_header): Check that size is in range. (from_header): Return intmax_t, not uintmax_t, to allow negative. All callers changed. At compile time, check assumptions about intmax_t and uintmax_t. Use bool for booleans. Avoid overflow hassles on picky hosts. (mode_from_header): Last arg is now bool *, not unsigned *. All callers changed. (simple_print_header): Do not assume UID, GID fit in 'long'. * src/list.c (from_header): * src/xheader.c (out_of_range_header): Arg is now a plain minimum value, not minus minval converted to uintmax_t. All callers changed. * src/misc.c (COMMON_INLINE): New macro. (sysinttostr, strtosysint, decode_timespec): New functions. * src/sparse.c (oldgnu_add_sparse, oldgnu_fixup_header) (star_fixup_header): Check for offset overflow. (decode_num): Clear errno before calling strtoumax. * src/tar.c (expand_pax_option): Don't discard nanoseconds. * src/xheader.c (assign_time_option): Allow negative time_t. (decode_record): Simplify, since out-of-range string is guaranteed to produce a value exceeding len_max. (xheader_read): Last arg is off_t, not size_t. Caller should diagnose negative arg, as needed. Check that it's in range. (enum decode_time_status): Remove. (_decode_time): Remove, folding into decode_time. (decode_time): Return bool, not enum decode_time_status. Rely on decode_timespec to do most of the work. (code_signed_num): New function. (code_num): Use it. (decode_signed_num): New function. (decode_num): Use it. (gid_coder, gid_decoder, uid_coder, uid_decoder, sparse_map_decoder) (sparse_map_decoder): Code and decode negative values. (sparse_map_decoder): Improve check for out-of-range values. * tests/time01.at: New file. * tests/Makefile.am (TESTSUITE_AT): Add it. * tests/testsuite.at: Include it.
This commit is contained in:
@@ -157,6 +157,7 @@ TESTSUITE_AT = \
|
||||
spmvp00.at\
|
||||
spmvp01.at\
|
||||
spmvp10.at\
|
||||
time01.at\
|
||||
truncate.at\
|
||||
update.at\
|
||||
update01.at\
|
||||
|
||||
@@ -284,6 +284,8 @@ m4_include([lustar01.at])
|
||||
m4_include([lustar02.at])
|
||||
m4_include([lustar03.at])
|
||||
|
||||
m4_include([time01.at])
|
||||
|
||||
m4_include([multiv01.at])
|
||||
m4_include([multiv02.at])
|
||||
m4_include([multiv03.at])
|
||||
@@ -357,4 +359,3 @@ m4_include([star/ustar-big-2g.at])
|
||||
m4_include([star/ustar-big-8g.at])
|
||||
|
||||
m4_include([star/pax-big-10g.at])
|
||||
|
||||
|
||||
70
tests/time01.at
Normal file
70
tests/time01.at
Normal file
@@ -0,0 +1,70 @@
|
||||
# Test time stamps for GNU tar. -*- Autotest -*-
|
||||
#
|
||||
# Copyright 2012 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, 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/>.
|
||||
|
||||
# written by Paul Eggert
|
||||
|
||||
AT_SETUP([time: tricky time stamps])
|
||||
AT_KEYWORDS([time time01])
|
||||
|
||||
AT_TAR_CHECK([
|
||||
export TZ=UTC0
|
||||
mkdir dir
|
||||
|
||||
# Test files with time stamps that are near common sources of error,
|
||||
# typically near powers of 2 (for seconds) or near 0, 1970, or 9999 (years).
|
||||
# Use GNU-style @ notation for very large time stamps, since they
|
||||
# typically don't render into years correctly due to int overflow.
|
||||
for s in \
|
||||
@-9223372036854775809 @-9223372036854775808 @-9223372036854775807 \
|
||||
0000-01-01T00:00:00 0000-01-01T00:00:01 \
|
||||
0000-01-02T00:00:00 \
|
||||
1697-10-17T11:03:27 1697-10-17T11:03:28 1697-10-17T11:03:29 \
|
||||
1833-11-24T17:31:43 1833-11-24T17:31:44 1833-11-24T17:31:45 \
|
||||
1901-12-13T20:45:51 1901-12-13T20:45:52 1901-12-13T20:45:53 \
|
||||
1901-12-14T20:45:51 \
|
||||
1969-12-31T23:59:58 1969-12-31T23:59:59 \
|
||||
1970-01-01T00:00:00 1970-01-01T00:00:01 \
|
||||
2038-01-18T03:14:07 \
|
||||
2038-01-19T03:14:07 2038-01-19T03:14:08 \
|
||||
2106-02-07T06:28:15 2106-02-07T06:28:16 \
|
||||
2242-03-16T12:56:31 2242-03-16T12:56:32 \
|
||||
9999-12-31T23:59:58 9999-12-31T23:59:59 \
|
||||
@9223372036854775807 @9223372036854775808
|
||||
do
|
||||
# Skip a time stamp $s if it's out of range for this platform,
|
||||
# of if it uses a notation that this platform does not recognize.
|
||||
touch -d $s dir/f$s >/dev/null 2>&1 || continue
|
||||
|
||||
# Likewise for $s.1. If $s is the most negative time stamp and
|
||||
# time stamps are signed, then $s.1 is out of range.
|
||||
touch -d $s.1 dir/f$s.$ns >/dev/null 2>&1 || continue
|
||||
|
||||
for frac in 01 001 00001 000001 0000001 00000001 000000001 0000000001 \
|
||||
9 99 999 99999 999999 9999999 99999999 999999999 9999999999
|
||||
do
|
||||
touch -d $s.$frac dir/f$s.$frac
|
||||
done
|
||||
done
|
||||
|
||||
tar -c -f archive.tar dir
|
||||
tar -d -f archive.tar dir
|
||||
],
|
||||
[0],
|
||||
[], [], [], [],
|
||||
[pax])
|
||||
|
||||
AT_CLEANUP
|
||||
Reference in New Issue
Block a user