Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit c63d196

Browse files
committed
fixup! git tag --contains : avoid stack overflow
1 parent 2ec943a commit c63d196

File tree

2 files changed

+19
-11
lines changed

2 files changed

+19
-11
lines changed

builtin/tag.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,17 @@ static int in_commit_list(const struct commit_list *want, struct commit *c)
7373
return 0;
7474
}
7575

76+
enum contains_result {
77+
CONTAINS_UNKNOWN = -1,
78+
CONTAINS_NO = 0,
79+
CONTAINS_YES = 1,
80+
};
81+
7682
/*
7783
* Test whether the candidate or one of its parents is contained in the list.
7884
* Do not recurse to find out, though, but return -1 if inconclusive.
7985
*/
80-
static int contains_test(struct commit *candidate,
86+
static enum contains_result contains_test(struct commit *candidate,
8187
const struct commit_list *want)
8288
{
8389
/* was it previously marked as containing a want commit? */
@@ -121,12 +127,13 @@ static void push_to_stack(struct commit *candidate, struct stack *stack)
121127
stack->stack[index].parents = candidate->parents;
122128
}
123129

124-
static int contains(struct commit *candidate, const struct commit_list *want)
130+
static enum contains_result contains(struct commit *candidate,
131+
const struct commit_list *want)
125132
{
126133
struct stack stack = { 0, 0, NULL };
127134
int result = contains_test(candidate, want);
128135

129-
if (result >= 0)
136+
if (result != CONTAINS_UNKNOWN)
130137
return result;
131138

132139
push_to_stack(candidate, &stack);
@@ -136,22 +143,22 @@ static int contains(struct commit *candidate, const struct commit_list *want)
136143
struct commit_list *parents = entry->parents;
137144

138145
if (!parents) {
139-
commit->object.flags = UNINTERESTING;
146+
commit->object.flags |= UNINTERESTING;
140147
stack.nr--;
141148
}
142149
/*
143150
* If we just popped the stack, parents->item has been marked,
144151
* therefore contains_test will return a meaningful 0 or 1.
145152
*/
146153
else switch (contains_test(parents->item, want)) {
147-
case 1:
154+
case CONTAINS_YES:
148155
commit->object.flags |= TMP_MARK;
149156
stack.nr--;
150157
break;
151-
case 0:
158+
case CONTAINS_NO:
152159
entry->parents = parents->next;
153160
break;
154-
default:
161+
case CONTAINS_UNKNOWN:
155162
push_to_stack(parents->item, &stack);
156163
break;
157164
}

t/t7004-tag.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,10 +1380,11 @@ test_expect_success 'multiple --points-at are OR-ed together' '
13801380
test_cmp expect actual
13811381
'
13821382
1383+
test_lazy_prereq BASH 'bash --version'
1384+
13831385
>expect
1384-
# ulimit is a bash builtin; we can rely on that in MinGW, but nowhere else
1385-
test_expect_success MINGW '--contains works in a deep repo' '
1386-
ulimit -s 64
1386+
# we require bash for its 'ulimit' builtin
1387+
test_expect_success BASH '--contains works in a deep repo' '
13871388
i=1 &&
13881389
while test $i -lt 1000
13891390
do
@@ -1397,7 +1398,7 @@ EOF"
13971398
done | git fast-import &&
13981399
git checkout master &&
13991400
git tag far-far-away HEAD^ &&
1400-
git tag --contains HEAD >actual &&
1401+
bash -c "ulimit -s 64 && git tag --contains HEAD >actual" &&
14011402
test_cmp expect actual
14021403
'
14031404

0 commit comments

Comments
 (0)