@matheusbsbs / matheus-bagliano / commits / d8d2eb7d6b
Fork 0

mailmap: fix use of freed memory

On an x86_64 system (F13-based), I ran these commands in an empty directory: git init printf '%s\n' \ '<jdoe@example.com> <jdoe@example.COM>' \ 'John <jdoe@example.com>' > .mailmap git shortlog < /dev/null Here's the result: (reading log message from standard input) *** glibc detected *** git: free(): invalid pointer: 0x0000000000f53730 *** ======= Backtrace: ========= /lib64/libc.so.6[0x31ba875676] git[0x48c2a5] git[0x4b9858] ... zsh: abort (core dumped) git shortlog What happened? Some .mailmap entry is of the <email1> <email2> form, while a subsequent one looks like "User Name <Email2>, and the two email addresses on the right are not identical but are "equal" when using a case-insensitive comparator. Then, when add_mapping is processing the latter line, new_email is NULL and we free me->email, yet do not replace it with a new strdup'd string. Thus, when later we attempt to use the buffer behind that ->email pointer, we reference freed memory. The solution is to free ->email and ->name only if we're about to replace them. [jc: squashed in the tests from Jonathan] Signed-off-by: Jim Meyering <meyering@redhat.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jim Meyering committed Oct 11, 2010 at 17:41 UTC d8d2eb7d6b5e48c2bcb0e71a770f8a05375ac03e
2 files changed +44 -7
mailmap.c
+6 -4
@@ -79,12 +79,14 @@ static void add_mapping(struct string_list *map,
79 if (old_name == NULL) {
80 debug_mm("mailmap: adding (simple) entry for %s at index %d\n", old_email, index);
81 /* Replace current name and new email for simple entry */
82 - free(me->name);
83 - free(me->email);
84 - if (new_name)
82 + if (new_name) {
83 + free(me->name);
84 me->name = xstrdup(new_name);
86 - if (new_email)
85 + }
86 + if (new_email) {
87 + free(me->email);
88 me->email = xstrdup(new_email);
89 + }
90 } else {
91 struct mailmap_info *mi = xmalloc(sizeof(struct mailmap_info));
92 debug_mm("mailmap: adding (complex) entry for %s at index %d\n", old_email, index);
t/t4203-mailmap.sh
+38 -3
@@ -11,6 +11,7 @@ test_expect_success setup '
11 git commit -m initial &&
12 echo two >>one &&
13 git add one &&
14 + test_tick &&
15 git commit --author "nick1 <bugs@company.xx>" -m second
16 '
17
@@ -54,7 +55,7 @@ Repo Guy (1):
55
56 EOF
57 test_expect_success 'mailmap.file set' '
57 - mkdir internal_mailmap &&
58 + mkdir -p internal_mailmap &&
59 echo "Internal Guy <bugs@company.xx>" > internal_mailmap/.mailmap &&
60 git config mailmap.file internal_mailmap/.mailmap &&
61 git shortlog HEAD >actual &&
@@ -92,6 +93,40 @@ test_expect_success 'mailmap.file non-existant' '
93 test_cmp expect actual
94 '
95
96 +cat >expect <<\EOF
97 +Internal Guy (1):
98 + second
99 +
100 +Repo Guy (1):
101 + initial
102 +
103 +EOF
104 +
105 +test_expect_success 'name entry after email entry' '
106 + mkdir -p internal_mailmap &&
107 + echo "<bugs@company.xy> <bugs@company.xx>" >internal_mailmap/.mailmap &&
108 + echo "Internal Guy <bugs@company.xx>" >>internal_mailmap/.mailmap &&
109 + git shortlog >actual &&
110 + test_cmp expect actual
111 +'
112 +
113 +cat >expect <<\EOF
114 +Internal Guy (1):
115 + second
116 +
117 +Repo Guy (1):
118 + initial
119 +
120 +EOF
121 +
122 +test_expect_success 'name entry after email entry, case-insensitive' '
123 + mkdir -p internal_mailmap &&
124 + echo "<bugs@company.xy> <bugs@company.xx>" >internal_mailmap/.mailmap &&
125 + echo "Internal Guy <BUGS@Company.xx>" >>internal_mailmap/.mailmap &&
126 + git shortlog >actual &&
127 + test_cmp expect actual
128 +'
129 +
130 cat >expect <<\EOF
131 A U Thor (1):
132 initial
@@ -101,7 +136,7 @@ nick1 (1):
136
137 EOF
138 test_expect_success 'No mailmap files, but configured' '
104 - rm .mailmap &&
139 + rm -f .mailmap internal_mailmap/.mailmap &&
140 git shortlog HEAD >actual &&
141 test_cmp expect actual
142 '
@@ -153,7 +188,7 @@ test_expect_success 'Shortlog output (complex mapping)' '
188 test_tick &&
189 git commit --author "CTO <cto@coompany.xx>" -m seventh &&
190
156 - mkdir internal_mailmap &&
191 + mkdir -p internal_mailmap &&
192 echo "Committed <committer@example.com>" > internal_mailmap/.mailmap &&
193 echo "<cto@company.xx> <cto@coompany.xx>" >> internal_mailmap/.mailmap &&
194 echo "Some Dude <some@dude.xx> nick1 <bugs@company.xx>" >> internal_mailmap/.mailmap &&