Skip to content

Commit dc49cd7

Browse files
spearceJunio C Hamano
authored andcommitted
Cast 64 bit off_t to 32 bit size_t
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6777a59 commit dc49cd7

16 files changed

+83
-59
lines changed

builtin-apply.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
19811981
}
19821982
}
19831983
else if (patch->old_name) {
1984-
size = st->st_size;
1984+
size = xsize_t(st->st_size);
19851985
alloc = size + 8192;
19861986
buf = xmalloc(alloc);
19871987
if (read_old_data(st, patch->old_name, &buf, &alloc, &size))

builtin-blame.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1963,7 +1963,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
19631963
die("Cannot lstat %s", path);
19641964
read_from = path;
19651965
}
1966-
fin_size = st.st_size;
1966+
fin_size = xsize_t(st.st_size);
19671967
buf = xmalloc(fin_size+1);
19681968
mode = canon_mode(st.st_mode);
19691969
switch (st.st_mode & S_IFMT) {

builtin-count-objects.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
4444
if (lstat(path, &st) || !S_ISREG(st.st_mode))
4545
bad = 1;
4646
else
47-
(*loose_size) += st.st_blocks;
47+
(*loose_size) += xsize_t(st.st_blocks);
4848
}
4949
if (bad) {
5050
if (verbose) {

builtin-grep.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ static int grep_file(struct grep_opt *opt, const char *filename)
122122
struct stat st;
123123
int i;
124124
char *data;
125+
size_t sz;
126+
125127
if (lstat(filename, &st) < 0) {
126128
err_ret:
127129
if (errno != ENOENT)
@@ -132,11 +134,12 @@ static int grep_file(struct grep_opt *opt, const char *filename)
132134
return 0; /* empty file -- no grep hit */
133135
if (!S_ISREG(st.st_mode))
134136
return 0;
137+
sz = xsize_t(st.st_size);
135138
i = open(filename, O_RDONLY);
136139
if (i < 0)
137140
goto err_ret;
138-
data = xmalloc(st.st_size + 1);
139-
if (st.st_size != read_in_full(i, data, st.st_size)) {
141+
data = xmalloc(sz + 1);
142+
if (st.st_size != read_in_full(i, data, sz)) {
140143
error("'%s': short read %s", filename, strerror(errno));
141144
close(i);
142145
free(data);
@@ -145,7 +148,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
145148
close(i);
146149
if (opt->relative && opt->prefix_length)
147150
filename += opt->prefix_length;
148-
i = grep_buffer(opt, filename, data, st.st_size);
151+
i = grep_buffer(opt, filename, data, sz);
149152
free(data);
150153
return i;
151154
}

combine-diff.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
684684
goto deleted_file;
685685

686686
if (S_ISLNK(st.st_mode)) {
687-
size_t len = st.st_size;
687+
size_t len = xsize_t(st.st_size);
688688
result_size = len;
689689
result = xmalloc(len + 1);
690690
if (result_size != readlink(elem->path, result, len)) {
@@ -697,7 +697,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
697697
}
698698
else if (0 <= (fd = open(elem->path, O_RDONLY)) &&
699699
!fstat(fd, &st)) {
700-
size_t len = st.st_size;
700+
size_t len = xsize_t(st.st_size);
701701
size_t sz = 0;
702702
int is_file, i;
703703

config.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ static struct {
431431
int do_not_match;
432432
regex_t* value_regex;
433433
int multi_replace;
434-
off_t offset[MAX_MATCHES];
434+
size_t offset[MAX_MATCHES];
435435
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
436436
int seen;
437437
} store;
@@ -579,11 +579,11 @@ static int store_write_pair(int fd, const char* key, const char* value)
579579
return 1;
580580
}
581581

582-
static int find_beginning_of_line(const char* contents, int size,
583-
int offset_, int* found_bracket)
582+
static ssize_t find_beginning_of_line(const char* contents, size_t size,
583+
size_t offset_, int* found_bracket)
584584
{
585-
int equal_offset = size, bracket_offset = size;
586-
int offset;
585+
size_t equal_offset = size, bracket_offset = size;
586+
ssize_t offset;
587587

588588
for (offset = offset_-2; offset > 0
589589
&& contents[offset] != '\n'; offset--)
@@ -727,7 +727,8 @@ int git_config_set_multivar(const char* key, const char* value,
727727
} else {
728728
struct stat st;
729729
char* contents;
730-
int i, copy_begin, copy_end, new_line = 0;
730+
size_t contents_sz, copy_begin, copy_end;
731+
int i, new_line = 0;
731732

732733
if (value_regex == NULL)
733734
store.value_regex = NULL;
@@ -784,7 +785,8 @@ int git_config_set_multivar(const char* key, const char* value,
784785
}
785786

786787
fstat(in_fd, &st);
787-
contents = xmmap(NULL, st.st_size, PROT_READ,
788+
contents_sz = xsize_t(st.st_size);
789+
contents = xmmap(NULL, contents_sz, PROT_READ,
788790
MAP_PRIVATE, in_fd, 0);
789791
close(in_fd);
790792

@@ -793,12 +795,12 @@ int git_config_set_multivar(const char* key, const char* value,
793795

794796
for (i = 0, copy_begin = 0; i < store.seen; i++) {
795797
if (store.offset[i] == 0) {
796-
store.offset[i] = copy_end = st.st_size;
798+
store.offset[i] = copy_end = contents_sz;
797799
} else if (store.state != KEY_SEEN) {
798800
copy_end = store.offset[i];
799801
} else
800802
copy_end = find_beginning_of_line(
801-
contents, st.st_size,
803+
contents, contents_sz,
802804
store.offset[i]-2, &new_line);
803805

804806
/* write the first part of the config */
@@ -825,13 +827,13 @@ int git_config_set_multivar(const char* key, const char* value,
825827
}
826828

827829
/* write the rest of the config */
828-
if (copy_begin < st.st_size)
830+
if (copy_begin < contents_sz)
829831
if (write_in_full(fd, contents + copy_begin,
830-
st.st_size - copy_begin) <
831-
st.st_size - copy_begin)
832+
contents_sz - copy_begin) <
833+
contents_sz - copy_begin)
832834
goto write_err_out;
833835

834-
munmap(contents, st.st_size);
836+
munmap(contents, contents_sz);
835837
unlink(config_filename);
836838
}
837839

diff.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,7 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
13991399
return err;
14001400
}
14011401
}
1402-
s->size = st.st_size;
1402+
s->size = xsize_t(st.st_size);
14031403
if (!s->size)
14041404
goto empty;
14051405
if (size_only)
@@ -1515,12 +1515,13 @@ static void prepare_temp_file(const char *name,
15151515
if (S_ISLNK(st.st_mode)) {
15161516
int ret;
15171517
char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
1518+
size_t sz = xsize_t(st.st_size);
15181519
if (sizeof(buf) <= st.st_size)
15191520
die("symlink too long: %s", name);
1520-
ret = readlink(name, buf, st.st_size);
1521+
ret = readlink(name, buf, sz);
15211522
if (ret < 0)
15221523
die("readlink(%s)", name);
1523-
prep_temp_blob(temp, buf, st.st_size,
1524+
prep_temp_blob(temp, buf, sz,
15241525
(one->sha1_valid ?
15251526
one->sha1 : null_sha1),
15261527
(one->sha1_valid ?
@@ -2138,7 +2139,7 @@ static int parse_num(const char **cp_p)
21382139
/* user says num divided by scale and we say internally that
21392140
* is MAX_SCORE * num / scale.
21402141
*/
2141-
return (num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale);
2142+
return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale));
21422143
}
21432144

21442145
int diff_scoreopt_parse(const char *opt)

diffcore-break.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static int should_break(struct diff_filespec *src,
8989
* merge the surviving pair together if the score is
9090
* less than the minimum, after rename/copy runs.
9191
*/
92-
*merge_score_p = src_removed * MAX_SCORE / src->size;
92+
*merge_score_p = (int)(src_removed * MAX_SCORE / src->size);
9393

9494
/* Extent of damage, which counts both inserts and
9595
* deletes.

diffcore-order.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ static void prepare_order(const char *orderfile)
1414
void *map;
1515
char *cp, *endp;
1616
struct stat st;
17+
size_t sz;
1718

1819
if (order)
1920
return;
@@ -25,11 +26,12 @@ static void prepare_order(const char *orderfile)
2526
close(fd);
2627
return;
2728
}
28-
map = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
29+
sz = xsize_t(st.st_size);
30+
map = mmap(NULL, sz, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
2931
close(fd);
3032
if (map == MAP_FAILED)
3133
return;
32-
endp = (char *) map + st.st_size;
34+
endp = (char *) map + sz;
3335
for (pass = 0; pass < 2; pass++) {
3436
cnt = 0;
3537
cp = map;

diffcore-rename.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,8 @@ static int estimate_similarity(struct diff_filespec *src,
172172
return 0; /* error but caught downstream */
173173

174174

175-
delta_limit = base_size * (MAX_SCORE-minimum_score) / MAX_SCORE;
175+
delta_limit = (unsigned long)
176+
(base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
176177
if (diffcore_count_changes(src->data, src->size,
177178
dst->data, dst->size,
178179
&src->cnt_data, &dst->cnt_data,
@@ -186,7 +187,7 @@ static int estimate_similarity(struct diff_filespec *src,
186187
if (!dst->size)
187188
score = 0; /* should not happen */
188189
else
189-
score = src_copied * MAX_SCORE / max_size;
190+
score = (int)(src_copied * MAX_SCORE / max_size);
190191
return score;
191192
}
192193

@@ -297,7 +298,7 @@ void diffcore_rename(struct diff_options *options)
297298
struct diff_filespec *one = rename_src[j].one;
298299
if (!is_exact_match(one, two, contents_too))
299300
continue;
300-
record_rename_pair(i, j, MAX_SCORE);
301+
record_rename_pair(i, j, (int)MAX_SCORE);
301302
rename_count++;
302303
break; /* we are done with this entry */
303304
}

0 commit comments

Comments
 (0)