From: Junio C Hamano Date: Wed, 16 Mar 2016 17:42:02 +0000 (-0700) Subject: Merge branch 'jk/path-name-safety-2.5' into jk/path-name-safety-2.6 X-Git-Tag: v2.8.0-rc3~2^2^2^2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/717e3551b9fbfdb72e40a81fc0fb714cdaadb37f?ds=inline;hp=-c Merge branch 'jk/path-name-safety-2.5' into jk/path-name-safety-2.6 * jk/path-name-safety-2.5: list-objects: pass full pathname to callbacks list-objects: drop name_path entirely list-objects: convert name_path to a strbuf show_object_with_name: simplify by using path_name() http-push: stop using name_path tree-diff: catch integer overflow in combine_diff_path allocation add helpers for detecting size_t overflow --- 717e3551b9fbfdb72e40a81fc0fb714cdaadb37f diff --combined builtin/pack-objects.c index 1c63f8f28c,53307d53b0..676727e1c6 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@@ -25,8 -25,8 +25,8 @@@ #include "argv-array.h" static const char *pack_usage[] = { - N_("git pack-objects --stdout [options...] [< ref-list | < object-list]"), - N_("git pack-objects [options...] base-name [< ref-list | < object-list]"), + N_("git pack-objects --stdout [...] [< | < ]"), + N_("git pack-objects [...] [< | < ]"), NULL }; @@@ -2284,21 -2284,11 +2284,11 @@@ static void show_commit(struct commit * index_commit_for_bitmap(commit); } - static void show_object(struct object *obj, - const struct name_path *path, const char *last, - void *data) + static void show_object(struct object *obj, const char *name, void *data) { - char *name = path_name(path, last); - add_preferred_base_object(name); add_object_entry(obj->sha1, obj->type, name, 0); obj->flags |= OBJECT_ADDED; - - /* - * We will have generated the hash from the name, - * but not saved a pointer to it - we can free it - */ - free((char *)name); } static void show_edge(struct commit *commit) @@@ -2480,8 -2470,7 +2470,7 @@@ static int get_object_list_from_bitmap( } static void record_recent_object(struct object *obj, - const struct name_path *path, - const char *last, + const char *name, void *data) { sha1_array_append(&recent_objects, obj->sha1); @@@ -2588,6 -2577,23 +2577,6 @@@ static int option_parse_unpack_unreacha return 0; } -static int option_parse_ulong(const struct option *opt, - const char *arg, int unset) -{ - if (unset) - die(_("option %s does not accept negative form"), - opt->long_name); - - if (!git_parse_ulong(arg, opt->value)) - die(_("unable to parse value '%s' for option %s"), - arg, opt->long_name); - return 0; -} - -#define OPT_ULONG(s, l, v, h) \ - { OPTION_CALLBACK, (s), (l), (v), "n", (h), \ - PARSE_OPT_NONEG, option_parse_ulong } - int cmd_pack_objects(int argc, const char **argv, const char *prefix) { int use_internal_rev_list = 0; @@@ -2610,16 -2616,16 +2599,16 @@@ { OPTION_CALLBACK, 0, "index-version", NULL, N_("version[,offset]"), N_("write the pack index file in the specified idx format version"), 0, option_parse_index_version }, - OPT_ULONG(0, "max-pack-size", &pack_size_limit, - N_("maximum size of each output pack file")), + OPT_MAGNITUDE(0, "max-pack-size", &pack_size_limit, + N_("maximum size of each output pack file")), OPT_BOOL(0, "local", &local, N_("ignore borrowed objects from alternate object store")), OPT_BOOL(0, "incremental", &incremental, N_("ignore packed objects")), OPT_INTEGER(0, "window", &window, N_("limit pack window by objects")), - OPT_ULONG(0, "window-memory", &window_memory_limit, - N_("limit pack window by memory in addition to object limit")), + OPT_MAGNITUDE(0, "window-memory", &window_memory_limit, + N_("limit pack window by memory in addition to object limit")), OPT_INTEGER(0, "depth", &depth, N_("maximum length of delta chain allowed in the resulting pack")), OPT_BOOL(0, "reuse-delta", &reuse_delta, diff --combined diff.h index f7208ad103,37e43bc537..c6b66d5a20 --- a/diff.h +++ b/diff.h @@@ -91,7 -91,6 +91,7 @@@ typedef struct strbuf *(*diff_prefix_fn #define DIFF_OPT_DIRSTAT_BY_LINE (1 << 28) #define DIFF_OPT_FUNCCONTEXT (1 << 29) #define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30) +#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1 << 31) #define DIFF_OPT_TST(opts, flag) ((opts)->flags & DIFF_OPT_##flag) #define DIFF_OPT_TOUCHED(opts, flag) ((opts)->touched_flags & DIFF_OPT_##flag) @@@ -222,8 -221,8 +222,8 @@@ struct combine_diff_path } parent[FLEX_ARRAY]; }; #define combine_diff_path_size(n, l) \ - (sizeof(struct combine_diff_path) + \ - sizeof(struct combine_diff_parent) * (n) + (l) + 1) + st_add4(sizeof(struct combine_diff_path), (l), 1, \ + st_mult(sizeof(struct combine_diff_parent), (n))) extern void show_combined_diff(struct combine_diff_path *elem, int num_parent, int dense, struct rev_info *); diff --combined git-compat-util.h index 0feeae2983,d20fa89d5f..f035363ba6 --- a/git-compat-util.h +++ b/git-compat-util.h @@@ -96,6 -96,14 +96,14 @@@ #define unsigned_add_overflows(a, b) \ ((b) > maximum_unsigned_value_of_type(a) - (a)) + /* + * Returns true if the multiplication of "a" and "b" will + * overflow. The types of "a" and "b" must match and must be unsigned. + * Note that this macro evaluates "a" twice! + */ + #define unsigned_mult_overflows(a, b) \ + ((a) && (b) > maximum_unsigned_value_of_type(a) / (a)) + #ifdef __GNUC__ #define TYPEOF(x) (__typeof__(x)) #else @@@ -296,10 -304,6 +304,10 @@@ extern char *gitbasename(char *) #define PRIuMAX "llu" #endif +#ifndef SCNuMAX +#define SCNuMAX PRIuMAX +#endif + #ifndef PRIu32 #define PRIu32 "u" #endif @@@ -572,7 -576,7 +580,7 @@@ extern int git_lstat(const char *, stru #endif #define DEFAULT_PACKED_GIT_LIMIT \ - ((1024L * 1024L) * (sizeof(void*) >= 8 ? 8192 : 256)) + ((1024L * 1024L) * (size_t)(sizeof(void*) >= 8 ? 8192 : 256)) #ifdef NO_PREAD #define pread git_pread @@@ -703,6 -707,32 +711,32 @@@ extern void release_pack_memory(size_t) typedef void (*try_to_free_t)(size_t); extern try_to_free_t set_try_to_free_routine(try_to_free_t); + static inline size_t st_add(size_t a, size_t b) + { + if (unsigned_add_overflows(a, b)) + die("size_t overflow: %"PRIuMAX" + %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a + b; + } + #define st_add3(a,b,c) st_add((a),st_add((b),(c))) + #define st_add4(a,b,c,d) st_add((a),st_add3((b),(c),(d))) + + static inline size_t st_mult(size_t a, size_t b) + { + if (unsigned_mult_overflows(a, b)) + die("size_t overflow: %"PRIuMAX" * %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a * b; + } + + static inline size_t st_sub(size_t a, size_t b) + { + if (a < b) + die("size_t underflow: %"PRIuMAX" - %"PRIuMAX, + (uintmax_t)a, (uintmax_t)b); + return a - b; + } + #ifdef HAVE_ALLOCA_H # include # define xalloca(size) (alloca(size)) @@@ -721,12 -751,10 +755,12 @@@ extern void *xrealloc(void *ptr, size_ extern void *xcalloc(size_t nmemb, size_t size); extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset); +extern int xopen(const char *path, int flags, ...); extern ssize_t xread(int fd, void *buf, size_t len); extern ssize_t xwrite(int fd, const void *buf, size_t len); extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset); extern int xdup(int fd); +extern FILE *xfopen(const char *path, const char *mode); extern FILE *xfdopen(int fd, const char *mode); extern int xmkstemp(char *template); extern int xmkstemp_mode(char *template, int mode); @@@ -923,6 -951,9 +957,6 @@@ int access_or_die(const char *path, in /* Warn on an inaccessible file that ought to be accessible */ void warn_on_inaccessible(const char *path); -/* Get the passwd entry for the UID of the current process. */ -struct passwd *xgetpwuid_self(void); - #ifdef GMTIME_UNRELIABLE_ERRORS struct tm *git_gmtime(const time_t *); struct tm *git_gmtime_r(const time_t *, struct tm *); diff --combined reachable.c index 43616d49c7,59196253a6..ed35201896 --- a/reachable.c +++ b/reachable.c @@@ -25,15 -25,9 +25,15 @@@ static void update_progress(struct conn static int add_one_ref(const char *path, const struct object_id *oid, int flag, void *cb_data) { - struct object *object = parse_object_or_die(oid->hash, path); struct rev_info *revs = (struct rev_info *)cb_data; + struct object *object; + if ((flag & REF_ISSYMREF) && (flag & REF_ISBROKEN)) { + warning("symbolic ref is dangling: %s", path); + return 0; + } + + object = parse_object_or_die(oid->hash, path); add_pending_object(revs, object, ""); return 0; @@@ -43,15 -37,14 +43,14 @@@ * The traversal will have already marked us as SEEN, so we * only need to handle any progress reporting here. */ - static void mark_object(struct object *obj, const struct name_path *path, - const char *name, void *data) + static void mark_object(struct object *obj, const char *name, void *data) { update_progress(data); } static void mark_commit(struct commit *c, void *data) { - mark_object(&c->object, NULL, NULL, data); + mark_object(&c->object, NULL, data); } struct recent_data { diff --combined revision.c index e0107738b7,8f30ab1e46..8435ce5256 --- a/revision.c +++ b/revision.c @@@ -18,76 -18,16 +18,20 @@@ #include "commit-slab.h" #include "dir.h" #include "cache-tree.h" +#include "bisect.h" volatile show_early_output_fn_t show_early_output; +static const char *term_bad; +static const char *term_good; + - char *path_name(const struct name_path *path, const char *name) + void show_object_with_name(FILE *out, struct object *obj, const char *name) { - const struct name_path *p; - char *n, *m; - int nlen = strlen(name); - int len = nlen + 1; - - for (p = path; p; p = p->up) { - if (p->elem_len) - len += p->elem_len + 1; - } - n = xmalloc(len); - m = n + len - (nlen + 1); - strcpy(m, name); - for (p = path; p; p = p->up) { - if (p->elem_len) { - m -= p->elem_len + 1; - memcpy(m, p->elem, p->elem_len); - m[p->elem_len] = '/'; - } - } - return n; - } - - static int show_path_component_truncated(FILE *out, const char *name, int len) - { - int cnt; - for (cnt = 0; cnt < len; cnt++) { - int ch = name[cnt]; - if (!ch || ch == '\n') - return -1; - fputc(ch, out); - } - return len; - } - - static int show_path_truncated(FILE *out, const struct name_path *path) - { - int emitted, ours; - - if (!path) - return 0; - emitted = show_path_truncated(out, path->up); - if (emitted < 0) - return emitted; - if (emitted) - fputc('/', out); - ours = show_path_component_truncated(out, path->elem, path->elem_len); - if (ours < 0) - return ours; - return ours || emitted; - } - - void show_object_with_name(FILE *out, struct object *obj, - const struct name_path *path, const char *component) - { - struct name_path leaf; - leaf.up = (struct name_path *)path; - leaf.elem = component; - leaf.elem_len = strlen(component); + const char *p; fprintf(out, "%s ", sha1_to_hex(obj->sha1)); - show_path_truncated(out, &leaf); + for (p = name; *p && *p != '\n'; p++) + fputc(*p, out); fputc('\n', out); } @@@ -135,12 -75,10 +79,12 @@@ static void mark_tree_contents_unintere void mark_tree_uninteresting(struct tree *tree) { - struct object *obj = &tree->object; + struct object *obj; if (!tree) return; + + obj = &tree->object; if (obj->flags & UNINTERESTING) return; obj->flags |= UNINTERESTING; @@@ -155,7 -93,10 +99,7 @@@ void mark_parents_uninteresting(struct commit_list_insert(l->item, &parents); while (parents) { - struct commit *commit = parents->item; - l = parents; - parents = parents->next; - free(l); + struct commit *commit = pop_commit(&parents); while (commit) { /* @@@ -294,8 -235,9 +238,8 @@@ static struct commit *handle_commit(str /* * We'll handle the tagged object by looping or dropping * through to the non-tag handlers below. Do not - * propagate data from the tag's pending entry. + * propagate path data from the tag's pending entry. */ - name = ""; path = NULL; mode = 0; } @@@ -1100,10 -1042,14 +1044,10 @@@ static int limit_list(struct rev_info * } while (list) { - struct commit_list *entry = list; - struct commit *commit = list->item; + struct commit *commit = pop_commit(&list); struct object *obj = &commit->object; show_early_output_fn_t show; - list = list->next; - free(entry); - if (commit == interesting_cache) interesting_cache = NULL; @@@ -1994,10 -1940,10 +1938,10 @@@ static int handle_revision_opt(struct r } else if (!strcmp(arg, "--full-history")) { revs->simplify_history = 0; } else if (!strcmp(arg, "--relative-date")) { - revs->date_mode = DATE_RELATIVE; + revs->date_mode.type = DATE_RELATIVE; revs->date_mode_explicit = 1; } else if ((argcount = parse_long_opt("date", argv, &optarg))) { - revs->date_mode = parse_date_format(optarg); + parse_date_format(optarg, &revs->date_mode); revs->date_mode_explicit = 1; return argcount; } else if (!strcmp(arg, "--log-size")) { @@@ -2074,23 -2020,14 +2018,23 @@@ void parse_revision_opt(struct rev_inf ctx->argc -= n; } +static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data, const char *term) { + struct strbuf bisect_refs = STRBUF_INIT; + int status; + strbuf_addf(&bisect_refs, "refs/bisect/%s", term); + status = for_each_ref_in_submodule(submodule, bisect_refs.buf, fn, cb_data); + strbuf_release(&bisect_refs); + return status; +} + static int for_each_bad_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data) { - return for_each_ref_in_submodule(submodule, "refs/bisect/bad", fn, cb_data); + return for_each_bisect_ref(submodule, fn, cb_data, term_bad); } static int for_each_good_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_data) { - return for_each_ref_in_submodule(submodule, "refs/bisect/good", fn, cb_data); + return for_each_bisect_ref(submodule, fn, cb_data, term_good); } static int handle_revision_pseudo_opt(const char *submodule, @@@ -2119,7 -2056,6 +2063,7 @@@ handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule); clear_ref_exclusion(&revs->ref_excludes); } else if (!strcmp(arg, "--bisect")) { + read_bisect_terms(&term_bad, &term_good); handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref); handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref); revs->bisect = 1; @@@ -2727,7 -2663,10 +2671,7 @@@ static void simplify_merges(struct rev_ yet_to_do = NULL; tail = &yet_to_do; while (list) { - commit = list->item; - next = list->next; - free(list); - list = next; + commit = pop_commit(&list); tail = simplify_one(revs, commit, tail); } } @@@ -2739,7 -2678,10 +2683,7 @@@ while (list) { struct merge_simplify_state *st; - commit = list->item; - next = list->next; - free(list); - list = next; + commit = pop_commit(&list); st = locate_simplify_state(revs, commit); if (st->simplified == commit) tail = &commit_list_insert(commit, tail)->next; @@@ -3113,7 -3055,11 +3057,7 @@@ static struct commit *get_revision_1(st return NULL; do { - struct commit_list *entry = revs->commits; - struct commit *commit = entry->item; - - revs->commits = entry->next; - free(entry); + struct commit *commit = pop_commit(&revs->commits); if (revs->reflog_info) { save_parents(revs, commit); diff --combined revision.h index 5bc9686846,1b58aacc03..9741302801 --- a/revision.h +++ b/revision.h @@@ -146,7 -146,7 +146,7 @@@ struct rev_info track_first_time:1, linear:1; - enum date_mode date_mode; + struct date_mode date_mode; unsigned int abbrev; enum cmit_fmt commit_format; @@@ -256,16 -256,9 +256,9 @@@ extern void put_revision_mark(const str extern void mark_parents_uninteresting(struct commit *commit); extern void mark_tree_uninteresting(struct tree *tree); - struct name_path { - struct name_path *up; - int elem_len; - const char *elem; - }; - - char *path_name(const struct name_path *path, const char *name); + char *path_name(struct strbuf *path, const char *name); - extern void show_object_with_name(FILE *, struct object *, - const struct name_path *, const char *); + extern void show_object_with_name(FILE *, struct object *, const char *); extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name);