From: Junio C Hamano Date: Wed, 16 Mar 2016 17:41:43 +0000 (-0700) Subject: Merge branch 'jk/path-name-safety-2.4' into jk/path-name-safety-2.5 X-Git-Tag: v2.8.0-rc3~2^2^2^2^2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/253ce7a15c251057464b130016c74cbe10fe9e57?ds=inline;hp=-c Merge branch 'jk/path-name-safety-2.4' into jk/path-name-safety-2.5 * jk/path-name-safety-2.4: 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 --- 253ce7a15c251057464b130016c74cbe10fe9e57 diff --combined builtin/pack-objects.c index 80fe8c7dc1,4af92f113c..53307d53b0 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@@ -540,11 -540,11 +540,11 @@@ static enum write_one_status write_one( return WRITE_ONE_WRITTEN; } -static int mark_tagged(const char *path, const unsigned char *sha1, int flag, +static int mark_tagged(const char *path, const struct object_id *oid, int flag, void *cb_data) { unsigned char peeled[20]; - struct object_entry *entry = packlist_find(&to_pack, sha1, NULL); + struct object_entry *entry = packlist_find(&to_pack, oid->hash, NULL); if (entry) entry->tagged = 1; @@@ -2097,14 -2097,14 +2097,14 @@@ static void ll_find_deltas(struct objec #define ll_find_deltas(l, s, w, d, p) find_deltas(l, &s, w, d, p) #endif -static int add_ref_tag(const char *path, const unsigned char *sha1, int flag, void *cb_data) +static int add_ref_tag(const char *path, const struct object_id *oid, int flag, void *cb_data) { - unsigned char peeled[20]; + struct object_id peeled; if (starts_with(path, "refs/tags/") && /* is a tag? */ - !peel_ref(path, peeled) && /* peelable? */ - packlist_find(&to_pack, peeled, NULL)) /* object packed? */ - add_object_entry(sha1, OBJ_TAG, NULL, 0); + !peel_ref(path, peeled.hash) && /* peelable? */ + packlist_find(&to_pack, peeled.hash, NULL)) /* object packed? */ + add_object_entry(oid->hash, OBJ_TAG, NULL, 0); return 0; } @@@ -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); diff --combined builtin/rev-list.c index d80d1ed359,7ae255862a..4c46341749 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@@ -177,9 -177,7 +177,7 @@@ static void finish_commit(struct commi free_commit_buffer(commit); } - static void finish_object(struct object *obj, - const struct name_path *path, const char *name, - void *cb_data) + static void finish_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1)) @@@ -188,15 -186,13 +186,13 @@@ parse_object(obj->sha1); } - static void show_object(struct object *obj, - const struct name_path *path, const char *component, - void *cb_data) + static void show_object(struct object *obj, const char *name, void *cb_data) { struct rev_list_info *info = cb_data; - finish_object(obj, path, component, cb_data); + finish_object(obj, name, cb_data); if (info->flags & REV_LIST_QUIET) return; - show_object_with_name(stdout, obj, path, component); + show_object_with_name(stdout, obj, name); } static void show_edge(struct commit *commit) @@@ -350,9 -346,6 +346,9 @@@ int cmd_rev_list(int argc, const char * revs.diff) usage(rev_list_usage); + if (revs.show_notes) + die(_("rev-list does not support display of notes")); + save_commit_buffer = (revs.verbose_header || revs.grep_filter.pattern_list || revs.grep_filter.header_list); diff --combined diff.h index c7ad42addf,561635b2b9..37e43bc537 --- a/diff.h +++ b/diff.h @@@ -6,7 -6,6 +6,7 @@@ #include "tree-walk.h" #include "pathspec.h" +#include "object.h" struct rev_info; struct diff_options; @@@ -138,11 -137,6 +138,11 @@@ struct diff_options int dirstat_permille; int setup; int abbrev; +/* white-space error highlighting */ +#define WSEH_NEW 1 +#define WSEH_CONTEXT 2 +#define WSEH_OLD 4 + unsigned ws_error_highlight; const char *prefix; int prefix_length; const char *stat_sep; @@@ -213,16 -207,16 +213,16 @@@ struct combine_diff_path struct combine_diff_path *next; char *path; unsigned int mode; - unsigned char sha1[20]; + struct object_id oid; struct combine_diff_parent { char status; unsigned int mode; - unsigned char sha1[20]; + struct object_id oid; } 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 076461e8c8,061e33c774..d20fa89d5f --- 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 @@@ -187,7 -195,6 +195,7 @@@ #elif defined(_MSC_VER) #include "compat/msvc.h" #else +#include #include #include #include @@@ -389,6 -396,7 +397,6 @@@ struct strbuf /* General helper functions */ extern void vreportf(const char *prefix, const char *err, va_list params); -extern void vwritef(int fd, const char *prefix, const char *err, va_list params); extern NORETURN void usage(const char *err); extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2))); extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2))); @@@ -424,7 -432,6 +432,7 @@@ static inline int const_error(void extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params)); extern void set_error_routine(void (*routine)(const char *err, va_list params)); extern void set_die_is_recursing_routine(int (*routine)(void)); +extern void set_error_handle(FILE *); extern int starts_with(const char *str, const char *prefix); @@@ -699,6 -706,32 +707,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)) @@@ -935,10 -968,4 +969,10 @@@ struct tm *git_gmtime_r(const time_t * # define SHELL_PATH "/bin/sh" #endif +#ifndef _POSIX_THREAD_SAFE_FUNCTIONS +#define flockfile(fh) +#define funlockfile(fh) +#define getc_unlocked(fh) getc(fh) +#endif + #endif diff --combined reachable.c index 9cff25b490,9b0295469f..59196253a6 --- a/reachable.c +++ b/reachable.c @@@ -22,10 -22,9 +22,10 @@@ static void update_progress(struct conn display_progress(cp->progress, cp->count); } -static int add_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) +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(sha1, path); + struct object *object = parse_object_or_die(oid->hash, path); struct rev_info *revs = (struct rev_info *)cb_data; add_pending_object(revs, object, ""); @@@ -37,15 -36,14 +37,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 9b9d77dc43,871812db2a..8f30ab1e46 --- a/revision.c +++ b/revision.c @@@ -21,69 -21,13 +21,13 @@@ volatile show_early_output_fn_t show_early_output; - 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); } @@@ -361,8 -305,8 +305,8 @@@ static int everybody_uninteresting(stru list = list->next; if (commit->object.flags & UNINTERESTING) continue; - if (interesting_cache) - *interesting_cache = commit; + + *interesting_cache = commit; return 0; } return 1; @@@ -1218,8 -1162,7 +1162,8 @@@ int ref_excluded(struct string_list *re return 0; } -static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) +static int handle_one_ref(const char *path, const struct object_id *oid, + int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; struct object *object; @@@ -1227,9 -1170,9 +1171,9 @@@ if (ref_excluded(cb->all_revs->ref_excludes, path)) return 0; - object = get_reference(cb->all_revs, path, sha1, cb->all_flags); + object = get_reference(cb->all_revs, path, oid->hash, cb->all_flags); add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags); - add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags); + add_pending_sha1(cb->all_revs, path, oid->hash, cb->all_flags); return 0; } @@@ -1293,8 -1236,7 +1237,8 @@@ static int handle_one_reflog_ent(unsign return 0; } -static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data) +static int handle_one_reflog(const char *path, const struct object_id *oid, + int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; cb->warned_bad_reflog = 0; @@@ -1306,7 -1248,6 +1250,7 @@@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags) { struct all_refs_cb cb; + cb.all_revs = revs; cb.all_flags = flags; for_each_reflog(handle_one_reflog, &cb); @@@ -2173,21 -2114,6 +2117,21 @@@ static int handle_revision_pseudo_opt(c return 1; } +static void NORETURN diagnose_missing_default(const char *def) +{ + unsigned char sha1[20]; + int flags; + const char *refname; + + refname = resolve_ref_unsafe(def, 0, sha1, &flags); + if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN)) + die(_("your current branch appears to be broken")); + + skip_prefix(refname, "refs/heads/", &refname); + die(_("your current branch '%s' does not have any commits yet"), + refname); +} + /* * Parse revision information, filling in the "rev_info" structure, * and removing the used arguments from the argument list. @@@ -2317,7 -2243,7 +2261,7 @@@ int setup_revisions(int argc, const cha struct object *object; struct object_context oc; if (get_sha1_with_context(revs->def, 0, sha1, &oc)) - die("bad default revision '%s'", revs->def); + diagnose_missing_default(revs->def); object = get_reference(revs, revs->def, sha1, 0); add_pending_object_with_mode(revs, object, revs->def, oc.mode); } diff --combined tree-diff.c index 290a1da4ce,4b32d40677..4dda9a14ab --- a/tree-diff.c +++ b/tree-diff.c @@@ -64,7 -64,7 +64,7 @@@ static int emit_diff_first_parent_only( { struct combine_diff_parent *p0 = &p->parent[0]; if (p->mode && p0->mode) { - opt->change(opt, p0->mode, p->mode, p0->sha1, p->sha1, + opt->change(opt, p0->mode, p->mode, p0->oid.hash, p->oid.hash, 1, 1, p->path, 0, 0); } else { @@@ -74,11 -74,11 +74,11 @@@ if (p->mode) { addremove = '+'; - sha1 = p->sha1; + sha1 = p->oid.hash; mode = p->mode; } else { addremove = '-'; - sha1 = p0->sha1; + sha1 = p0->oid.hash; mode = p0->mode; } @@@ -124,8 -124,8 +124,8 @@@ static struct combine_diff_path *path_a unsigned mode, const unsigned char *sha1) { struct combine_diff_path *p; - int len = base->len + pathlen; - int alloclen = combine_diff_path_size(nparent, len); + size_t len = st_add(base->len, pathlen); + size_t alloclen = combine_diff_path_size(nparent, len); /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */ p = last->next; @@@ -151,7 -151,7 +151,7 @@@ memcpy(p->path + base->len, path, pathlen); p->path[len] = 0; p->mode = mode; - hashcpy(p->sha1, sha1 ? sha1 : null_sha1); + hashcpy(p->oid.hash, sha1 ? sha1 : null_sha1); return p; } @@@ -238,7 -238,7 +238,7 @@@ static struct combine_diff_path *emit_p } p->parent[i].mode = mode_i; - hashcpy(p->parent[i].sha1, sha1_i ? sha1_i : null_sha1); + hashcpy(p->parent[i].oid.hash, sha1_i ? sha1_i : null_sha1); } keep = 1;