Since the AST is already using smart pointers, one simple solution would be to change to using an std::set<std::shared_ptr<ColumnDescriptor>>.
Ubuntu jammy container.
=================================================================
==229663==ERROR: AddressSanitizer: heap-use-after-free on address 0x7c0fd0140bf1 at pc 0x000000a85144 bp 0x7ffdfb7538f0 sp 0x7ffdfb7538e8
READ of size 1 at 0x7c0fd0140bf1 thread T0
#0 0x000000a85143 in clp_s::search::ast::ColumnDescriptor::is_pure_wildcard() const /home/lion/yscope/clp/components/core/src/clp/ffi/ir_stream/search/../../../../clp_s/search/ast/ColumnDescriptor.hpp:260
#1 0x0000019742a2 in clp_s::search::SchemaMatch::populate_schema_mapping() /home/lion/yscope/clp/components/core/src/clp_s/search/SchemaMatch.cpp:340
#2 0x000001971a50 in clp_s::search::SchemaMatch::run(std::shared_ptr<clp_s::search::ast::Expression>&) /home/lion/yscope/clp/components/core/src/clp_s/search/SchemaMatch.cpp:83
#3 0x00000118276a in (anonymous namespace)::search(std::shared_ptr<clp_s::search::ast::Expression>, bool, std::vector<long, std::allocator<long> > const&) /home/lion/yscope/clp/components/core/tests/test-clp_s-search.cpp:186
#4 0x00000117e4f9 in (anonymous namespace)::search(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, std::vector<long, std::allocator<long> > const&) /home/lion/yscope/clp/components/core/tests/test-clp_s-search.cpp:136
#5 0x000001170f86 in CATCH2_INTERNAL_TEST_1() /home/lion/yscope/clp/components/core/tests/test-clp_s-search.cpp:252
#6 0x000001e6d9a5 in Catch::RunContext::runCurrentTest() ??:?
#7 0x000001e6d2c4 in Catch::RunContext::runTest(Catch::TestCaseHandle const&) ??:?
#8 0x000001e4891c in Catch::Session::runInternal() ??:?
#9 0x000001e47fd5 in Catch::Session::run() ??:?
#10 0x000001b274c1 in main ??:?
#11 0x7f2fd10105b4 in __libc_start_call_main ??:?
#12 0x7f2fd1010667 in __libc_start_main_alias_2 :?
#13 0x00000041f484 in _start ??:?
0x7c0fd0140bf1 is located 113 bytes inside of 160-byte region [0x7c0fd0140b80,0x7c0fd0140c20)
freed by thread T0 here:
#0 0x0000005098e6 in operator delete(void*, unsigned long) ??:?
#1 0x000001b3aad5 in std::__new_allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::deallocate(std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/new_allocator.h:172
#2 0x000001b39b63 in std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::deallocate(std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/allocator.h:215
#3 0x000001b39b63 in std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::deallocate(std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >&, std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>*, unsigned long) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/alloc_traits.h:649
#4 0x000001b39b63 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::~__allocated_ptr() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/allocated_ptr.h:74
#5 0x000001b3a20c in std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2>::_M_destroy() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:625
#6 0x000000634c29 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:346
#7 0x000000634a0b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:1069
#8 0x00000196d68b in std::__shared_ptr<clp_s::search::ast::Value, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:1531
#9 0x00000196d637 in std::shared_ptr<clp_s::search::ast::Value>::~shared_ptr() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr.h:175
#10 0x00000196d5df in void std::destroy_at<std::shared_ptr<clp_s::search::ast::Value> >(std::shared_ptr<clp_s::search::ast::Value>*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_construct.h:88
#11 0x00000196d421 in void std::allocator_traits<std::allocator<std::_List_node<std::shared_ptr<clp_s::search::ast::Value> > > >::destroy<std::shared_ptr<clp_s::search::ast::Value> >(std::allocator<std::_List_node<std::shared_ptr<clp_s::search::ast::Value> > >&, std::shared_ptr<clp_s::search::ast::Value>*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/alloc_traits.h:698
#12 0x00000196d421 in std::__cxx11::_List_base<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::_M_destroy_node(std::_List_node<std::shared_ptr<clp_s::search::ast::Value> >*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_list.h:845
#13 0x000001b295e5 in std::__cxx11::_List_base<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::_M_clear() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/list.tcc:76
#14 0x000001b29347 in std::__cxx11::_List_base<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::~_List_base() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_list.h:899
#15 0x000001b291c7 in std::__cxx11::list<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::~list() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_list.h:1290
#16 0x000001b29296 in clp_s::search::ast::Expression::~Expression() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/Expression.hpp:20
#17 0x000001b49ba7 in clp_s::search::ast::FilterExpr::~FilterExpr() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/FilterExpr.hpp:69
#18 0x000001b49bf7 in clp_s::search::ast::FilterExpr::~FilterExpr() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/FilterExpr.hpp:69
#19 0x000001b2a509 in std::_Sp_counted_ptr<clp_s::search::ast::Expression*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:427
#20 0x000000634bd7 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:345
#21 0x000000634a0b in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:1069
#22 0x00000196d68b in std::__shared_ptr<clp_s::search::ast::Value, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:1531
#23 0x00000196d637 in std::shared_ptr<clp_s::search::ast::Value>::~shared_ptr() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr.h:175
#24 0x00000196d5df in void std::destroy_at<std::shared_ptr<clp_s::search::ast::Value> >(std::shared_ptr<clp_s::search::ast::Value>*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_construct.h:88
#25 0x00000196d421 in void std::allocator_traits<std::allocator<std::_List_node<std::shared_ptr<clp_s::search::ast::Value> > > >::destroy<std::shared_ptr<clp_s::search::ast::Value> >(std::allocator<std::_List_node<std::shared_ptr<clp_s::search::ast::Value> > >&, std::shared_ptr<clp_s::search::ast::Value>*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/alloc_traits.h:698
#26 0x00000196d421 in std::__cxx11::_List_base<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::_M_destroy_node(std::_List_node<std::shared_ptr<clp_s::search::ast::Value> >*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_list.h:845
#27 0x000001b295e5 in std::__cxx11::_List_base<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::_M_clear() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/list.tcc:76
#28 0x000001b29347 in std::__cxx11::_List_base<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::~_List_base() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_list.h:899
#29 0x000001b291c7 in std::__cxx11::list<std::shared_ptr<clp_s::search::ast::Value>, std::allocator<std::shared_ptr<clp_s::search::ast::Value> > >::~list() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/stl_list.h:1290
#30 0x000001b29296 in clp_s::search::ast::Expression::~Expression() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/Expression.hpp:20
#31 0x000001b28bb7 in clp_s::search::ast::AndExpr::~AndExpr() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/AndExpr.hpp:11
#32 0x000001b28c07 in clp_s::search::ast::AndExpr::~AndExpr() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/AndExpr.hpp:11
#33 0x000001b29e59 in std::_Sp_counted_ptr<clp_s::search::ast::AndExpr*, (__gnu_cxx::_Lock_policy)2>::_M_dispose() /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:427
previously allocated by thread T0 here:
#0 0x000000508c61 in operator new(unsigned long) ??:?
#1 0x000001b39cf3 in std::__new_allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/new_allocator.h:151
#2 0x000001b39516 in std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/allocator.h:203
#3 0x000001b39516 in std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/alloc_traits.h:614
#4 0x000001b39516 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, (__gnu_cxx::_Lock_policy)2> >&) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/allocated_ptr.h:102
#5 0x000001b391b9 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<clp_s::search::ast::ColumnDescriptor, std::allocator<void>, clp_s::search::ast::ColumnDescriptor&>(clp_s::search::ast::ColumnDescriptor*&, std::_Sp_alloc_shared_tag<std::allocator<void> >, clp_s::search::ast::ColumnDescriptor&) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:967
#6 0x000001b38f4b in std::__shared_ptr<clp_s::search::ast::ColumnDescriptor, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<void>, clp_s::search::ast::ColumnDescriptor&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, clp_s::search::ast::ColumnDescriptor&) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr_base.h:1719
#7 0x000001b38e3b in std::shared_ptr<clp_s::search::ast::ColumnDescriptor>::shared_ptr<std::allocator<void>, clp_s::search::ast::ColumnDescriptor&>(std::_Sp_alloc_shared_tag<std::allocator<void> >, clp_s::search::ast::ColumnDescriptor&) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr.h:463
#8 0x000001b31d04 in std::shared_ptr<clp_s::search::ast::ColumnDescriptor> std::make_shared<clp_s::search::ast::ColumnDescriptor, clp_s::search::ast::ColumnDescriptor&>(clp_s::search::ast::ColumnDescriptor&) /usr/bin/../lib/gcc/x86_64-redhat-linux/15/../../../../include/c++/15/bits/shared_ptr.h:1007
#9 0x000001b2e909 in clp_s::search::ast::ColumnDescriptor::copy() /home/lion/yscope/clp/components/core/src/clp_s/search/ast/ColumnDescriptor.cpp:68
#10 0x000001b48dfb in clp_s::search::ast::FilterExpr::copy() const /home/lion/yscope/clp/components/core/src/clp_s/search/ast/FilterExpr.cpp:86
#11 0x000001b40f07 in clp_s::search::ast::Expression::copy_replace(clp_s::search::ast::Expression*, std::_List_iterator<std::shared_ptr<clp_s::search::ast::Value> >) const /home/lion/yscope/clp/components/core/src/clp_s/search/ast/Expression.cpp:31
#12 0x000001b281e0 in clp_s::search::ast::AndExpr::copy() const /home/lion/yscope/clp/components/core/src/clp_s/search/ast/AndExpr.cpp:37
#13 0x000001b40f07 in clp_s::search::ast::Expression::copy_replace(clp_s::search::ast::Expression*, std::_List_iterator<std::shared_ptr<clp_s::search::ast::Value> >) const /home/lion/yscope/clp/components/core/src/clp_s/search/ast/Expression.cpp:31
#14 0x000001b54310 in clp_s::search::ast::OrExpr::copy() const /home/lion/yscope/clp/components/core/src/clp_s/search/ast/OrExpr.cpp:35
#15 0x000001181aa1 in (anonymous namespace)::search(std::shared_ptr<clp_s::search::ast::Expression>, bool, std::vector<long, std::allocator<long> > const&) /home/lion/yscope/clp/components/core/tests/test-clp_s-search.cpp:168
#16 0x00000117e4f9 in (anonymous namespace)::search(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, std::vector<long, std::allocator<long> > const&) /home/lion/yscope/clp/components/core/tests/test-clp_s-search.cpp:136
#17 0x000001170f86 in CATCH2_INTERNAL_TEST_1() /home/lion/yscope/clp/components/core/tests/test-clp_s-search.cpp:252
#18 0x000001e6d9a5 in Catch::RunContext::runCurrentTest() ??:?
SUMMARY: AddressSanitizer: heap-use-after-free /home/lion/yscope/clp/components/core/src/clp/ffi/ir_stream/search/../../../../clp_s/search/ast/ColumnDescriptor.hpp:260 in clp_s::search::ast::ColumnDescriptor::is_pure_wildcard() const
Shadow bytes around the buggy address:
0x7c0fd0140900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c0fd0140980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c0fd0140a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7c0fd0140a80: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00
0x7c0fd0140b00: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
=>0x7c0fd0140b80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd
0x7c0fd0140c00: fd fd fd fd fa fa fa fa fa fa fa fa 00 00 00 00
0x7c0fd0140c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7c0fd0140d00: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x7c0fd0140d80: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x7c0fd0140e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==229663==ABORTING
Bug
SchemaMatchmaintains creates a cache mappingcolumn id -> set<ColumnDescriptor*>during column resolution. Since we sometimes eliminate parts of the AST using constant propagation, some of theseColumnDescriptor*can become invalidated.Since the AST is already using smart pointers, one simple solution would be to change to using an
std::set<std::shared_ptr<ColumnDescriptor>>.CLP version
v0.9.0
Environment
Ubuntu jammy container.
Reproduction steps
Build and run our unit tests with address sanitizer, and observe the following:
Thanks to @davidlion for forwarding this address sanitizer output.