New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Double free after calling git_diff_merge #6588
Comments
vincenzopalazzo
added a commit
to vincenzopalazzo/libgit2
that referenced
this issue
Jul 9, 2023
This commit addresses a double free issue that occurs when merging two diffs and free the diff objects. The problem was caused from copying the pointer using a vector swap git function and then make a deep free of the original vector. This operation made on a vector of pointers deallocated all the pointers inside the new vector where we swap the content to. As a result, an invalid object was returned to the user. The valgrid report. ``` ==256010== HEAP SUMMARY: ==256010== in use at exit: 696,247 bytes in 11,244 blocks ==256010== total heap usage: 50,123 allocs, 38,880 frees, 4,419,142 bytes allocated ==256010== ==256010== Searching for pointers to 11,244 not-freed blocks ==256010== Checked 850,720 bytes ==256010== ==256010== 112 bytes in 1 blocks are definitely lost in loss record 69 of 163 ==256010== at 0x4841848: malloc (vg_replace_malloc.c:431) ==256010== by 0x48964FD: stdalloc__malloc.lto_priv.0 (stdalloc.c:22) ==256010== by 0x48D4C34: git_diff__delta_dup (diff_tform.c:23) ==256010== by 0x48DAA22: git_diff__merge_like_cgit (diff_tform.c:81) ==256010== by 0x48D5C14: git_diff__merge (diff_tform.c:160) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== LEAK SUMMARY: ==256010== definitely lost: 112 bytes in 1 blocks ==256010== indirectly lost: 0 bytes in 0 blocks ==256010== possibly lost: 0 bytes in 0 blocks ==256010== still reachable: 696,135 bytes in 11,243 blocks ==256010== suppressed: 0 bytes in 0 blocks ==256010== Reachable blocks (those to which a pointer was found) are not shown. ==256010== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ==256010== ==256010== 1 errors in context 1 of 2: ==256010== Invalid free() / delete / delete[] / realloc() ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x490D5B0: patch_parsed__free.part.0.lto_priv.0 (patch_parse.c:1150) ==256010== by 0x48CC454: diff_parsed_free (diff_parse.c:21) ==256010== by 0x1092EA: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Address 0x59e55b0 is 0 bytes inside a block of size 112 free'd ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x48A17CD: git_vector_free_deep.part.0 (vector.c:99) ==256010== by 0x48D5A2B: UnknownInlinedFun (vector.c:95) ==256010== by 0x48D5A2B: git_diff__merge (diff_tform.c:193) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Block was alloc'd at ==256010== at 0x48469B3: calloc (vg_replace_malloc.c:1554) ==256010== by 0x489652D: stdalloc__calloc.lto_priv.0 (stdalloc.c:42) ==256010== by 0x48CCDE9: UnknownInlinedFun (patch_parse.c:1184) ==256010== by 0x48CCDE9: git_diff_from_buffer (diff_parse.c:86) ==256010== by 0x109219: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ``` Link: libgit2#6588 Reported-by: Eric Huss Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
vincenzopalazzo
added a commit
to vincenzopalazzo/libgit2
that referenced
this issue
Jul 9, 2023
This commit addresses a double free issue that occurs when merging two diffs and free the diff objects. The problem was caused from copying the pointer using a vector swap git function and then make a deep free of the original vector. This operation made on a vector of pointers deallocated all the pointers inside the new vector where we swap the content to. As a result, an invalid object was returned to the user. The valgrid report. ``` ==256010== HEAP SUMMARY: ==256010== in use at exit: 696,247 bytes in 11,244 blocks ==256010== total heap usage: 50,123 allocs, 38,880 frees, 4,419,142 bytes allocated ==256010== ==256010== Searching for pointers to 11,244 not-freed blocks ==256010== Checked 850,720 bytes ==256010== ==256010== 112 bytes in 1 blocks are definitely lost in loss record 69 of 163 ==256010== at 0x4841848: malloc (vg_replace_malloc.c:431) ==256010== by 0x48964FD: stdalloc__malloc.lto_priv.0 (stdalloc.c:22) ==256010== by 0x48D4C34: git_diff__delta_dup (diff_tform.c:23) ==256010== by 0x48DAA22: git_diff__merge_like_cgit (diff_tform.c:81) ==256010== by 0x48D5C14: git_diff__merge (diff_tform.c:160) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== LEAK SUMMARY: ==256010== definitely lost: 112 bytes in 1 blocks ==256010== indirectly lost: 0 bytes in 0 blocks ==256010== possibly lost: 0 bytes in 0 blocks ==256010== still reachable: 696,135 bytes in 11,243 blocks ==256010== suppressed: 0 bytes in 0 blocks ==256010== Reachable blocks (those to which a pointer was found) are not shown. ==256010== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ==256010== ==256010== 1 errors in context 1 of 2: ==256010== Invalid free() / delete / delete[] / realloc() ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x490D5B0: patch_parsed__free.part.0.lto_priv.0 (patch_parse.c:1150) ==256010== by 0x48CC454: diff_parsed_free (diff_parse.c:21) ==256010== by 0x1092EA: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Address 0x59e55b0 is 0 bytes inside a block of size 112 free'd ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x48A17CD: git_vector_free_deep.part.0 (vector.c:99) ==256010== by 0x48D5A2B: UnknownInlinedFun (vector.c:95) ==256010== by 0x48D5A2B: git_diff__merge (diff_tform.c:193) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Block was alloc'd at ==256010== at 0x48469B3: calloc (vg_replace_malloc.c:1554) ==256010== by 0x489652D: stdalloc__calloc.lto_priv.0 (stdalloc.c:42) ==256010== by 0x48CCDE9: UnknownInlinedFun (patch_parse.c:1184) ==256010== by 0x48CCDE9: git_diff_from_buffer (diff_parse.c:86) ==256010== by 0x109219: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ``` Link: libgit2#6588 Reported-by: Eric Huss Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
vincenzopalazzo
added a commit
to vincenzopalazzo/libgit2
that referenced
this issue
Jul 9, 2023
This commit addresses a double free issue that occurs when merging two diffs and free the diff objects. The problem was caused from copying the pointer using a vector swap git function and then make a deep free of the original vector. This operation made on a vector of pointers deallocated all the pointers inside the new vector where we swap the content to. As a result, an invalid object was returned to the user. The valgrid report. ``` ==256010== HEAP SUMMARY: ==256010== in use at exit: 696,247 bytes in 11,244 blocks ==256010== total heap usage: 50,123 allocs, 38,880 frees, 4,419,142 bytes allocated ==256010== ==256010== Searching for pointers to 11,244 not-freed blocks ==256010== Checked 850,720 bytes ==256010== ==256010== 112 bytes in 1 blocks are definitely lost in loss record 69 of 163 ==256010== at 0x4841848: malloc (vg_replace_malloc.c:431) ==256010== by 0x48964FD: stdalloc__malloc.lto_priv.0 (stdalloc.c:22) ==256010== by 0x48D4C34: git_diff__delta_dup (diff_tform.c:23) ==256010== by 0x48DAA22: git_diff__merge_like_cgit (diff_tform.c:81) ==256010== by 0x48D5C14: git_diff__merge (diff_tform.c:160) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== LEAK SUMMARY: ==256010== definitely lost: 112 bytes in 1 blocks ==256010== indirectly lost: 0 bytes in 0 blocks ==256010== possibly lost: 0 bytes in 0 blocks ==256010== still reachable: 696,135 bytes in 11,243 blocks ==256010== suppressed: 0 bytes in 0 blocks ==256010== Reachable blocks (those to which a pointer was found) are not shown. ==256010== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ==256010== ==256010== 1 errors in context 1 of 2: ==256010== Invalid free() / delete / delete[] / realloc() ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x490D5B0: patch_parsed__free.part.0.lto_priv.0 (patch_parse.c:1150) ==256010== by 0x48CC454: diff_parsed_free (diff_parse.c:21) ==256010== by 0x1092EA: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Address 0x59e55b0 is 0 bytes inside a block of size 112 free'd ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x48A17CD: git_vector_free_deep.part.0 (vector.c:99) ==256010== by 0x48D5A2B: UnknownInlinedFun (vector.c:95) ==256010== by 0x48D5A2B: git_diff__merge (diff_tform.c:193) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Block was alloc'd at ==256010== at 0x48469B3: calloc (vg_replace_malloc.c:1554) ==256010== by 0x489652D: stdalloc__calloc.lto_priv.0 (stdalloc.c:42) ==256010== by 0x48CCDE9: UnknownInlinedFun (patch_parse.c:1184) ==256010== by 0x48CCDE9: git_diff_from_buffer (diff_parse.c:86) ==256010== by 0x109219: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ``` Link: libgit2#6588 Reported-by: Eric Huss Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Ok, a possible patch is live #6589 |
vincenzopalazzo
added a commit
to vincenzopalazzo/libgit2
that referenced
this issue
Jul 12, 2023
This commit addresses a double free issue that occurs when merging two diffs and free the diff objects. The problem was caused from copying the pointer using a vector swap git function and then make a deep free of the original vector. This operation made on a vector of pointers deallocated all the pointers inside the new vector where we swap the content to. As a result, an invalid object was returned to the user. The valgrid report. ``` ==256010== HEAP SUMMARY: ==256010== in use at exit: 696,247 bytes in 11,244 blocks ==256010== total heap usage: 50,123 allocs, 38,880 frees, 4,419,142 bytes allocated ==256010== ==256010== Searching for pointers to 11,244 not-freed blocks ==256010== Checked 850,720 bytes ==256010== ==256010== 112 bytes in 1 blocks are definitely lost in loss record 69 of 163 ==256010== at 0x4841848: malloc (vg_replace_malloc.c:431) ==256010== by 0x48964FD: stdalloc__malloc.lto_priv.0 (stdalloc.c:22) ==256010== by 0x48D4C34: git_diff__delta_dup (diff_tform.c:23) ==256010== by 0x48DAA22: git_diff__merge_like_cgit (diff_tform.c:81) ==256010== by 0x48D5C14: git_diff__merge (diff_tform.c:160) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== LEAK SUMMARY: ==256010== definitely lost: 112 bytes in 1 blocks ==256010== indirectly lost: 0 bytes in 0 blocks ==256010== possibly lost: 0 bytes in 0 blocks ==256010== still reachable: 696,135 bytes in 11,243 blocks ==256010== suppressed: 0 bytes in 0 blocks ==256010== Reachable blocks (those to which a pointer was found) are not shown. ==256010== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ==256010== ==256010== 1 errors in context 1 of 2: ==256010== Invalid free() / delete / delete[] / realloc() ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x490D5B0: patch_parsed__free.part.0.lto_priv.0 (patch_parse.c:1150) ==256010== by 0x48CC454: diff_parsed_free (diff_parse.c:21) ==256010== by 0x1092EA: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Address 0x59e55b0 is 0 bytes inside a block of size 112 free'd ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x48A17CD: git_vector_free_deep.part.0 (vector.c:99) ==256010== by 0x48D5A2B: UnknownInlinedFun (vector.c:95) ==256010== by 0x48D5A2B: git_diff__merge (diff_tform.c:193) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Block was alloc'd at ==256010== at 0x48469B3: calloc (vg_replace_malloc.c:1554) ==256010== by 0x489652D: stdalloc__calloc.lto_priv.0 (stdalloc.c:42) ==256010== by 0x48CCDE9: UnknownInlinedFun (patch_parse.c:1184) ==256010== by 0x48CCDE9: git_diff_from_buffer (diff_parse.c:86) ==256010== by 0x109219: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ``` Link: libgit2#6588 Reported-by: Eric Huss Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
vincenzopalazzo
added a commit
to vincenzopalazzo/libgit2
that referenced
this issue
Jul 21, 2023
This commit addresses a double free issue that occurs when merging two diffs and free the diff objects. The problem was caused from copying the pointer using a vector swap git function and then make a deep free of the original vector. This operation made on a vector of pointers deallocated all the pointers inside the new vector where we swap the content to. As a result, an invalid object was returned to the user. The valgrid report. ``` ==256010== HEAP SUMMARY: ==256010== in use at exit: 696,247 bytes in 11,244 blocks ==256010== total heap usage: 50,123 allocs, 38,880 frees, 4,419,142 bytes allocated ==256010== ==256010== Searching for pointers to 11,244 not-freed blocks ==256010== Checked 850,720 bytes ==256010== ==256010== 112 bytes in 1 blocks are definitely lost in loss record 69 of 163 ==256010== at 0x4841848: malloc (vg_replace_malloc.c:431) ==256010== by 0x48964FD: stdalloc__malloc.lto_priv.0 (stdalloc.c:22) ==256010== by 0x48D4C34: git_diff__delta_dup (diff_tform.c:23) ==256010== by 0x48DAA22: git_diff__merge_like_cgit (diff_tform.c:81) ==256010== by 0x48D5C14: git_diff__merge (diff_tform.c:160) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== LEAK SUMMARY: ==256010== definitely lost: 112 bytes in 1 blocks ==256010== indirectly lost: 0 bytes in 0 blocks ==256010== possibly lost: 0 bytes in 0 blocks ==256010== still reachable: 696,135 bytes in 11,243 blocks ==256010== suppressed: 0 bytes in 0 blocks ==256010== Reachable blocks (those to which a pointer was found) are not shown. ==256010== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ==256010== ==256010== 1 errors in context 1 of 2: ==256010== Invalid free() / delete / delete[] / realloc() ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x490D5B0: patch_parsed__free.part.0.lto_priv.0 (patch_parse.c:1150) ==256010== by 0x48CC454: diff_parsed_free (diff_parse.c:21) ==256010== by 0x1092EA: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Address 0x59e55b0 is 0 bytes inside a block of size 112 free'd ==256010== at 0x484412F: free (vg_replace_malloc.c:974) ==256010== by 0x48A17CD: git_vector_free_deep.part.0 (vector.c:99) ==256010== by 0x48D5A2B: UnknownInlinedFun (vector.c:95) ==256010== by 0x48D5A2B: git_diff__merge (diff_tform.c:193) ==256010== by 0x1092A6: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== Block was alloc'd at ==256010== at 0x48469B3: calloc (vg_replace_malloc.c:1554) ==256010== by 0x489652D: stdalloc__calloc.lto_priv.0 (stdalloc.c:42) ==256010== by 0x48CCDE9: UnknownInlinedFun (patch_parse.c:1184) ==256010== by 0x48CCDE9: git_diff_from_buffer (diff_parse.c:86) ==256010== by 0x109219: main (in /home/vincent/Github/libgit2/build/a.out) ==256010== ==256010== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) ``` Link: libgit2#6588 Reported-by: Eric Huss Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Reproduction steps
Expected behavior
After calling
git_diff_merge
, I am assuming that both the originalgit_diff
objects should be safe to free.Actual behavior
There is a double-free when calling
git_diff_free
. From a small amount of debugging, I see that it is failing inpatch_parsed__free
when freeingpatch->base.delta
. The delta was previously freed ingit_dif__merge
when it callsgit_vector_free_deep(&onto_new);
removing the previous vector of deltas.Version of libgit2 (release number or SHA1)
f041a94 or v1.6.4
Operating system(s) tested
Linux or macOS
The text was updated successfully, but these errors were encountered: