[llvm-bugs] [Bug 35547] New: [ThinLTO] multi-threaded use after free when handling error

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Dec 6 08:28:26 PST 2017


https://bugs.llvm.org/show_bug.cgi?id=35547

            Bug ID: 35547
           Summary: [ThinLTO] multi-threaded use after free when handling
                    error
           Product: new-bugs
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: russell_gallop at sn.scee.net
                CC: llvm-bugs at lists.llvm.org

While investigating PR35472 we observed some crashes while handling that error.

Building clang and llvm-lto with ASan (r319883) shows that one thread is trying
to access command line options after they have been freed. Note that we do not
see the use-after-free with -threads=1.
$ cat a.cpp
struct Charlie {
    __attribute__((__always_inline__)) ~Charlie() { Golf = 0; }
    int Golf;
};

struct Delta {
    Charlie Foxtrot;
};

struct Echo {
    Charlie Foxtrot;
    __attribute__((nodebug)) ~Echo() = default;
};

extern void Bravo();

void Bravo() {
    Delta Hotel;
    Echo India;
}
$ cat b.cpp
extern void Bravo();
extern void Alpha();
void Alpha() { Bravo(); }
$ clang++ -c a.cpp b.cpp --std=c++11 -O0 -g -flto=thin
$ llvm-lto -thinlto-action=run a.o b.o
ThinLTO: b.o: error: Invalid function metadata: outgoing forward refs
(Producer: 'LLVM6.0.0svn' Reader: 'LLVM 6.0.0svn')
LLVM ERROR: importFunctions failed
=================================================================
==10367==ERROR: AddressSanitizer: heap-use-after-free on address 0x624000004100
at pc 0x00000060388d bp 0x7ff7c62fd050 sp 0x7ff7c62fc800
READ of size 32 at 0x624000004100 thread T1
    #0 0x60388c in __asan_memcpy
.../llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cc:23
    #1 0x234da66 in llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo::OptionInfo(llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo&&) .../llvm/include/llvm/Support/CommandLine.h:740:9
    #2 0x234d8ad in llvm::cl::parser<llvm::PassInfo const*>::OptionInfo*
std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo*>, llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo*>(std::move_iterator<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo*>, std::move_iterator<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo*>, llvm::cl::parser<llvm::PassInfo const*>::OptionInfo*)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/stl_uninitialized.h:75:3
    #3 0x234d481 in
llvm::SmallVectorTemplateBase<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo, false>::grow(unsigned long)
.../llvm/include/llvm/ADT/SmallVector.h:246:3
    #4 0x234d144 in
llvm::SmallVectorTemplateBase<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo, false>::push_back(llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo const&) .../llvm/include/llvm/ADT/SmallVector.h:214:13
    #5 0x234ce8d in void llvm::cl::parser<llvm::PassInfo
const*>::addLiteralOption<llvm::PassInfo const*>(llvm::StringRef,
llvm::PassInfo const* const&, llvm::StringRef)
.../llvm/include/llvm/Support/CommandLine.h:789:12
    #6 0x234c61b in llvm::PassNameParser::passRegistered(llvm::PassInfo const*)
.../llvm/include/llvm/IR/LegacyPassNameParser.h:76:5
    #7 0x236b874 in llvm::PassRegistry::registerPass(llvm::PassInfo const&,
bool) .../llvm/lib/IR/PassRegistry.cpp:68:15
    #8 0x379b512 in
initializeForceFunctionAttrsLegacyPassPassOnce(llvm::PassRegistry&)
.../llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp:118:1
    #9 0x7ff7ca461a98 in __pthread_once_slow
(/lib/x86_64-linux-gnu/libpthread.so.0+0xea98)
    #10 0x6d3b50 in void std::call_once<void* (&)(llvm::PassRegistry&),
std::reference_wrapper<llvm::PassRegistry> >(std::once_flag&, void*
(&)(llvm::PassRegistry&), std::reference_wrapper<llvm::PassRegistry>&&)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/mutex:738:17
    #11 0x379b452 in
llvm::initializeForceFunctionAttrsLegacyPassPass(llvm::PassRegistry&)
.../llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp:118:1
    #12 0x379b53a in llvm::createForceFunctionAttrsLegacyPass()
.../llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp:122:14
    #13 0x388d9e8 in
llvm::PassManagerBuilder::populateModulePassManager(llvm::legacy::PassManagerBase&)
.../llvm/lib/Transforms/IPO/PassManagerBuilder.cpp:401:11
    #14 0x3890826 in
llvm::PassManagerBuilder::populateThinLTOPassManager(llvm::legacy::PassManagerBase&)
.../llvm/lib/Transforms/IPO/PassManagerBuilder.cpp:887:3
    #15 0x244586b in (anonymous namespace)::optimizeModule(llvm::Module&,
llvm::TargetMachine&, unsigned int, bool)
.../llvm/lib/LTO/ThinLTOCodeGenerator.cpp:237:7
    #16 0x2452b7f in (anonymous namespace)::ProcessThinLTOModule(llvm::Module&,
llvm::ModuleSummaryIndex&, llvm::StringMap<llvm::MemoryBufferRef,
llvm::MallocAllocator>&, llvm::TargetMachine&,
llvm::StringMap<std::map<unsigned long, unsigned int, std::less<unsigned long>,
std::allocator<std::pair<unsigned long const, unsigned int> > >,
llvm::MallocAllocator> const&, std::unordered_set<unsigned long,
std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned
long> > const&, llvm::DenseSet<unsigned long, llvm::DenseMapInfo<unsigned long>
> const&, llvm::DenseMap<unsigned long, llvm::GlobalValueSummary*,
llvm::DenseMapInfo<unsigned long>, llvm::detail::DenseMapPair<unsigned long,
llvm::GlobalValueSummary*> > const&, llvm::ThinLTOCodeGenerator::CachingOptions
const&, bool, llvm::StringRef, bool, unsigned int, unsigned int)
.../llvm/lib/LTO/ThinLTOCodeGenerator.cpp:468:3
    #17 0x2450e2f in llvm::ThinLTOCodeGenerator::run()::$_5::operator()(int)
const .../llvm/lib/LTO/ThinLTOCodeGenerator.cpp:1011:29
    #18 0x24504bf in void std::_Bind<llvm::ThinLTOCodeGenerator::run()::$_5
(int)>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1073:11
    #19 0x24503a2 in void std::_Bind<llvm::ThinLTOCodeGenerator::run()::$_5
(int)>::operator()<, void>()
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1131:17
    #20 0x278f309 in
std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>,
std::__future_base::_Result_base::_Deleter>,
std::_Bind_simple<std::reference_wrapper<std::function<void ()> > ()>,
void>::operator()() const
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/future:1342:6
    #21 0x278f1b9 in
std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> (),
std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>,
std::__future_base::_Result_base::_Deleter>,
std::_Bind_simple<std::reference_wrapper<std::function<void ()> > ()>, void>
>::_M_invoke(std::_Any_data const&)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:1856:9
    #22 0x278f085 in
std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>::operator()() const
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/functional:2267:14
    #23 0x278e5c4 in
std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>*, bool*)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/future:527:27
    #24 0x7ff7ca461a98 in __pthread_once_slow
(/lib/x86_64-linux-gnu/libpthread.so.0+0xea98)
    #25 0x278e467 in void std::call_once<void
(std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>*, bool*),
std::__future_base::_State_baseV2*,
std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void
(std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>*, bool*),
std::__future_base::_State_baseV2*&&,
std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/mutex:738:17
    #26 0x278de81 in
std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base,
std::__future_base::_Result_base::_Deleter> ()>, bool)
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/future:386:2
    #27 0x278d0b0 in std::__future_base::_Task_state<std::function<void ()>,
std::allocator<int>, void ()>::_M_run()
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/future:1403:8
    #28 0x2787364 in llvm::ThreadPool::ThreadPool(unsigned
int)::$_0::operator()() const .../llvm/lib/Support/ThreadPool.cpp:57:9
    #29 0x7ff7c9631c7f  (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb8c7f)
    #30 0x7ff7ca45a6b9 in start_thread
(/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
    #31 0x7ff7c90a03dc in clone
/build/glibc-bfm8X4/glibc-2.23/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:109

0x624000004100 is located 0 bytes inside of 7168-byte region
[0x624000004100,0x624000005d00)
freed by thread T2 here:
    #0 0x604848 in __interceptor_cfree.localalias.0
.../llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:76
    #1 0x234cbdf in llvm::cl::parser<llvm::PassInfo const*>::~parser()
.../llvm/include/llvm/Support/CommandLine.h:738:33
    #2 0x234b9d1 in llvm::PassNameParser::~PassNameParser()
.../llvm/lib/IR/Pass.cpp:254:33
    #3 0x22cfb92 in llvm::cl::list<llvm::PassInfo const*, bool,
llvm::PassNameParser>::~list()
.../llvm/include/llvm/Support/CommandLine.h:1475:7
    #4 0x7ff7c8fd2ff7 in __run_exit_handlers
/build/glibc-bfm8X4/glibc-2.23/stdlib/exit.c:82

previously allocated by thread T0 here:
    #0 0x604a08 in __interceptor_malloc
.../llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:88
    #1 0x234d43c in
llvm::SmallVectorTemplateBase<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo, false>::grow(unsigned long)
.../llvm/include/llvm/ADT/SmallVector.h:241:32
    #2 0x234d144 in
llvm::SmallVectorTemplateBase<llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo, false>::push_back(llvm::cl::parser<llvm::PassInfo
const*>::OptionInfo const&) .../llvm/include/llvm/ADT/SmallVector.h:214:13
    #3 0x234ce8d in void llvm::cl::parser<llvm::PassInfo
const*>::addLiteralOption<llvm::PassInfo const*>(llvm::StringRef,
llvm::PassInfo const* const&, llvm::StringRef)
.../llvm/include/llvm/Support/CommandLine.h:789:12
    #4 0x234c61b in llvm::PassNameParser::passRegistered(llvm::PassInfo const*)
.../llvm/include/llvm/IR/LegacyPassNameParser.h:76:5
    #5 0x236b874 in llvm::PassRegistry::registerPass(llvm::PassInfo const&,
bool) .../llvm/lib/IR/PassRegistry.cpp:68:15
    #6 0x447b0ff in
initializeMemoryDependenceWrapperPassPassOnce(llvm::PassRegistry&)
.../llvm/lib/Analysis/MemoryDependenceAnalysis.cpp:1728:1
    #7 0x7ff7ca461a98 in __pthread_once_slow
(/lib/x86_64-linux-gnu/libpthread.so.0+0xea98)

Thread T1 created by T0 here:
    #0 0x55a16d in pthread_create
.../llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:204
    #1 0x7ff7c9631dc2 in
std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void
(*)()) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb8dc2)

Thread T2 created by T0 here:
    #0 0x55a16d in pthread_create
.../llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:204
    #1 0x7ff7c9631dc2 in
std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>, void
(*)()) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb8dc2)

SUMMARY: AddressSanitizer: heap-use-after-free
.../llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cc:23 in
__asan_memcpy
Shadow bytes around the buggy address:
  0x0c487fff87d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c487fff87e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c487fff87f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c487fff8800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c487fff8810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c487fff8820:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c487fff8830: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c487fff8840: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c487fff8850: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c487fff8860: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c487fff8870: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
==10367==ABORTING

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20171206/c62244ec/attachment-0001.html>


More information about the llvm-bugs mailing list