When decompressing data in 'pack' format, gzip no longer mishandles
leading zeros in the end-of-block code. [bug introduced in gzip-1.6]
- When converting timestamps to gzip file format (32-bit unsigned) or
- to time_t format (system-dependent), gzip now ignores out-of-range
- values instead of shoehorning them into the destination format,
- sometimes with undefined behavior. This affects timestamps before
+ When converting from system-dependent time_t format to the 32-bit
+ unsigned MTIME format used in gzip files, if a timestamp does not
+ fit gzip now substitutes zero instead of the timestamp's low-order
+ 32 bits, as per Internet RFC 1952. When converting from MTIME to
+ time_t format, if a timestamp does not fit gzip now warns and
+ substitutes the nearest in-range value instead of crashing or
+ silently substituting an implementation-defined value (typically,
+ the timestamp's low-order bits). This affects timestamps before
1970 and after 2106, and timestamps after 2038 on platforms with
32-bit signed time_t. [bug present since the beginning]
static char const *z_suffix; /* default suffix (can be set with --suffix) */
static size_t z_len; /* strlen(z_suffix) */
-/* The original timestamp (modification time). Its tv_nsec component
- is negative if the original time is unknown or is out of time_t
- range; the latter can happen on hosts with 32-bit signed time_t
- because the gzip format's MTIME is 32-bit unsigned. */
+/* The original timestamp (modification time). If the original is
+ unknown, TIME_STAMP.tv_nsec is negative. If the original is
+ greater than struct timespec range, TIME_STAMP is the maximal
+ struct timespec value; this can happen on hosts with 32-bit signed
+ time_t because the gzip format's MTIME is 32-bit unsigned.
+ The original cannot be less than struct timespec range. */
struct timespec time_stamp;
/* The set of signals that are caught. */
stamp |= ((ulg)get_byte()) << 8;
stamp |= ((ulg)get_byte()) << 16;
stamp |= ((ulg)get_byte()) << 24;
- if (!no_time && 0 < stamp && stamp <= TYPE_MAXIMUM (time_t))
+ 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));
+ time_stamp.tv_sec = TYPE_MAXIMUM (time_t);
+ time_stamp.tv_nsec = TIMESPEC_RESOLUTION - 1;
+ }
}
magic[8] = get_byte (); /* Ignore extra flags. */
static char const month_abbr[][4]
= { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- struct tm *tm = (time_stamp.tv_nsec < 0
- ? NULL
- : localtime (&time_stamp.tv_sec));
+ struct tm *tm = localtime (&time_stamp.tv_sec);
printf ("%5s %08lx ", methods[method], crc);
if (tm)
printf ("%s%3d %02d:%02d ", month_abbr[tm->tm_mon],