Skip to content

clp-s: Use-after-free in SchemaMatch. #1986

@gibber9809

Description

@gibber9809

Bug

SchemaMatch maintains creates a cache mapping column id -> set<ColumnDescriptor*> during column resolution. Since we sometimes eliminate parts of the AST using constant propagation, some of these ColumnDescriptor* 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:

=================================================================
==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

Thanks to @davidlion for forwarding this address sanitizer output.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions