[cfe-dev] ast_matchers::MatchFinder default constructor segfaults away

Whisperity via cfe-dev cfe-dev at lists.llvm.org
Fri Jul 27 04:41:16 PDT 2018


Okay, this is even weirder.

Using a newer GDB, I was able to figure out that in this case the
memory address of the rvalue reference argument in that move ctor is
0x0, which causes the segfault when the code wants to read its
member...

I originally *thought* using the stack allocated member (as opposed to
the default constructor) works, and it worked to the point of creating
the finder, but when I modified my code to include a -- rather trivial
-- matcher and ran a `matchAST`, it resulted in a memory corruption:
 - the `matchAST` instantiates a visitor for each matcher
 - this matcher implementation type's destructor checks if the
MatchFinder's option struct (which got passed to it by lvalue
reference) has profiling enabled
 - because the profiling enabled state of the Optional was garbage
(I've seen this bool have 120, 210, 224 and 78 as value, absolute
garbage!), it goes and moves some inner struct
 - this inner struct's move ctor tries to free the previous buffer,
but it is a garbage pointer, resulting in a long error dump by LLVM's
handlers.

But now, even using the thing I've worded as "works" in the previous
email, I'm getting weird segfaults at the same location.
I even tried to do the same thing Clang-Tidy (who does not segfault)
does: put the finder into a unique_ptr. Somehow(???) the argument from
where the options struct's inner record moves from turns to a 0x0.
(Doing a `p &O` or `i ar` in the top two stack frames show that
"Options" and "O" is unreadable.)

(gdb) i ar
  this = 0x7fffffff92c0
  O = <error reading variable>
(gdb) i f
  Stack level 0, frame at 0x7fffffff8f60:
   rip = 0x7fffec987f3a in
llvm::Optional<clang::ast_matchers::MatchFinder::MatchFinderOptions::Profiling>::Optional
(../../../../../include/llvm/ADT/Optional.h:144);
      saved rip = 0x7fffec987f73


; Whisperity.


2018-07-26 21:31 GMT+02:00 Whisperity <whisperity at gmail.com>:
> Dear List,
>
>
>
> When trying to instantiate a MatchFinder on my function's local stack,
> if I try to use the default constructor, it segfaults.
>
> Relevant code snippet:
>
>   void f()
>   {
>     MatchFinder finder; // <- SIGSEGV
>     // ...
>   }
>
> and backtrace:
>
> (gdb) bt  5
> #0  0x00007fffeb240f67 in
> llvm::optional_detail::OptionalStorage<clang::ast_matchers::MatchFinder::MatchFinderOptions::Profiling,
> true>::OptionalStorage(llvm::optiona
> l_detail::OptionalStorage<clang::ast_matchers::MatchFinder::MatchFinderOptions::Profiling,
> true>&&) (this=0x7fffdeac3120,
>     O=<unknown type in
> /large/whisperity/llvm/build/./lib/../lib/libclangASTMatchers.so.7, CU
> 0x0, DIE 0x20cb21>) at ../../../../../include/llvm/ADT/Optional.h:46
> #1  0x00007fffeb237f4d in
> llvm::Optional<clang::ast_matchers::MatchFinder::MatchFinderOptions::Profiling>::Optional(llvm::Optional<clang::ast_matchers::MatchFinder::M
> atchFinderOptions::Profiling>&&) (this=0x7fffdeac3120, O=<unknown type
> in /large/whisperity/llvm/build/./lib/../lib/libclangASTMatchers.so.7,
> CU 0x0, DIE 0x2002ac>)
>     at ../../../../../include/llvm/ADT/Optional.h:144
> #2  0x00007fffeb237f73 in
> clang::ast_matchers::MatchFinder::MatchFinderOptions::MatchFinderOptions(clang::ast_matchers::MatchFinder::MatchFinderOptions&&)
> (
>     this=0x7fffdeac3120) at
> ../../../../../../clang/include/clang/ASTMatchers/ASTMatchFinder.h:123
> #3  0x00007fffeb17fd94 in
> clang::ast_matchers::MatchFinder::MatchFinder (this=0x7fffdeac2fe8,
> Options=...)
>     at ../../../../../../clang/lib/ASTMatchers/ASTMatchFinder.cpp:934
>
> The default constructor's init-list moves from the argument and the
> method itself is declared in the header with default argument using a
> default constructed instance of Options.
> The only use place I could find for this class so far is Clang-Tidy.
>
> I don't want to use the options in any special way in my code, that's
> why I tried the default initialiser.
>
> If I explicitly initialise a MatchFinder::MatchFinderOptions and pass
> it as an argument, either by copy or move, it works.
> Passing a temporary by copy or move results in the same segfault.
>
>   void f()
>   {
>      MatchFinder::MatchFinderOptions opts;
>      MatchFinder finder(opts); // works
>   }
>
> I'm not entirely sure what would be the best option to solve this API
> inconsistency, as seemingly the error lies two or three types
> deeper...
>
>
>
> ; Whisperity


More information about the cfe-dev mailing list