Skip to content

Commit 50a6c8e

Browse files
peffgitster
authored andcommitted
use st_add and st_mult for allocation size computation
If our size computation overflows size_t, we may allocate a much smaller buffer than we expected and overflow it. It's probably impossible to trigger an overflow in most of these sites in practice, but it is easy enough convert their additions and multiplications into overflow-checking variants. This may be fixing real bugs, and it makes auditing the code easier. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 96ffc06 commit 50a6c8e

25 files changed

+56
-53
lines changed

archive.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ static void queue_directory(const unsigned char *sha1,
171171
unsigned mode, int stage, struct archiver_context *c)
172172
{
173173
struct directory *d;
174-
size_t len = base->len + 1 + strlen(filename) + 1;
175-
d = xmalloc(sizeof(*d) + len);
174+
size_t len = st_add4(base->len, 1, strlen(filename), 1);
175+
d = xmalloc(st_add(sizeof(*d), len));
176176
d->up = c->bottom;
177177
d->baselen = base->len;
178178
d->mode = mode;

builtin/apply.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2632,7 +2632,7 @@ static void update_image(struct image *img,
26322632
insert_count = postimage->len;
26332633

26342634
/* Adjust the contents */
2635-
result = xmalloc(img->len + insert_count - remove_count + 1);
2635+
result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1));
26362636
memcpy(result, img->buf, applied_at);
26372637
memcpy(result + applied_at, postimage->buf, postimage->len);
26382638
memcpy(result + applied_at + postimage->len,

builtin/clean.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
615615
nr += chosen[i];
616616
}
617617

618-
result = xcalloc(nr + 1, sizeof(int));
618+
result = xcalloc(st_add(nr, 1), sizeof(int));
619619
for (i = 0; i < stuff->nr && j < nr; i++) {
620620
if (chosen[i])
621621
result[j++] = i;

builtin/fetch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1107,7 +1107,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
11071107
if (argc > 0) {
11081108
int j = 0;
11091109
int i;
1110-
refs = xcalloc(argc + 1, sizeof(const char *));
1110+
refs = xcalloc(st_add(argc, 1), sizeof(const char *));
11111111
for (i = 0; i < argc; i++) {
11121112
if (!strcmp(argv[i], "tag")) {
11131113
i++;

builtin/index-pack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,9 +1744,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
17441744

17451745
curr_pack = open_pack_file(pack_name);
17461746
parse_pack_header();
1747-
objects = xcalloc(nr_objects + 1, sizeof(struct object_entry));
1747+
objects = xcalloc(st_add(nr_objects, 1), sizeof(struct object_entry));
17481748
if (show_stat)
1749-
obj_stat = xcalloc(nr_objects + 1, sizeof(struct object_stat));
1749+
obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat));
17501750
ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry));
17511751
parse_pack_objects(pack_sha1);
17521752
resolve_deltas();

builtin/merge.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ static int setup_with_upstream(const char ***argv)
939939
if (!branch->merge_nr)
940940
die(_("No default upstream defined for the current branch."));
941941

942-
args = xcalloc(branch->merge_nr + 1, sizeof(char *));
942+
args = xcalloc(st_add(branch->merge_nr, 1), sizeof(char *));
943943
for (i = 0; i < branch->merge_nr; i++) {
944944
if (!branch->merge[i]->dst)
945945
die(_("No remote-tracking branch for %s from %s"),

builtin/mv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ static const char **internal_copy_pathspec(const char *prefix,
4848

4949
static const char *add_slash(const char *path)
5050
{
51-
int len = strlen(path);
51+
size_t len = strlen(path);
5252
if (path[len - 1] != '/') {
53-
char *with_slash = xmalloc(len + 2);
53+
char *with_slash = xmalloc(st_add(len, 2));
5454
memcpy(with_slash, path, len);
5555
with_slash[len++] = '/';
5656
with_slash[len] = 0;

builtin/receive-pack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,7 +1372,7 @@ static struct command **queue_command(struct command **tail,
13721372

13731373
refname = line + 82;
13741374
reflen = linelen - 82;
1375-
cmd = xcalloc(1, sizeof(struct command) + reflen + 1);
1375+
cmd = xcalloc(1, st_add3(sizeof(struct command), reflen, 1));
13761376
hashcpy(cmd->old_sha1, old_sha1);
13771377
hashcpy(cmd->new_sha1, new_sha1);
13781378
memcpy(cmd->ref_name, refname, reflen);

combine-diff.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,11 @@ static struct lline *coalesce_lines(struct lline *base, int *lenbase,
189189
* - Else if we have NEW, insert newend lline into base and
190190
* consume newend
191191
*/
192-
lcs = xcalloc(origbaselen + 1, sizeof(int*));
193-
directions = xcalloc(origbaselen + 1, sizeof(enum coalesce_direction*));
192+
lcs = xcalloc(st_add(origbaselen, 1), sizeof(int*));
193+
directions = xcalloc(st_add(origbaselen, 1), sizeof(enum coalesce_direction*));
194194
for (i = 0; i < origbaselen + 1; i++) {
195-
lcs[i] = xcalloc(lennew + 1, sizeof(int));
196-
directions[i] = xcalloc(lennew + 1, sizeof(enum coalesce_direction));
195+
lcs[i] = xcalloc(st_add(lennew, 1), sizeof(int));
196+
directions[i] = xcalloc(st_add(lennew, 1), sizeof(enum coalesce_direction));
197197
directions[i][0] = BASE;
198198
}
199199
for (j = 1; j < lennew + 1; j++)
@@ -1111,7 +1111,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
11111111
if (result_size && result[result_size-1] != '\n')
11121112
cnt++; /* incomplete line */
11131113

1114-
sline = xcalloc(cnt+2, sizeof(*sline));
1114+
sline = xcalloc(st_add(cnt, 2), sizeof(*sline));
11151115
sline[0].bol = result;
11161116
for (lno = 0, cp = result; cp < result + result_size; cp++) {
11171117
if (*cp == '\n') {
@@ -1130,7 +1130,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
11301130
/* Even p_lno[cnt+1] is valid -- that is for the end line number
11311131
* for deletion hunk at the end.
11321132
*/
1133-
sline[0].p_lno = xcalloc((cnt+2) * num_parent, sizeof(unsigned long));
1133+
sline[0].p_lno = xcalloc(st_mult(st_add(cnt, 2), num_parent), sizeof(unsigned long));
11341134
for (lno = 0; lno <= cnt; lno++)
11351135
sline[lno+1].p_lno = sline[lno].p_lno + num_parent;
11361136

@@ -1262,7 +1262,7 @@ static struct diff_filepair *combined_pair(struct combine_diff_path *p,
12621262
struct diff_filespec *pool;
12631263

12641264
pair = xmalloc(sizeof(*pair));
1265-
pool = xcalloc(num_parent + 1, sizeof(struct diff_filespec));
1265+
pool = xcalloc(st_add(num_parent, 1), sizeof(struct diff_filespec));
12661266
pair->one = pool + 1;
12671267
pair->two = pool;
12681268

commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ struct commit_graft *read_graft_line(char *buf, int len)
147147
if ((len + 1) % entry_size)
148148
goto bad_graft_data;
149149
i = (len + 1) / entry_size - 1;
150-
graft = xmalloc(sizeof(*graft) + GIT_SHA1_RAWSZ * i);
150+
graft = xmalloc(st_add(sizeof(*graft), st_mult(GIT_SHA1_RAWSZ, i)));
151151
graft->nr_parent = i;
152152
if (get_oid_hex(buf, &graft->oid))
153153
goto bad_graft_data;

0 commit comments

Comments
 (0)