unpack_entry: avoid freeing objects in base cache
commit756a042600a3e234e7f1eae92c84d395c6833c6d
authorThomas Rast <trast@inf.ethz.ch>
Tue, 30 Apr 2013 12:53:06 +0000 (30 14:53 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 30 Apr 2013 22:43:48 +0000 (30 15:43 -0700)
tree6d330e2e7de3dcf576d466e67a91851bae74a437
parentabe601bba52ee6b0bf89d282aa1c3ef5fd89cbb0
unpack_entry: avoid freeing objects in base cache

In the !delta_data error path of unpack_entry(), we run free(base).
This became a window for use-after-free() in abe601b (sha1_file:
remove recursion in unpack_entry, 2013-03-27), as follows:

Before abe601b, we got the 'base' from cache_or_unpack_entry(..., 0);
keep_cache=0 tells it to also remove that entry.  So the 'base' is at
this point not cached, and freeing it in the error path is the right
thing.

After abe601b, the structure changed: we use a three-phase approach
where phase 1 finds the innermost base or a base that is already in
the cache.  In phase 3 we therefore know that all bases we unpack are
not part of the delta cache yet.  (Observe that we pop from the cache
in phase 1, so this is also true for the very first base.)  So we make
no further attempts to look up the bases in the cache, and just call
add_delta_base_cache() on every base object we have assembled.

But the !delta_data error path remained unchanged, and now calls
free() on a base that has already been entered in the cache.  This
means that there is a use-after-free if we later use the same base
again.

So remove that free(); we are still going to use that data.

Reported-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Thomas Rast <trast@inf.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sha1_file.c