Merge branch 'maint-1.6.0' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 1 Feb 2009 01:42:17 +0000 (17:42 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 1 Feb 2009 01:42:17 +0000 (17:42 -0800)
* maint-1.6.0:
merge: fix out-of-bounds memory access

1  2 
unpack-trees.c
diff --combined unpack-trees.c
index 15c9ef592b393410354496c577a6e8c2dfb39940,4229eec1235842cf3432e4d5707b0e75845708b1..3a4e181af43add517a7a86511c17e4198552289c
@@@ -240,8 -240,11 +240,11 @@@ static struct cache_entry *create_ce_en
        return ce;
  }
  
- static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmask, struct cache_entry *src[5],
-       const struct name_entry *names, const struct traverse_info *info)
+ static int unpack_nondirectories(int n, unsigned long mask,
+                                unsigned long dirmask,
+                                struct cache_entry **src,
+                                const struct name_entry *names,
+                                const struct traverse_info *info)
  {
        int i;
        struct unpack_trees_options *o = info->data;
  
  static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
  {
-       struct cache_entry *src[5] = { NULL, };
+       struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
        struct unpack_trees_options *o = info->data;
        const struct name_entry *p = names;
  
@@@ -494,7 -497,7 +497,7 @@@ static int verify_clean_subdirectory(st
         * anything in the existing directory there.
         */
        int namelen;
 -      int pos, i;
 +      int i;
        struct dir_struct d;
        char *pathbuf;
        int cnt = 0;
         * in that directory.
         */
        namelen = strlen(ce->name);
 -      pos = index_name_pos(o->src_index, ce->name, namelen);
 -      if (0 <= pos)
 -              return cnt; /* we have it as nondirectory */
 -      pos = -pos - 1;
 -      for (i = pos; i < o->src_index->cache_nr; i++) {
 -              struct cache_entry *ce = o->src_index->cache[i];
 -              int len = ce_namelen(ce);
 +      for (i = o->pos; i < o->src_index->cache_nr; i++) {
 +              struct cache_entry *ce2 = o->src_index->cache[i];
 +              int len = ce_namelen(ce2);
                if (len < namelen ||
 -                  strncmp(ce->name, ce->name, namelen) ||
 -                  ce->name[namelen] != '/')
 +                  strncmp(ce->name, ce2->name, namelen) ||
 +                  ce2->name[namelen] != '/')
                        break;
                /*
 -               * ce->name is an entry in the subdirectory.
 +               * ce2->name is an entry in the subdirectory.
                 */
 -              if (!ce_stage(ce)) {
 -                      if (verify_uptodate(ce, o))
 +              if (!ce_stage(ce2)) {
 +                      if (verify_uptodate(ce2, o))
                                return -1;
 -                      add_entry(o, ce, CE_REMOVE, 0);
 +                      add_entry(o, ce2, CE_REMOVE, 0);
                }
                cnt++;
        }
@@@ -584,7 -591,7 +587,7 @@@ static int verify_absent(struct cache_e
                return 0;
  
        if (!lstat(ce->name, &st)) {
 -              int cnt;
 +              int ret;
                int dtype = ce_to_dtype(ce);
                struct cache_entry *result;
  
                         * files that are in "foo/" we would lose
                         * it.
                         */
 -                      cnt = verify_clean_subdirectory(ce, action, o);
 +                      ret = verify_clean_subdirectory(ce, action, o);
 +                      if (ret < 0)
 +                              return ret;
  
                        /*
                         * If this removed entries from the index,
                         * what that means is:
                         *
 -                       * (1) the caller unpack_trees_rec() saw path/foo
 +                       * (1) the caller unpack_callback() saw path/foo
                         * in the index, and it has not removed it because
                         * it thinks it is handling 'path' as blob with
                         * D/F conflict;
                         * We need to increment it by the number of
                         * deleted entries here.
                         */
 -                      o->pos += cnt;
 +                      o->pos += ret;
                        return 0;
                }