Skip to content

Commit 6b763c4

Browse files
committed
git-apply: do not read past the end of buffer
When the preimage we are patching is shorter than what the patch text expects, we tried to match the buffer contents at the "original" line with the fragment in full, without checking we have enough data to match in the preimage. This caused the size of a later memmove() to wrap around and attempt to scribble almost the entire address space. Not good. The code that follows the part this patch touches tries to match the fragment with line offsets. Curiously, that code does not have the problem --- it guards against reading past the end of the preimage. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 5587cac commit 6b763c4

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

builtin-apply.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1514,7 +1514,8 @@ static int find_offset(const char *buf, unsigned long size, const char *fragment
15141514
}
15151515

15161516
/* Exact line number? */
1517-
if (!memcmp(buf + start, fragment, fragsize))
1517+
if ((start + fragsize <= size) &&
1518+
!memcmp(buf + start, fragment, fragsize))
15181519
return start;
15191520

15201521
/*

t/t4123-apply-shrink.sh

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/bin/sh
2+
3+
test_description='apply a patch that is larger than the preimage'
4+
5+
. ./test-lib.sh
6+
7+
cat >F <<\EOF
8+
1
9+
2
10+
3
11+
4
12+
5
13+
6
14+
7
15+
8
16+
999999
17+
A
18+
B
19+
C
20+
D
21+
E
22+
F
23+
G
24+
H
25+
I
26+
J
27+
28+
EOF
29+
30+
test_expect_success setup '
31+
32+
git add F &&
33+
mv F G &&
34+
sed -e "s/1/11/" -e "s/999999/9/" -e "s/H/HH/" <G >F &&
35+
git diff >patch &&
36+
sed -e "/^\$/d" <G >F &&
37+
git add F
38+
39+
'
40+
41+
test_expect_success 'apply should fail gracefully' '
42+
43+
if git apply --index patch
44+
then
45+
echo Oops, should not have succeeded
46+
false
47+
else
48+
status=$?
49+
echo "Status was $status"
50+
if test -f .git/index.lock
51+
then
52+
echo Oops, should not have crashed
53+
false
54+
fi
55+
fi
56+
'
57+
58+
test_done

0 commit comments

Comments
 (0)