Merge branch 'ar/maint-mksnpath' into HEAD
authorJunio C Hamano <gitster@pobox.com>
Mon, 27 Oct 2008 05:24:44 +0000 (22:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 27 Oct 2008 05:24:44 +0000 (22:24 -0700)
* ar/maint-mksnpath:
Fix potentially dangerous uses of mkpath and git_path
Fix mkpath abuse in dwim_ref and dwim_log of sha1_name.c
Add mksnpath which allows you to specify the output buffer

1  2 
builtin-apply.c
cache.h
sha1_name.c
diff --combined builtin-apply.c
index cfd8fceb9033cf5c4c7924d96437b94a9c4fe226,50b623e54c003fb5bbe183568d13f496c3c41c25..4c4d1e1774ade358dbc3283df5d1b764a32821b8
@@@ -321,12 -321,13 +321,12 @@@ static char *find_name(const char *line
        const char *start = line;
  
        if (*line == '"') {
 -              struct strbuf name;
 +              struct strbuf name = STRBUF_INIT;
  
                /*
                 * Proposed "new-style" GNU patch/diff format; see
                 * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
                 */
 -              strbuf_init(&name, 0);
                if (!unquote_c_style(&name, line, NULL)) {
                        char *cp;
  
@@@ -674,8 -675,11 +674,8 @@@ static char *git_header_name(char *line
  
        if (*line == '"') {
                const char *cp;
 -              struct strbuf first;
 -              struct strbuf sp;
 -
 -              strbuf_init(&first, 0);
 -              strbuf_init(&sp, 0);
 +              struct strbuf first = STRBUF_INIT;
 +              struct strbuf sp = STRBUF_INIT;
  
                if (unquote_c_style(&first, line, &second))
                        goto free_and_fail1;
         */
        for (second = name; second < line + llen; second++) {
                if (*second == '"') {
 -                      struct strbuf sp;
 +                      struct strbuf sp = STRBUF_INIT;
                        const char *np;
  
 -                      strbuf_init(&sp, 0);
                        if (unquote_c_style(&sp, second, NULL))
                                goto free_and_fail2;
  
@@@ -1510,10 -1515,11 +1510,10 @@@ static const char minuses[]
  
  static void show_stats(struct patch *patch)
  {
 -      struct strbuf qname;
 +      struct strbuf qname = STRBUF_INIT;
        char *cp = patch->new_name ? patch->new_name : patch->old_name;
        int max, add, del;
  
 -      strbuf_init(&qname, 0);
        quote_c_style(cp, &qname, NULL, 0);
  
        /*
@@@ -2293,12 -2299,14 +2293,12 @@@ static void add_to_fn_table(struct patc
  
  static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
  {
 -      struct strbuf buf;
 +      struct strbuf buf = STRBUF_INIT;
        struct image image;
        size_t len;
        char *img;
        struct patch *tpatch;
  
 -      strbuf_init(&buf, 0);
 -
        if (!(patch->is_copy || patch->is_rename) &&
            ((tpatch = in_fn_table(patch->old_name)) != NULL)) {
                if (tpatch == (struct patch *) -1) {
@@@ -2778,7 -2786,7 +2778,7 @@@ static void add_index_file(const char *
  static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
  {
        int fd;
 -      struct strbuf nbuf;
 +      struct strbuf nbuf = STRBUF_INIT;
  
        if (S_ISGITLINK(mode)) {
                struct stat st;
        if (fd < 0)
                return -1;
  
 -      strbuf_init(&nbuf, 0);
        if (convert_to_working_tree(path, buf, size, &nbuf)) {
                size = nbuf.len;
                buf  = nbuf.buf;
@@@ -2841,8 -2850,8 +2841,8 @@@ static void create_one_file(char *path
                unsigned int nr = getpid();
  
                for (;;) {
-                       const char *newpath;
-                       newpath = mkpath("%s~%u", path, nr);
+                       char newpath[PATH_MAX];
+                       mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
                        if (!try_create_file(newpath, mode, buf, size)) {
                                if (!rename(newpath, path))
                                        return;
@@@ -2987,45 -2996,29 +2987,45 @@@ static int write_out_results(struct pat
  
  static struct lock_file lock_file;
  
 -static struct excludes {
 -      struct excludes *next;
 -      const char *path;
 -} *excludes;
 +static struct string_list limit_by_name;
 +static int has_include;
 +static void add_name_limit(const char *name, int exclude)
 +{
 +      struct string_list_item *it;
 +
 +      it = string_list_append(name, &limit_by_name);
 +      it->util = exclude ? NULL : (void *) 1;
 +}
  
  static int use_patch(struct patch *p)
  {
        const char *pathname = p->new_name ? p->new_name : p->old_name;
 -      struct excludes *x = excludes;
 -      while (x) {
 -              if (fnmatch(x->path, pathname, 0) == 0)
 -                      return 0;
 -              x = x->next;
 -      }
 +      int i;
 +
 +      /* Paths outside are not touched regardless of "--include" */
        if (0 < prefix_length) {
                int pathlen = strlen(pathname);
                if (pathlen <= prefix_length ||
                    memcmp(prefix, pathname, prefix_length))
                        return 0;
        }
 -      return 1;
 +
 +      /* See if it matches any of exclude/include rule */
 +      for (i = 0; i < limit_by_name.nr; i++) {
 +              struct string_list_item *it = &limit_by_name.items[i];
 +              if (!fnmatch(it->string, pathname, 0))
 +                      return (it->util != NULL);
 +      }
 +
 +      /*
 +       * If we had any include, a path that does not match any rule is
 +       * not used.  Otherwise, we saw bunch of exclude rules (or none)
 +       * and such a path is used.
 +       */
 +      return !has_include;
  }
  
 +
  static void prefix_one(char **name)
  {
        char *old_name = *name;
@@@ -3058,12 -3051,13 +3058,12 @@@ static void prefix_patches(struct patc
  static int apply_patch(int fd, const char *filename, int options)
  {
        size_t offset;
 -      struct strbuf buf;
 +      struct strbuf buf = STRBUF_INIT;
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
  
        /* FIXME - memory leak when using multiple patch files as inputs */
        memset(&fn_table, 0, sizeof(struct string_list));
 -      strbuf_init(&buf, 0);
        patch_input_file = filename;
        read_patch_file(&buf, fd);
        offset = 0;
@@@ -3165,12 -3159,10 +3165,12 @@@ int cmd_apply(int argc, const char **ar
                        continue;
                }
                if (!prefixcmp(arg, "--exclude=")) {
 -                      struct excludes *x = xmalloc(sizeof(*x));
 -                      x->path = arg + 10;
 -                      x->next = excludes;
 -                      excludes = x;
 +                      add_name_limit(arg + 10, 1);
 +                      continue;
 +              }
 +              if (!prefixcmp(arg, "--include=")) {
 +                      add_name_limit(arg + 10, 0);
 +                      has_include = 1;
                        continue;
                }
                if (!prefixcmp(arg, "-p")) {
diff --combined cache.h
index b0edbf9b9f68a98a0052ecb949f20aafb3125e56,aea13b0822d56546f30a02eb366524e6993c55df..629cdf3971f0e55fc34b7b5f43e5b4ea225e5be4
+++ b/cache.h
@@@ -6,14 -6,8 +6,14 @@@
  #include "hash.h"
  
  #include SHA1_HEADER
 -#include <zlib.h>
 +#ifndef git_SHA_CTX
 +#define git_SHA_CTX   SHA_CTX
 +#define git_SHA1_Init SHA1_Init
 +#define git_SHA1_Update       SHA1_Update
 +#define git_SHA1_Final        SHA1_Final
 +#endif
  
 +#include <zlib.h>
  #if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
  #define deflateBound(c,s)  ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
  #endif
@@@ -132,7 -126,6 +132,7 @@@ struct cache_entry 
  
  #define CE_NAMEMASK  (0x0fff)
  #define CE_STAGEMASK (0x3000)
 +#define CE_EXTENDED  (0x4000)
  #define CE_VALID     (0x8000)
  #define CE_STAGESHIFT 12
  
@@@ -277,7 -270,6 +277,7 @@@ static inline void remove_name_hash(str
  #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
  #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
  #define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
 +#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
  #endif
  
  enum object_type {
@@@ -320,7 -312,6 +320,7 @@@ extern int is_bare_repository(void)
  extern int is_inside_git_dir(void);
  extern char *git_work_tree_cfg;
  extern int is_inside_work_tree(void);
 +extern int have_git_dir(void);
  extern const char *get_git_dir(void);
  extern char *get_object_directory(void);
  extern char *get_index_file(void);
@@@ -379,7 -370,6 +379,7 @@@ extern int index_name_pos(const struct 
  #define ADD_CACHE_OK_TO_REPLACE 2     /* Ok to replace file/directory */
  #define ADD_CACHE_SKIP_DFCHECK 4      /* Ok to skip DF conflict checks */
  #define ADD_CACHE_JUST_APPEND 8               /* Append only; tree.c::read_tree() */
 +#define ADD_CACHE_NEW_ONLY 16         /* Do not replace existing ones */
  extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
  extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
@@@ -388,13 -378,10 +388,13 @@@ extern int remove_file_from_index(struc
  #define ADD_CACHE_VERBOSE 1
  #define ADD_CACHE_PRETEND 2
  #define ADD_CACHE_IGNORE_ERRORS       4
 +#define ADD_CACHE_IGNORE_REMOVAL 8
 +#define ADD_CACHE_INTENT 16
  extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
  extern int add_file_to_index(struct index_state *, const char *path, int flags);
  extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
  extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
 +extern int index_name_is_other(const struct index_state *, const char *, int);
  
  /* do stat comparison even if CE_VALID is true */
  #define CE_MATCH_IGNORE_VALID         01
@@@ -405,6 -392,7 +405,6 @@@ extern int ie_modified(const struct ind
  
  extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
  extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
 -extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
  extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
  extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
  
@@@ -423,8 -411,6 +423,8 @@@ struct lock_file 
        char on_list;
        char filename[PATH_MAX];
  };
 +#define LOCK_DIE_ON_ERROR 1
 +#define LOCK_NODEREF 2
  extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
  extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
  extern int commit_lock_file(struct lock_file *);
@@@ -466,7 -452,6 +466,7 @@@ enum safe_crlf 
  extern enum safe_crlf safe_crlf;
  
  enum branch_track {
 +      BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,
        BRANCH_TRACK_REMOTE,
        BRANCH_TRACK_ALWAYS,
@@@ -495,6 -480,9 +495,9 @@@ extern int check_repository_format(void
  #define DATA_CHANGED    0x0020
  #define TYPE_CHANGED    0x0040
  
+ extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+       __attribute__((format (printf, 3, 4)));
  /* Return a statically allocated filename matching the sha1 signature */
  extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
  extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
@@@ -519,7 -507,6 +522,7 @@@ static inline void hashclr(unsigned cha
  {
        memset(hash, 0, 20);
  }
 +extern int is_empty_blob_sha1(const unsigned char *sha1);
  
  int git_mkstemp(char *path, size_t n, const char *template);
  
@@@ -547,7 -534,6 +550,7 @@@ static inline int is_absolute_path(cons
  {
        return path[0] == '/' || has_dos_drive_prefix(path);
  }
 +int is_directory(const char *);
  const char *make_absolute_path(const char *path);
  const char *make_nonrelative_path(const char *path);
  const char *make_relative_path(const char *abs, const char *base);
@@@ -655,8 -641,6 +658,8 @@@ extern struct alternate_object_databas
  } *alt_odb_list;
  extern void prepare_alt_odb(void);
  extern void add_to_alternates_file(const char *reference);
 +typedef int alt_odb_fn(struct alternate_object_database *, void *);
 +extern void foreach_alt_odb(alt_odb_fn, void*);
  
  struct pack_window {
        struct pack_window *next;
@@@ -725,11 -709,7 +728,11 @@@ extern struct child_process *git_connec
  extern int finish_connect(struct child_process *conn);
  extern int path_match(const char *path, int nr, char **match);
  extern int get_ack(int fd, unsigned char *result_sha1);
 -extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags);
 +struct extra_have_objects {
 +      int nr, alloc;
 +      unsigned char (*array)[20];
 +};
 +extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, char **match, unsigned int flags, struct extra_have_objects *);
  extern int server_supports(const char *feature);
  
  extern struct packed_git *parse_pack_index(unsigned char *sha1);
@@@ -763,6 -743,7 +766,6 @@@ typedef int (*config_fn_t)(const char *
  extern int git_default_config(const char *, const char *, void *);
  extern int git_config_from_file(config_fn_t fn, const char *, void *);
  extern int git_config(config_fn_t fn, void *);
 -extern int git_parse_long(const char *, long *);
  extern int git_parse_ulong(const char *, unsigned long *);
  extern int git_config_int(const char *, const char *);
  extern unsigned long git_config_ulong(const char *, const char *);
diff --combined sha1_name.c
index 41b680915d7348bf622397da8b1465d3769a361a,75a5a7e96f292bed344a7609fca2f3a45ba4314e..159c2ab84fa2cdde0e540024a1ca22e0bbb43af8
@@@ -245,11 -245,13 +245,13 @@@ int dwim_ref(const char *str, int len, 
  
        *ref = NULL;
        for (p = ref_rev_parse_rules; *p; p++) {
+               char fullref[PATH_MAX];
                unsigned char sha1_from_ref[20];
                unsigned char *this_result;
  
                this_result = refs_found ? sha1_from_ref : sha1;
-               r = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL);
+               mksnpath(fullref, sizeof(fullref), *p, len, str);
+               r = resolve_ref(fullref, this_result, 1, NULL);
                if (r) {
                        if (!refs_found++)
                                *ref = xstrdup(r);
@@@ -272,7 -274,7 +274,7 @@@ int dwim_log(const char *str, int len, 
                char path[PATH_MAX];
                const char *ref, *it;
  
-               strcpy(path, mkpath(*p, len, str));
+               mksnpath(path, sizeof(path), *p, len, str);
                ref = resolve_ref(path, hash, 1, NULL);
                if (!ref)
                        continue;
@@@ -349,10 -351,7 +351,10 @@@ static int get_sha1_basic(const char *s
                        else
                                nth = -1;
                }
 -              if (0 <= nth)
 +              if (100000000 <= nth) {
 +                      at_time = nth;
 +                      nth = -1;
 +              } else if (0 <= nth)
                        at_time = 0;
                else {
                        char *tmp = xstrndup(str + at + 2, reflog_len);