srcML / srcML

srcML Toolkit
srcml.org
GNU General Public License v3.0
105 stars 26 forks source link

Apparent double-free in srcml_unit_apply_transforms #1964

Open toBeOfUse opened 8 months ago

toBeOfUse commented 8 months ago

In attempting to test the function srcml_append_transform_xpath_element in C++, I ran into:

free(): double free detected in tcache 2
Aborted

emerging from srcml_unit_apply_transforms. The debugger reports the error as happening in the callback here:

https://github.com/srcML/srcML/blob/7517dc53e0b7f719e691be17aa24e1ac5e048a3d/src/libsrcml/srcml_transform.cpp#L520

Valgrind gives many more details:

==26783== Invalid read of size 8
==26783==    at 0x4F02298: xmlFreeDoc (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x497A803: srcml_unit_apply_transforms::{lambda(_xmlDoc*)#1}::operator()(_xmlDoc*) const (srcml_transform.cpp:520)
==26783==    by 0x497CA01: std::_Sp_counted_deleter<_xmlDoc*, srcml_unit_apply_transforms::{lambda(_xmlDoc*)#1}, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:471)
==26783==    by 0x496443B: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:155)
==26783==    by 0x4963B20: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:730)
==26783==    by 0x49661A7: std::__shared_ptr<_xmlDoc, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1169)
==26783==    by 0x49661C7: std::shared_ptr<_xmlDoc>::~shared_ptr() (shared_ptr.h:103)
==26783==    by 0x497BC16: srcml_unit_apply_transforms (srcml_transform.cpp:520)
==26783==    by 0x10947B: main (in /home/mitch/srcML/unsystematictests/a.out)
==26783==  Address 0x70c05d0 is 96 bytes inside a block of size 176 free'd
==26783==    at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26783==    by 0x4F02639: xmlFreeNodeList (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x4F02297: xmlFreeDoc (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x497A803: srcml_unit_apply_transforms::{lambda(_xmlDoc*)#1}::operator()(_xmlDoc*) const (srcml_transform.cpp:520)
==26783==    by 0x497CA01: std::_Sp_counted_deleter<_xmlDoc*, srcml_unit_apply_transforms::{lambda(_xmlDoc*)#1}, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:471)
==26783==    by 0x496443B: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:155)
==26783==    by 0x4963B20: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:730)
==26783==    by 0x49661A7: std::__shared_ptr<_xmlDoc, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:1169)
==26783==    by 0x49661C7: std::shared_ptr<_xmlDoc>::~shared_ptr() (shared_ptr.h:103)
==26783==    by 0x497BC16: srcml_unit_apply_transforms (srcml_transform.cpp:520)
==26783==    by 0x10947B: main (in /home/mitch/srcML/unsystematictests/a.out)
==26783==  Block was alloc'd at
==26783==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==26783==    by 0x4EFFE69: xmlNewDoc (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x4FDCAF0: xmlSAX2StartDocument (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x4EF6B55: xmlParseDocument (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x4EFC21D: xmlReadMemory (in /usr/lib/x86_64-linux-gnu/libxml2.so.2.9.10)
==26783==    by 0x497AB4D: srcml_unit_apply_transforms (srcml_transform.cpp:520)
==26783==    by 0x10947B: main (in /home/mitch/srcML/unsystematictests/a.out)

However, it's not immediately obvious to me why the lambda there is apparently being called twice. The example program I was running can be found here, but it's literally just the pre-existing srcml_xpath example with srcml_append_transform_xpath_element used instead of just srcml_append_transform_xpath.