fixup! git tag --contains : avoid stack overflow

This commit is contained in:
Johannes Schindelin
2014-04-17 12:18:57 -05:00
parent 2ec943a028
commit c63d196ece
2 changed files with 19 additions and 11 deletions

View File

@@ -73,11 +73,17 @@ static int in_commit_list(const struct commit_list *want, struct commit *c)
return 0;
}
enum contains_result {
CONTAINS_UNKNOWN = -1,
CONTAINS_NO = 0,
CONTAINS_YES = 1,
};
/*
* Test whether the candidate or one of its parents is contained in the list.
* Do not recurse to find out, though, but return -1 if inconclusive.
*/
static int contains_test(struct commit *candidate,
static enum contains_result contains_test(struct commit *candidate,
const struct commit_list *want)
{
/* was it previously marked as containing a want commit? */
@@ -121,12 +127,13 @@ static void push_to_stack(struct commit *candidate, struct stack *stack)
stack->stack[index].parents = candidate->parents;
}
static int contains(struct commit *candidate, const struct commit_list *want)
static enum contains_result contains(struct commit *candidate,
const struct commit_list *want)
{
struct stack stack = { 0, 0, NULL };
int result = contains_test(candidate, want);
if (result >= 0)
if (result != CONTAINS_UNKNOWN)
return result;
push_to_stack(candidate, &stack);
@@ -136,7 +143,7 @@ static int contains(struct commit *candidate, const struct commit_list *want)
struct commit_list *parents = entry->parents;
if (!parents) {
commit->object.flags = UNINTERESTING;
commit->object.flags |= UNINTERESTING;
stack.nr--;
}
/*
@@ -144,14 +151,14 @@ static int contains(struct commit *candidate, const struct commit_list *want)
* therefore contains_test will return a meaningful 0 or 1.
*/
else switch (contains_test(parents->item, want)) {
case 1:
case CONTAINS_YES:
commit->object.flags |= TMP_MARK;
stack.nr--;
break;
case 0:
case CONTAINS_NO:
entry->parents = parents->next;
break;
default:
case CONTAINS_UNKNOWN:
push_to_stack(parents->item, &stack);
break;
}

View File

@@ -1380,10 +1380,11 @@ test_expect_success 'multiple --points-at are OR-ed together' '
test_cmp expect actual
'
test_lazy_prereq BASH 'bash --version'
>expect
# ulimit is a bash builtin; we can rely on that in MinGW, but nowhere else
test_expect_success MINGW '--contains works in a deep repo' '
ulimit -s 64
# we require bash for its 'ulimit' builtin
test_expect_success BASH '--contains works in a deep repo' '
i=1 &&
while test $i -lt 1000
do
@@ -1397,7 +1398,7 @@ EOF"
done | git fast-import &&
git checkout master &&
git tag far-far-away HEAD^ &&
git tag --contains HEAD >actual &&
bash -c "ulimit -s 64 && git tag --contains HEAD >actual" &&
test_cmp expect actual
'