From: "René Scharfe" <rene.scharfe@lsrfire.ath.cx>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [RFH] unpack-trees: cache_entry lifetime issue?
Date: Fri, 02 Mar 2012 18:25:54 +0100 [thread overview]
Message-ID: <4F5102A2.70303@lsrfire.ath.cx> (raw)
Hello,
below is the output of "git grep -hnW unpack_nondirectories",
which shows some parts of unpack-trees.c that I use as context to
ask: Should we check for o->merge in line 775, before using src[0]?
If o->merge is 0, the src[0] will be NULL right up to the call of
unpack_nondirectories() in line 772. There it may be set (in line
582). In that case we'll end up at line 779, where mark_ce_used()
is applied to it.
I suspect that this is unintended and that line 775 should rather
read "if (o->merge && src[0]) {". Can someone with a better
understanding of unpack-trees confirm or refute that suspicion?
Thanks,
René
542:static int unpack_nondirectories(int n, unsigned long mask,
543- unsigned long dirmask,
544- struct cache_entry **src,
545- const struct name_entry *names,
546- const struct traverse_info *info)
547-{
548- int i;
549- struct unpack_trees_options *o = info->data;
550- unsigned long conflicts;
551-
552- /* Do we have *only* directories? Nothing to do */
553- if (mask == dirmask && !src[0])
554- return 0;
555-
556- conflicts = info->conflicts;
557- if (o->merge)
558- conflicts >>= 1;
559- conflicts |= dirmask;
560-
561- /*
562- * Ok, we've filled in up to any potential index entry in src[0],
563- * now do the rest.
564- */
565- for (i = 0; i < n; i++) {
566- int stage;
567- unsigned int bit = 1ul << i;
568- if (conflicts & bit) {
569- src[i + o->merge] = o->df_conflict_entry;
570- continue;
571- }
572- if (!(mask & bit))
573- continue;
574- if (!o->merge)
575- stage = 0;
576- else if (i + 1 < o->head_idx)
577- stage = 1;
578- else if (i + 1 > o->head_idx)
579- stage = 3;
580- else
581- stage = 2;
582- src[i + o->merge] = create_ce_entry(info, names + i, stage);
583- }
584-
585- if (o->merge)
586- return call_unpack_fn(src, o);
587-
588- for (i = 0; i < n; i++)
589- if (src[i] && src[i] != o->df_conflict_entry)
590- add_entry(o, src[i], 0, 0);
591- return 0;
592-}
593-
--
721=static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info)
722-{
723- struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
724- struct unpack_trees_options *o = info->data;
725- const struct name_entry *p = names;
726-
727- /* Find first entry with a real name (we could use "mask" too) */
728- while (!p->mode)
729- p++;
730-
731- if (o->debug_unpack)
732- debug_unpack_callback(n, mask, dirmask, names, info);
733-
734- /* Are we supposed to look at the index too? */
735- if (o->merge) {
736- while (1) {
737- int cmp;
738- struct cache_entry *ce;
739-
740- if (o->diff_index_cached)
741- ce = next_cache_entry(o);
742- else
743- ce = find_cache_entry(info, p);
744-
745- if (!ce)
746- break;
747- cmp = compare_entry(ce, info, p);
748- if (cmp < 0) {
749- if (unpack_index_entry(ce, o) < 0)
750- return unpack_failed(o, NULL);
751- continue;
752- }
753- if (!cmp) {
754- if (ce_stage(ce)) {
755- /*
756- * If we skip unmerged index
757- * entries, we'll skip this
758- * entry *and* the tree
759- * entries associated with it!
760- */
761- if (o->skip_unmerged) {
762- add_same_unmerged(ce, o);
763- return mask;
764- }
765- }
766- src[0] = ce;
767- }
768- break;
769- }
770- }
771-
772: if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0)
773- return -1;
774-
775- if (src[0]) {
776- if (ce_stage(src[0]))
777- mark_ce_used_same_name(src[0], o);
778- else
779- mark_ce_used(src[0], o);
780- }
781-
782- /* Now handle any directories.. */
783- if (dirmask) {
784- unsigned long conflicts = mask & ~dirmask;
785- if (o->merge) {
786- conflicts <<= 1;
787- if (src[0])
788- conflicts |= 1;
789- }
790-
791- /* special case: "diff-index --cached" looking at a tree */
792- if (o->diff_index_cached &&
793- n == 1 && dirmask == 1 && S_ISDIR(names->mode)) {
794- int matches;
795- matches = cache_tree_matches_traversal(o->src_index->cache_tree,
796- names, info);
797- /*
798- * Everything under the name matches; skip the
799- * entire hierarchy. diff_index_cached codepath
800- * special cases D/F conflicts in such a way that
801- * it does not do any look-ahead, so this is safe.
802- */
803- if (matches) {
804- o->cache_bottom += matches;
805- return mask;
806- }
807- }
808-
809- if (traverse_trees_recursive(n, dirmask, conflicts,
810- names, info) < 0)
811- return -1;
812- return mask;
813- }
814-
815- return mask;
816-}
817-
PS: These functions are a tad too long, aren't they? ;-)
next reply other threads:[~2012-03-02 17:26 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-02 17:25 René Scharfe [this message]
2012-03-02 19:17 ` [RFH] unpack-trees: cache_entry lifetime issue? Junio C Hamano
2012-03-03 14:14 ` René Scharfe
2012-03-05 22:01 ` Junio C Hamano
2012-03-06 19:37 ` René Scharfe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F5102A2.70303@lsrfire.ath.cx \
--to=rene.scharfe@lsrfire.ath.cx \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=pclouds@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).