Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'jk/tighten-alloc'
Update various codepaths to avoid manually-counted malloc().

* jk/tighten-alloc: (22 commits)
  ewah: convert to REALLOC_ARRAY, etc
  convert ewah/bitmap code to use xmalloc
  diff_populate_gitlink: use a strbuf
  transport_anonymize_url: use xstrfmt
  git-compat-util: drop mempcpy compat code
  sequencer: simplify memory allocation of get_message
  test-path-utils: fix normalize_path_copy output buffer size
  fetch-pack: simplify add_sought_entry
  fast-import: simplify allocation in start_packfile
  write_untracked_extension: use FLEX_ALLOC helper
  prepare_{git,shell}_cmd: use argv_array
  use st_add and st_mult for allocation size computation
  convert trivial cases to FLEX_ARRAY macros
  use xmallocz to avoid size arithmetic
  convert trivial cases to ALLOC_ARRAY
  convert manual allocations to argv_array
  argv-array: add detach function
  add helpers for allocating flex-array structs
  harden REALLOC_ARRAY and xcalloc against size_t overflow
  tree-diff: catch integer overflow in combine_diff_path allocation
  ...
  • Loading branch information
Junio C Hamano committed Feb 26, 2016
2 parents 3ed26a4 + 08c95df commit 11529ec
Show file tree
Hide file tree
Showing 91 changed files with 441 additions and 482 deletions.
7 changes: 7 additions & 0 deletions Documentation/technical/api-argv-array.txt
Expand Up @@ -56,3 +56,10 @@ Functions
`argv_array_clear`::
Free all memory associated with the array and return it to the
initial, empty state.

`argv_array_detach`::
Disconnect the `argv` member from the `argv_array` struct and
return it. The caller is responsible for freeing the memory used
by the array, and by the strings it references. After detaching,
the `argv_array` is in a reinitialized state and can be pushed
into again.
2 changes: 1 addition & 1 deletion alias.c
Expand Up @@ -23,7 +23,7 @@ int split_cmdline(char *cmdline, const char ***argv)
int src, dst, count = 0, size = 16;
char quoted = 0;

*argv = xmalloc(sizeof(**argv) * size);
ALLOC_ARRAY(*argv, size);

/* split alias_string */
(*argv)[count++] = cmdline;
Expand Down
4 changes: 2 additions & 2 deletions archive.c
Expand Up @@ -171,8 +171,8 @@ static void queue_directory(const unsigned char *sha1,
unsigned mode, int stage, struct archiver_context *c)
{
struct directory *d;
size_t len = base->len + 1 + strlen(filename) + 1;
d = xmalloc(sizeof(*d) + len);
size_t len = st_add4(base->len, 1, strlen(filename), 1);
d = xmalloc(st_add(sizeof(*d), len));
d->up = c->bottom;
d->baselen = base->len;
d->mode = mode;
Expand Down
11 changes: 11 additions & 0 deletions argv-array.c
Expand Up @@ -74,3 +74,14 @@ void argv_array_clear(struct argv_array *array)
}
argv_array_init(array);
}

const char **argv_array_detach(struct argv_array *array)
{
if (array->argv == empty_argv)
return xcalloc(1, sizeof(const char *));
else {
const char **ret = array->argv;
argv_array_init(array);
return ret;
}
}
1 change: 1 addition & 0 deletions argv-array.h
Expand Up @@ -20,5 +20,6 @@ void argv_array_pushl(struct argv_array *, ...);
void argv_array_pushv(struct argv_array *, const char **);
void argv_array_pop(struct argv_array *);
void argv_array_clear(struct argv_array *);
const char **argv_array_detach(struct argv_array *);

#endif /* ARGV_ARRAY_H */
6 changes: 2 additions & 4 deletions attr.c
Expand Up @@ -93,9 +93,7 @@ static struct git_attr *git_attr_internal(const char *name, int len)
if (invalid_attr_name(name, len))
return NULL;

a = xmalloc(sizeof(*a) + len + 1);
memcpy(a->name, name, len);
a->name[len] = 0;
FLEX_ALLOC_MEM(a, name, name, len);
a->h = hval;
a->next = git_attr_hash[pos];
a->attr_nr = attr_nr++;
Expand Down Expand Up @@ -799,7 +797,7 @@ int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
++count;
}
*num = count;
*check = xmalloc(sizeof(**check) * count);
ALLOC_ARRAY(*check, count);
j = 0;
for (i = 0; i < attr_nr; i++) {
const char *value = check_all_attr[i].value;
Expand Down
4 changes: 2 additions & 2 deletions bisect.c
Expand Up @@ -708,10 +708,10 @@ static struct commit *get_commit_reference(const unsigned char *sha1)

static struct commit **get_bad_and_good_commits(int *rev_nr)
{
int len = 1 + good_revs.nr;
struct commit **rev = xmalloc(len * sizeof(*rev));
struct commit **rev;
int i, n = 0;

ALLOC_ARRAY(rev, 1 + good_revs.nr);
rev[n++] = get_commit_reference(current_bad_oid->hash);
for (i = 0; i < good_revs.nr; i++)
rev[n++] = get_commit_reference(good_revs.sha1[i]);
Expand Down
2 changes: 1 addition & 1 deletion builtin/apply.c
Expand Up @@ -2632,7 +2632,7 @@ static void update_image(struct image *img,
insert_count = postimage->len;

/* Adjust the contents */
result = xmalloc(img->len + insert_count - remove_count + 1);
result = xmalloc(st_add3(st_sub(img->len, remove_count), insert_count, 1));
memcpy(result, img->buf, applied_at);
memcpy(result + applied_at, postimage->buf, postimage->len);
memcpy(result + applied_at + postimage->len,
Expand Down
7 changes: 3 additions & 4 deletions builtin/blame.c
Expand Up @@ -466,13 +466,11 @@ static void queue_blames(struct scoreboard *sb, struct origin *porigin,
static struct origin *make_origin(struct commit *commit, const char *path)
{
struct origin *o;
size_t pathlen = strlen(path) + 1;
o = xcalloc(1, sizeof(*o) + pathlen);
FLEX_ALLOC_STR(o, path, path);
o->commit = commit;
o->refcnt = 1;
o->next = commit->util;
commit->util = o;
memcpy(o->path, path, pathlen); /* includes NUL */
return o;
}

Expand Down Expand Up @@ -2059,7 +2057,8 @@ static int prepare_lines(struct scoreboard *sb)
for (p = buf; p < end; p = get_next_line(p, end))
num++;

sb->lineno = lineno = xmalloc(sizeof(*sb->lineno) * (num + 1));
ALLOC_ARRAY(sb->lineno, num + 1);
lineno = sb->lineno;

for (p = buf; p < end; p = get_next_line(p, end))
*lineno++ = p - buf;
Expand Down
2 changes: 1 addition & 1 deletion builtin/check-ref-format.c
Expand Up @@ -20,7 +20,7 @@ static const char builtin_check_ref_format_usage[] =
*/
static char *collapse_slashes(const char *refname)
{
char *ret = xmalloc(strlen(refname) + 1);
char *ret = xmallocz(strlen(refname));
char ch;
char prev = '/';
char *cp = ret;
Expand Down
4 changes: 2 additions & 2 deletions builtin/clean.c
Expand Up @@ -543,7 +543,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
int eof = 0;
int i;

chosen = xmalloc(sizeof(int) * stuff->nr);
ALLOC_ARRAY(chosen, stuff->nr);
/* set chosen as uninitialized */
for (i = 0; i < stuff->nr; i++)
chosen[i] = -1;
Expand Down Expand Up @@ -615,7 +615,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
nr += chosen[i];
}

result = xcalloc(nr + 1, sizeof(int));
result = xcalloc(st_add(nr, 1), sizeof(int));
for (i = 0; i < stuff->nr && j < nr; i++) {
if (chosen[i])
result[j++] = i;
Expand Down
2 changes: 1 addition & 1 deletion builtin/fast-export.c
Expand Up @@ -1021,7 +1021,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
const char **refspecs_str;
int i;

refspecs_str = xmalloc(sizeof(*refspecs_str) * refspecs_list.nr);
ALLOC_ARRAY(refspecs_str, refspecs_list.nr);
for (i = 0; i < refspecs_list.nr; i++)
refspecs_str[i] = refspecs_list.items[i].string;

Expand Down
27 changes: 9 additions & 18 deletions builtin/fetch-pack.c
Expand Up @@ -10,33 +10,24 @@ static const char fetch_pack_usage[] =
"[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
"[--no-progress] [--diag-url] [-v] [<host>:]<directory> [<refs>...]";

static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc,
const char *name, int namelen)
static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
const char *name)
{
struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1);
struct ref *ref;
struct object_id oid;
const int chunksz = GIT_SHA1_HEXSZ + 1;

if (namelen > chunksz && name[chunksz - 1] == ' ' &&
!get_oid_hex(name, &oid)) {
oidcpy(&ref->old_oid, &oid);
name += chunksz;
namelen -= chunksz;
}
if (!get_oid_hex(name, &oid) && name[GIT_SHA1_HEXSZ] == ' ')
name += GIT_SHA1_HEXSZ + 1;
else
oidclr(&oid);

memcpy(ref->name, name, namelen);
ref->name[namelen] = '\0';
ref = alloc_ref(name);
oidcpy(&ref->old_oid, &oid);
(*nr)++;
ALLOC_GROW(*sought, *nr, *alloc);
(*sought)[*nr - 1] = ref;
}

static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
const char *string)
{
add_sought_entry_mem(sought, nr, alloc, string, strlen(string));
}

int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
{
int i, ret;
Expand Down
2 changes: 1 addition & 1 deletion builtin/fetch.c
Expand Up @@ -1115,7 +1115,7 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
if (argc > 0) {
int j = 0;
int i;
refs = xcalloc(argc + 1, sizeof(const char *));
refs = xcalloc(st_add(argc, 1), sizeof(const char *));
for (i = 0; i < argc; i++) {
if (!strcmp(argv[i], "tag")) {
i++;
Expand Down
10 changes: 5 additions & 5 deletions builtin/grep.c
Expand Up @@ -365,17 +365,17 @@ static void append_path(struct grep_opt *opt, const void *data, size_t len)
static void run_pager(struct grep_opt *opt, const char *prefix)
{
struct string_list *path_list = opt->output_priv;
const char **argv = xmalloc(sizeof(const char *) * (path_list->nr + 1));
struct child_process child = CHILD_PROCESS_INIT;
int i, status;

for (i = 0; i < path_list->nr; i++)
argv[i] = path_list->items[i].string;
argv[path_list->nr] = NULL;
argv_array_push(&child.args, path_list->items[i].string);
child.dir = prefix;
child.use_shell = 1;

status = run_command_v_opt_cd_env(argv, RUN_USING_SHELL, prefix, NULL);
status = run_command(&child);
if (status)
exit(status);
free(argv);
}

static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached)
Expand Down
9 changes: 3 additions & 6 deletions builtin/help.c
Expand Up @@ -171,12 +171,10 @@ static void exec_man_cmd(const char *cmd, const char *page)
static void add_man_viewer(const char *name)
{
struct man_viewer_list **p = &man_viewer_list;
size_t len = strlen(name);

while (*p)
p = &((*p)->next);
*p = xcalloc(1, (sizeof(**p) + len + 1));
memcpy((*p)->name, name, len); /* NUL-terminated by xcalloc */
FLEX_ALLOC_STR(*p, name, name);
}

static int supported_man_viewer(const char *name, size_t len)
Expand All @@ -190,9 +188,8 @@ static void do_add_man_viewer_info(const char *name,
size_t len,
const char *value)
{
struct man_viewer_info_list *new = xcalloc(1, sizeof(*new) + len + 1);

memcpy(new->name, name, len); /* NUL-terminated by xcalloc */
struct man_viewer_info_list *new;
FLEX_ALLOC_MEM(new, name, name, len);
new->info = xstrdup(value);
new->next = man_viewer_info_list;
man_viewer_info_list = new;
Expand Down
8 changes: 4 additions & 4 deletions builtin/index-pack.c
Expand Up @@ -1346,7 +1346,7 @@ static void fix_unresolved_deltas(struct sha1file *f)
* before deltas depending on them, a good heuristic is to start
* resolving deltas in the same order as their position in the pack.
*/
sorted_by_pos = xmalloc(nr_ref_deltas * sizeof(*sorted_by_pos));
ALLOC_ARRAY(sorted_by_pos, nr_ref_deltas);
for (i = 0; i < nr_ref_deltas; i++)
sorted_by_pos[i] = &ref_deltas[i];
qsort(sorted_by_pos, nr_ref_deltas, sizeof(*sorted_by_pos), delta_pos_compare);
Expand Down Expand Up @@ -1744,9 +1744,9 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)

curr_pack = open_pack_file(pack_name);
parse_pack_header();
objects = xcalloc(nr_objects + 1, sizeof(struct object_entry));
objects = xcalloc(st_add(nr_objects, 1), sizeof(struct object_entry));
if (show_stat)
obj_stat = xcalloc(nr_objects + 1, sizeof(struct object_stat));
obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat));
ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry));
parse_pack_objects(pack_sha1);
resolve_deltas();
Expand All @@ -1759,7 +1759,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
if (show_stat)
show_pack_info(stat_only);

idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *));
ALLOC_ARRAY(idx_objects, nr_objects);
for (i = 0; i < nr_objects; i++)
idx_objects[i] = &objects[i].idx;
curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_sha1);
Expand Down
2 changes: 1 addition & 1 deletion builtin/merge-base.c
Expand Up @@ -252,7 +252,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
if (argc < 2)
usage_with_options(merge_base_usage, options);

rev = xmalloc(argc * sizeof(*rev));
ALLOC_ARRAY(rev, argc);
while (argc-- > 0)
rev[rev_nr++] = get_commit_reference(*argv++);
return show_merge_base(rev, rev_nr, show_all);
Expand Down
2 changes: 1 addition & 1 deletion builtin/merge-tree.c
Expand Up @@ -174,7 +174,7 @@ static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsi

static char *traverse_path(const struct traverse_info *info, const struct name_entry *n)
{
char *path = xmalloc(traverse_path_len(info, n) + 1);
char *path = xmallocz(traverse_path_len(info, n));
return make_traverse_path(path, info, n);
}

Expand Down
2 changes: 1 addition & 1 deletion builtin/merge.c
Expand Up @@ -939,7 +939,7 @@ static int setup_with_upstream(const char ***argv)
if (!branch->merge_nr)
die(_("No default upstream defined for the current branch."));

args = xcalloc(branch->merge_nr + 1, sizeof(char *));
args = xcalloc(st_add(branch->merge_nr, 1), sizeof(char *));
for (i = 0; i < branch->merge_nr; i++) {
if (!branch->merge[i]->dst)
die(_("No remote-tracking branch for %s from %s"),
Expand Down
9 changes: 5 additions & 4 deletions builtin/mktree.c
Expand Up @@ -19,16 +19,17 @@ static int alloc, used;
static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
{
struct treeent *ent;
int len = strlen(path);
size_t len = strlen(path);
if (strchr(path, '/'))
die("path %s contains slash", path);

ALLOC_GROW(entries, used + 1, alloc);
ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
FLEX_ALLOC_MEM(ent, name, path, len);
ent->mode = mode;
ent->len = len;
hashcpy(ent->sha1, sha1);
memcpy(ent->name, path, len+1);

ALLOC_GROW(entries, used + 1, alloc);
entries[used++] = ent;
}

static int ent_compare(const void *a_, const void *b_)
Expand Down
7 changes: 4 additions & 3 deletions builtin/mv.c
Expand Up @@ -24,7 +24,8 @@ static const char **internal_copy_pathspec(const char *prefix,
int count, unsigned flags)
{
int i;
const char **result = xmalloc((count + 1) * sizeof(const char *));
const char **result;
ALLOC_ARRAY(result, count + 1);
memcpy(result, pathspec, count * sizeof(const char *));
result[count] = NULL;
for (i = 0; i < count; i++) {
Expand All @@ -47,9 +48,9 @@ static const char **internal_copy_pathspec(const char *prefix,

static const char *add_slash(const char *path)
{
int len = strlen(path);
size_t len = strlen(path);
if (path[len - 1] != '/') {
char *with_slash = xmalloc(len + 2);
char *with_slash = xmalloc(st_add(len, 2));
memcpy(with_slash, path, len);
with_slash[len++] = '/';
with_slash[len] = 0;
Expand Down
7 changes: 4 additions & 3 deletions builtin/pack-objects.c
Expand Up @@ -624,7 +624,7 @@ static struct object_entry **compute_write_order(void)
{
unsigned int i, wo_end, last_untagged;

struct object_entry **wo = xmalloc(to_pack.nr_objects * sizeof(*wo));
struct object_entry **wo;
struct object_entry *objects = to_pack.objects;

for (i = 0; i < to_pack.nr_objects; i++) {
Expand Down Expand Up @@ -657,6 +657,7 @@ static struct object_entry **compute_write_order(void)
* Give the objects in the original recency order until
* we see a tagged tip.
*/
ALLOC_ARRAY(wo, to_pack.nr_objects);
for (i = wo_end = 0; i < to_pack.nr_objects; i++) {
if (objects[i].tagged)
break;
Expand Down Expand Up @@ -769,7 +770,7 @@ static void write_pack_file(void)

if (progress > pack_to_stdout)
progress_state = start_progress(_("Writing objects"), nr_result);
written_list = xmalloc(to_pack.nr_objects * sizeof(*written_list));
ALLOC_ARRAY(written_list, to_pack.nr_objects);
write_order = compute_write_order();

do {
Expand Down Expand Up @@ -2129,7 +2130,7 @@ static void prepare_pack(int window, int depth)
if (!to_pack.nr_objects || !window || !depth)
return;

delta_list = xmalloc(to_pack.nr_objects * sizeof(*delta_list));
ALLOC_ARRAY(delta_list, to_pack.nr_objects);
nr_deltas = n = 0;

for (i = 0; i < to_pack.nr_objects; i++) {
Expand Down

0 comments on commit 11529ec

Please sign in to comment.