Some systems have sizeof(off_t) == 8 while sizeof(size_t) == 4.
This implies that we are able to access and work on files whose
maximum length is around 2^63-1 bytes, but we can only malloc or
mmap somewhat less than 2^32-1 bytes of memory.
On such a system an implicit conversion of off_t to size_t can cause
the size_t to wrap, resulting in unexpected and exciting behavior.
Right now we are working around all gcc warnings generated by the
-Wshorten-64-to-32 option by passing the off_t through xsize_t().
In the future we should make xsize_t on such problematic platforms
detect the wrapping and die if such a file is accessed.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
}
}
else if (patch->old_name) {
- size = st->st_size;
+ size = xsize_t(st->st_size);
alloc = size + 8192;
buf = xmalloc(alloc);
if (read_old_data(st, patch->old_name, &buf, &alloc, &size))
die("Cannot lstat %s", path);
read_from = path;
}
- fin_size = st.st_size;
+ fin_size = xsize_t(st.st_size);
buf = xmalloc(fin_size+1);
mode = canon_mode(st.st_mode);
switch (st.st_mode & S_IFMT) {
if (lstat(path, &st) || !S_ISREG(st.st_mode))
bad = 1;
else
- (*loose_size) += st.st_blocks;
+ (*loose_size) += xsize_t(st.st_blocks);
}
if (bad) {
if (verbose) {
struct stat st;
int i;
char *data;
+ size_t sz;
+
if (lstat(filename, &st) < 0) {
err_ret:
if (errno != ENOENT)
return 0; /* empty file -- no grep hit */
if (!S_ISREG(st.st_mode))
return 0;
+ sz = xsize_t(st.st_size);
i = open(filename, O_RDONLY);
if (i < 0)
goto err_ret;
- data = xmalloc(st.st_size + 1);
- if (st.st_size != read_in_full(i, data, st.st_size)) {
+ data = xmalloc(sz + 1);
+ if (st.st_size != read_in_full(i, data, sz)) {
error("'%s': short read %s", filename, strerror(errno));
close(i);
free(data);
close(i);
if (opt->relative && opt->prefix_length)
filename += opt->prefix_length;
- i = grep_buffer(opt, filename, data, st.st_size);
+ i = grep_buffer(opt, filename, data, sz);
free(data);
return i;
}
goto deleted_file;
if (S_ISLNK(st.st_mode)) {
- size_t len = st.st_size;
+ size_t len = xsize_t(st.st_size);
result_size = len;
result = xmalloc(len + 1);
if (result_size != readlink(elem->path, result, len)) {
}
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
!fstat(fd, &st)) {
- size_t len = st.st_size;
+ size_t len = xsize_t(st.st_size);
size_t sz = 0;
int is_file, i;
int do_not_match;
regex_t* value_regex;
int multi_replace;
- off_t offset[MAX_MATCHES];
+ size_t offset[MAX_MATCHES];
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
int seen;
} store;
return 1;
}
-static int find_beginning_of_line(const char* contents, int size,
- int offset_, int* found_bracket)
+static ssize_t find_beginning_of_line(const char* contents, size_t size,
+ size_t offset_, int* found_bracket)
{
- int equal_offset = size, bracket_offset = size;
- int offset;
+ size_t equal_offset = size, bracket_offset = size;
+ ssize_t offset;
for (offset = offset_-2; offset > 0
&& contents[offset] != '\n'; offset--)
} else {
struct stat st;
char* contents;
- int i, copy_begin, copy_end, new_line = 0;
+ size_t contents_sz, copy_begin, copy_end;
+ int i, new_line = 0;
if (value_regex == NULL)
store.value_regex = NULL;
}
fstat(in_fd, &st);
- contents = xmmap(NULL, st.st_size, PROT_READ,
+ contents_sz = xsize_t(st.st_size);
+ contents = xmmap(NULL, contents_sz, PROT_READ,
MAP_PRIVATE, in_fd, 0);
close(in_fd);
for (i = 0, copy_begin = 0; i < store.seen; i++) {
if (store.offset[i] == 0) {
- store.offset[i] = copy_end = st.st_size;
+ store.offset[i] = copy_end = contents_sz;
} else if (store.state != KEY_SEEN) {
copy_end = store.offset[i];
} else
copy_end = find_beginning_of_line(
- contents, st.st_size,
+ contents, contents_sz,
store.offset[i]-2, &new_line);
/* write the first part of the config */
}
/* write the rest of the config */
- if (copy_begin < st.st_size)
+ if (copy_begin < contents_sz)
if (write_in_full(fd, contents + copy_begin,
- st.st_size - copy_begin) <
- st.st_size - copy_begin)
+ contents_sz - copy_begin) <
+ contents_sz - copy_begin)
goto write_err_out;
- munmap(contents, st.st_size);
+ munmap(contents, contents_sz);
unlink(config_filename);
}
return err;
}
}
- s->size = st.st_size;
+ s->size = xsize_t(st.st_size);
if (!s->size)
goto empty;
if (size_only)
if (S_ISLNK(st.st_mode)) {
int ret;
char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
+ size_t sz = xsize_t(st.st_size);
if (sizeof(buf) <= st.st_size)
die("symlink too long: %s", name);
- ret = readlink(name, buf, st.st_size);
+ ret = readlink(name, buf, sz);
if (ret < 0)
die("readlink(%s)", name);
- prep_temp_blob(temp, buf, st.st_size,
+ prep_temp_blob(temp, buf, sz,
(one->sha1_valid ?
one->sha1 : null_sha1),
(one->sha1_valid ?
/* user says num divided by scale and we say internally that
* is MAX_SCORE * num / scale.
*/
- return (num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale);
+ return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale));
}
int diff_scoreopt_parse(const char *opt)
* merge the surviving pair together if the score is
* less than the minimum, after rename/copy runs.
*/
- *merge_score_p = src_removed * MAX_SCORE / src->size;
+ *merge_score_p = (int)(src_removed * MAX_SCORE / src->size);
/* Extent of damage, which counts both inserts and
* deletes.
void *map;
char *cp, *endp;
struct stat st;
+ size_t sz;
if (order)
return;
close(fd);
return;
}
- map = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+ sz = xsize_t(st.st_size);
+ map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
if (map == MAP_FAILED)
return;
- endp = (char *) map + st.st_size;
+ endp = (char *) map + sz;
for (pass = 0; pass < 2; pass++) {
cnt = 0;
cp = map;
return 0; /* error but caught downstream */
- delta_limit = base_size * (MAX_SCORE-minimum_score) / MAX_SCORE;
+ delta_limit = (unsigned long)
+ (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
if (diffcore_count_changes(src->data, src->size,
dst->data, dst->size,
&src->cnt_data, &dst->cnt_data,
if (!dst->size)
score = 0; /* should not happen */
else
- score = src_copied * MAX_SCORE / max_size;
+ score = (int)(src_copied * MAX_SCORE / max_size);
return score;
}
struct diff_filespec *one = rename_src[j].one;
if (!is_exact_match(one, two, contents_too))
continue;
- record_rename_pair(i, j, MAX_SCORE);
+ record_rename_pair(i, j, (int)MAX_SCORE);
rename_count++;
break; /* we are done with this entry */
}
{
struct stat st;
int fd, i;
- long size;
+ size_t size;
char *buf, *entry;
fd = open(fname, O_RDONLY);
if (fd < 0 || fstat(fd, &st) < 0)
goto err;
- size = st.st_size;
+ size = xsize_t(st.st_size);
if (size == 0) {
close(fd);
return 0;
}
}
+static inline size_t xsize_t(off_t len)
+{
+ return (size_t)len;
+}
+
static inline int has_extension(const char *filename, const char *ext)
{
size_t len = strlen(filename);
return match;
}
-static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
+static int ce_compare_link(struct cache_entry *ce, size_t expected_size)
{
int match = -1;
char *target;
return DATA_CHANGED;
break;
case S_IFLNK:
- if (ce_compare_link(ce, st->st_size))
+ if (ce_compare_link(ce, xsize_t(st->st_size)))
return DATA_CHANGED;
break;
default:
}
if (!fstat(fd, &st)) {
- cache_mmap_size = st.st_size;
+ cache_mmap_size = xsize_t(st.st_size);
errno = EINVAL;
if (cache_mmap_size >= sizeof(struct cache_header) + 20)
cache_mmap = xmmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
unsigned long date;
unsigned char logged_sha1[20];
void *log_mapped;
+ size_t mapsz;
logfile = git_path("logs/%s", ref);
logfd = open(logfile, O_RDONLY, 0);
fstat(logfd, &st);
if (!st.st_size)
die("Log %s is empty.", logfile);
- log_mapped = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
+ mapsz = xsize_t(st.st_size);
+ log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
logdata = log_mapped;
close(logfd);
logfile, show_rfc2822_date(date, tz));
}
}
- munmap(log_mapped, st.st_size);
+ munmap(log_mapped, mapsz);
return 0;
}
lastrec = rec;
die("Log %s is corrupt.", logfile);
if (msg)
*msg = ref_msg(logdata, logend);
- munmap(log_mapped, st.st_size);
+ munmap(log_mapped, mapsz);
if (cutoff_time)
*cutoff_time = date;
static void read_info_alternates(const char * relative_base, int depth)
{
char *map;
+ size_t mapsz;
struct stat st;
char path[PATH_MAX];
int fd;
close(fd);
return;
}
- map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ mapsz = xsize_t(st.st_size);
+ map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- link_alt_odb_entries(map, map + st.st_size, '\n', relative_base, depth);
+ link_alt_odb_entries(map, map + mapsz, '\n', relative_base, depth);
- munmap(map, st.st_size);
+ munmap(map, mapsz);
}
void prepare_alt_odb(void)
{
void *idx_map;
uint32_t *index;
- unsigned long idx_size;
+ size_t idx_size;
uint32_t nr, i;
int fd = open(path, O_RDONLY);
struct stat st;
close(fd);
return -1;
}
- idx_size = st.st_size;
+ idx_size = xsize_t(st.st_size);
if (idx_size < 4 * 256 + 20 + 20) {
close(fd);
return error("index file %s is too small", path);
}
if (!win) {
size_t window_align = packed_git_window_size / 2;
+ off_t len;
win = xcalloc(1, sizeof(*win));
win->offset = (offset / window_align) * window_align;
- win->len = p->pack_size - win->offset;
- if (win->len > packed_git_window_size)
- win->len = packed_git_window_size;
+ len = p->pack_size - win->offset;
+ if (len > packed_git_window_size)
+ len = packed_git_window_size;
+ win->len = (size_t)len;
pack_mapped += win->len;
while (packed_git_limit < pack_mapped
&& unuse_one_window(p))
}
offset -= win->offset;
if (left)
- *left = win->len - offset;
+ *left = win->len - xsize_t(offset);
return win->base + offset;
}
*/
sha1_file_open_flag = 0;
}
- map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ *size = xsize_t(st.st_size);
+ map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- *size = st.st_size;
return map;
}
uint32_t num_packed_objects(const struct packed_git *p)
{
/* See check_packed_git_idx() */
- return (p->index_size - 20 - 20 - 4*256) / 24;
+ return (uint32_t)((p->index_size - 20 - 20 - 4*256) / 24);
}
int nth_packed_object_sha1(const struct packed_git *p, uint32_t n,
int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
enum object_type type, const char *path)
{
- unsigned long size = st->st_size;
+ size_t size = xsize_t(st->st_size);
void *buf = NULL;
int ret, re_allocated = 0;
{
int fd;
char *target;
+ size_t len;
switch (st->st_mode & S_IFMT) {
case S_IFREG:
path);
break;
case S_IFLNK:
- target = xmalloc(st->st_size+1);
- if (readlink(path, target, st->st_size+1) != st->st_size) {
+ len = xsize_t(st->st_size);
+ target = xmalloc(len + 1);
+ if (readlink(path, target, len + 1) != st->st_size) {
char *errstr = strerror(errno);
free(target);
return error("readlink(\"%s\"): %s", path,
errstr);
}
if (!write_object)
- hash_sha1_file(target, st->st_size, blob_type, sha1);
- else if (write_sha1_file(target, st->st_size, blob_type, sha1))
+ hash_sha1_file(target, len, blob_type, sha1);
+ else if (write_sha1_file(target, len, blob_type, sha1))
return error("%s: failed to insert into database",
path);
free(target);
{
struct stat st;
FILE *f;
+ size_t sz;
if (stat(filename, &st))
return error("Could not stat %s", filename);
if ((f = fopen(filename, "rb")) == NULL)
return error("Could not open %s", filename);
- ptr->ptr = xmalloc(st.st_size);
- if (fread(ptr->ptr, st.st_size, 1, f) != 1)
+ sz = xsize_t(st.st_size);
+ ptr->ptr = xmalloc(sz);
+ if (fread(ptr->ptr, sz, 1, f) != 1)
return error("Could not read %s", filename);
fclose(f);
- ptr->size = st.st_size;
+ ptr->size = sz;
return 0;
}