/* Old GNU Format. The sparse file information is stored in the
oldgnu_header in the following manner:
- The header is marked with type 'S'. Its `size' field contains
+ The header is marked with type 'S'. Its 'size' field contains
the cumulative size of all non-empty blocks of the file. The
- actual file size is stored in `realsize' member of oldgnu_header.
+ actual file size is stored in 'realsize' member of oldgnu_header.
- The map of the file is stored in a list of `struct sparse'.
+ The map of the file is stored in a list of 'struct sparse'.
Each struct contains offset to the block of data and its
size (both as octal numbers). The first file header contains
at most 4 such structs (SPARSES_IN_OLDGNU_HEADER). If the map
- contains more structs, then the field `isextended' of the main
- header is set to 1 (binary) and the `struct sparse_header'
+ contains more structs, then the field 'isextended' of the main
+ header is set to 1 (binary) and the 'struct sparse_header'
header follows, containing at most 21 following structs
- (SPARSES_IN_SPARSE_HEADER). If more structs follow, `isextended'
+ (SPARSES_IN_SPARSE_HEADER). If more structs follow, 'isextended'
field of the extended header is set and next next extension header
follows, etc... */
return add_finish;
sp.offset = OFF_FROM_HEADER (s->offset);
sp.numbytes = OFF_FROM_HEADER (s->numbytes);
- if (sp.offset < 0
- || sp.offset + sp.numbytes < 0
+ if (sp.offset < 0 || sp.numbytes < 0
+ || INT_ADD_OVERFLOW (sp.offset, sp.numbytes)
|| file->stat_info->stat.st_size < sp.offset + sp.numbytes
|| file->stat_info->archive_file_size < 0)
return add_fail;
{
/* NOTE! st_size was initialized from the header
which actually contains archived size. The following fixes it */
+ off_t realsize = OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
- file->stat_info->stat.st_size =
- OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
- return true;
+ file->stat_info->stat.st_size = max (0, realsize);
+ return 0 <= realsize;
}
/* Convert old GNU format sparse data to internal representation */
{
/* NOTE! st_size was initialized from the header
which actually contains archived size. The following fixes it */
+ off_t realsize = OFF_FROM_HEADER (current_header->star_in_header.realsize);
file->stat_info->archive_file_size = file->stat_info->stat.st_size;
- file->stat_info->stat.st_size =
- OFF_FROM_HEADER (current_header->star_in_header.realsize);
- return true;
+ file->stat_info->stat.st_size = max (0, realsize);
+ return 0 <= realsize;
}
/* Convert STAR format sparse data to internal representation */
if (!ISDIGIT (*arg))
return false;
+ errno = 0;
u = strtoumax (arg, &arg_lim, 10);
if (! (u <= maxval && errno != ERANGE) || *arg_lim)