<div dir="ltr"><div><font face="monospace, monospace">I'm seeing memory corruption when I use a literal string and std::string in a ternary (?:) expression.  If I change ss to ss.c_str() on line 5, the corruption goes away. [1] is an AST diff, which might help explain it.</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">Although clang doesn't give me an error or warning, is this code legal, or is this a bug?</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">thanks...</font></div><div><font face="monospace, monospace">don</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">$ grep -n "." x.cpp</font></div><div><font face="monospace, monospace">1:#include "llvm/ADT/StringRef.h"</font></div><div><font face="monospace, monospace">3:int main() {</font></div><div><font face="monospace, monospace">4:  const std::string ss;</font></div><div><font face="monospace, monospace">5:  llvm::StringRef Ref = true ? "noexcept" : ss;</font></div><div><font face="monospace, monospace">6:  std::string s = Ref;</font></div><div><font face="monospace, monospace">7:  return 0;</font></div><div><font face="monospace, monospace">8:}</font></div></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">$ ../../4.0.0/build/Release/bin/<wbr>clang++ x.cpp -O1 -g -fsanitize=address -fno-omit-frame-pointer -std=c++11 -I ../../llvm/include/ -I include</font></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">$ ./a.out</font></div><div><font face="monospace, monospace">==============================<wbr>==============================<wbr>=====</font></div><div><font face="monospace, monospace">==14769==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000000068 at pc 0x0000004651b2 bp 0x7ffcc5b3a7d0 sp 0x7ffcc5b39f80</font></div><div><font face="monospace, monospace">READ of size 8 at 0x604000000068 thread T0</font></div><div><font face="monospace, monospace">    #0 0x4651b1 in __interceptor_memcpy.part.36 /home/d80049854/projects/clang<wbr>/4.0.0/llvm/projects/compilerr<wbr>t/lib/asan/../sanitizer_<wbr>common/sanitizer_common_<wbr>interceptors.inc:655</font></div><div><font face="monospace, monospace">    #1 0x7f00fe4d10ed  (/usr/lib/x86_64-linux-gnu/li<wbr>bstdc++.so.6+0xc40ed)</font></div><div><font face="monospace, monospace">    #2 0x7f00fe4d298a in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, unsigned long, std::allocator<char> const&) (/usr/lib/x86_64-linux-gnu/lib<wbr>stdc++.so.6+0xc598a)</font></div><div><font face="monospace, monospace">    #3 0x50d3bc in llvm::StringRef::str() const /home/d80049854/projects/clang<wbr>/build/Debug/../../llvm/includ<wbr>e/llvm/ADT/StringRef.h:230:14</font></div><div><font face="monospace, monospace">    #4 0x50d2cd in llvm::StringRef::operator std::string() const /home/d80049854/projects/clang<wbr>/build/Debug/../../llvm/includ<wbr>e/llvm/ADT/StringRef.h:257:14</font></div><div><font face="monospace, monospace">    #5 0x50d0aa in main /home/d80049854/projects/clang<wbr>/build/Debug/x.cpp:6:19</font></div><div><font face="monospace, monospace">    #6 0x7f00fd522f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so<wbr>.6+0x21f44)</font></div><div><font face="monospace, monospace">    #7 0x41a10b in _start (/home/d80049854/projects/clan<wbr>g/build/Debug/a.out+0x41a10b)</font></div></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">0x604000000068 is located 24 bytes inside of 33-byte region [0x604000000050,0x604000000071<wbr>)</font></div><div><font face="monospace, monospace">freed by thread T0 here:</font></div><div><font face="monospace, monospace">    #0 0x5098b0 in operator delete(void*) /home/d80049854/projects/clang<wbr>/4.0.0/llvm/projects/compiler-<wbr>rt/lib/asan/asan_new_delete.<wbr>cc:126</font></div><div><font face="monospace, monospace">    #1 0x7f00fe4d11cd in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (/usr/lib/x86_64-linux-gnu/lib<wbr>stdc++.so.6+0xc41cd)</font></div><div><font face="monospace, monospace">    #2 0x7f00fd522f44 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so<wbr>.6+0x21f44)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">previously allocated by thread T0 here:</font></div><div><font face="monospace, monospace">    #0 0x508b70 in operator new(unsigned long) /home/d80049854/projects/clang<wbr>/4.0.0/llvm/projects/compiler-<wbr>rt/lib/asan/asan_new_delete.<wbr>cc:82</font></div><div><font face="monospace, monospace">    #1 0x7f00fe4d0f68 in std::string::_Rep::_S_create(u<wbr>nsigned long, unsigned long, std::allocator<char> const&) (/usr/lib/x86_64-linux-gnu/lib<wbr>stdc++.so.6+0xc3f68)</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">SUMMARY: AddressSanitizer: heap-use-after-free /home/d80049854/projects/clang<wbr>/4.0.0/llvm/projects/compiler-<wbr>rt/lib/asan/../sanitizer_<wbr>common/sanitizer_common_<wbr>interceptors.inc:655 in __interceptor_memcpy.part.36</font></div><div><font face="monospace, monospace">Shadow bytes around the buggy address:</font></div><div><font face="monospace, monospace">  0x0c087fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</font></div><div><font face="monospace, monospace">  0x0c087fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</font></div><div><font face="monospace, monospace">  0x0c087fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</font></div><div><font face="monospace, monospace">  0x0c087fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</font></div><div><font face="monospace, monospace">  0x0c087fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</font></div><div><font face="monospace, monospace">=>0x0c087fff8000: fa fa 00 00 00 00 00 01 fa fa fd fd fd[fd]fd fa</font></div><div><font face="monospace, monospace">  0x0c087fff8010: fa fa 00 00 00 00 01 fa fa fa fa fa fa fa fa fa</font></div><div><font face="monospace, monospace">  0x0c087fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa</font></div><div><font face="monospace, monospace">  0x0c087fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa</font></div><div><font face="monospace, monospace">  0x0c087fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa</font></div><div><font face="monospace, monospace">  0x0c087fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa</font></div><div><font face="monospace, monospace">Shadow byte legend (one shadow byte represents 8 application bytes):</font></div><div><font face="monospace, monospace">  Addressable:           00</font></div><div><font face="monospace, monospace">  Partially addressable: 01 02 03 04 05 06 07</font></div><div><font face="monospace, monospace">  Heap left redzone:       fa</font></div><div><font face="monospace, monospace">  Freed heap region:       fd</font></div><div><font face="monospace, monospace">  Stack left redzone:      f1</font></div><div><font face="monospace, monospace">  Stack mid redzone:       f2</font></div><div><font face="monospace, monospace">  Stack right redzone:     f3</font></div><div><font face="monospace, monospace">  Stack after return:      f5</font></div><div><font face="monospace, monospace">  Stack use after scope:   f8</font></div><div><font face="monospace, monospace">  Global redzone:          f9</font></div><div><font face="monospace, monospace">  Global init order:       f6</font></div><div><font face="monospace, monospace">  Poisoned by user:        f7</font></div><div><font face="monospace, monospace">  Container overflow:      fc</font></div><div><font face="monospace, monospace">  Array cookie:            ac</font></div><div><font face="monospace, monospace">  Intra object redzone:    bb</font></div><div><font face="monospace, monospace">  ASan internal:           fe</font></div><div><font face="monospace, monospace">  Left alloca redzone:     ca</font></div><div><font face="monospace, monospace">  Right alloca redzone:    cb</font></div><div><font face="monospace, monospace">==14769==ABORTING</font></div></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">1. AST diff:</font></div><div><font face="monospace, monospace">< uses ss</font></div><div><font face="monospace, monospace">> uses ss.c_str()</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace" size="1"><div>49566c49566</div><div>< | | |-CXXConstructorDecl 0xXXXXXXX <line:3010:7, col:XX> col:XX used basic_string 'void (const char *, const class std::allocator<char> &)'</div><div>---</div><div>> | | |-CXXConstructorDecl 0xXXXXXXX <line:3010:7, col:XX> col:XX basic_string 'void (const char *, const class std::allocator<char> &)'</div><div>49568,49573c49568</div><div>< | | | `-ParmVarDecl 0xXXXXXXX <col:XX, col:XX> col:XX __a 'const class std::allocator<char> &' cinit</div><div>< | | |   `-ExprWithCleanups 0xXXXXXXX <col:XX, col:XX> 'const class std::allocator<char>':'const class std::allocator<char>' lvalue</div><div>< | | |     `-MaterializeTemporaryExpr 0xXXXXXXX <col:XX, col:XX> 'const class std::allocator<char>':'const class std::allocator<char>' lvalue</div><div>< | | |       `-ImplicitCastExpr 0xXXXXXXX <col:XX, col:XX> 'const class std::allocator<char>':'const class std::allocator<char>' <NoOp></div><div>< | | |         `-CXXBindTemporaryExpr 0xXXXXXXX <col:XX, col:XX> 'class std::allocator<char>':'class std::allocator<char>' (CXXTemporary 0xXXXXXXX)</div><div>< | | |           `-CXXTemporaryObjectExpr 0xXXXXXXX <col:XX, col:XX> 'class std::allocator<char>':'class std::allocator<char>' 'void (void) throw()'</div><div>---</div><div>> | | | `-ParmVarDecl 0xXXXXXXX <col:XX, col:XX> col:XX __a 'const class std::allocator<char> &'</div><div>108945c108940</div><div>< | | |-CXXConstructorDecl 0xXXXXXXX <../../llvm/include/llvm/<wbr>Support/Compiler.h:194:38, ../../llvm/include/llvm/ADT/<wbr>StringRef.h:96:49> line:95:18 used StringRef 'void (const std::string &)'</div><div>---</div><div>> | | |-CXXConstructorDecl 0xXXXXXXX <../../llvm/include/llvm/<wbr>Support/Compiler.h:194:38, ../../llvm/include/llvm/ADT/<wbr>StringRef.h:96:49> line:95:18 StringRef 'void (const std::string &)'</div><div>111747,111765c111742,111749</div><div><     |           `-CXXConstructExpr 0xXXXXXXX <col:XX, col:XX> 'llvm::StringRef':'class llvm::StringRef' 'void (const std::string &)'</div><div><     |             `-MaterializeTemporaryExpr 0xXXXXXXX <col:XX, col:XX> 'const std::string':'const class std::basic_string<char>' lvalue</div><div><     |               `-ConditionalOperator 0xXXXXXXX <col:XX, col:XX> 'const std::string':'const class std::basic_string<char>'</div><div><     |                 |-CXXBoolLiteralExpr 0xXXXXXXX <col:XX> '_Bool' true</div><div><     |                 |-CXXBindTemporaryExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' (CXXTemporary 0xXXXXXXX)</div><div><     |                 | `-CXXConstructExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' 'void (const class std::basic_string<char> &)' elidable</div><div><     |                 |   `-MaterializeTemporaryExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' lvalue</div><div><     |                 |     `-CXXBindTemporaryExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' (CXXTemporary 0xXXXXXXX)</div><div><     |                 |       `-CXXConstructExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' 'void (class std::basic_string<char> &&) noexcept' elidable</div><div><     |                 |         `-MaterializeTemporaryExpr 0xXXXXXXX <col:XX> 'std::string':'class std::basic_string<char>' xvalue</div><div><     |                 |           `-CXXBindTemporaryExpr 0xXXXXXXX <col:XX> 'std::string':'class std::basic_string<char>' (CXXTemporary 0xXXXXXXX)</div><div><     |                 |             `-ImplicitCastExpr 0xXXXXXXX <col:XX> 'std::string':'class std::basic_string<char>' <ConstructorConversion></div><div><     |                 |               `-CXXConstructExpr 0xXXXXXXX <col:XX> 'std::string':'class std::basic_string<char>' 'void (const char *, const class std::allocator<char> &)'</div><div><     |                 |                 |-ImplicitCastExpr 0xXXXXXXX <col:XX> 'const char *' <ArrayToPointerDecay></div><div><     |                 |                 | `-StringLiteral 0xXXXXXXX <col:XX> 'const char [9]' lvalue "noexcept"</div><div><     |                 |                 `-CXXDefaultArgExpr 0xXXXXXXX <<invalid sloc>> 'const class std::allocator<char>':'const class std::allocator<char>' lvalue</div><div><     |                 `-CXXBindTemporaryExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' (CXXTemporary 0xXXXXXXX)</div><div><     |                   `-CXXConstructExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' 'void (const class std::basic_string<char> &)'</div><div><     |                     `-DeclRefExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' lvalue Var 0xXXXXXXX 'ss' 'const std::string':'const class std::basic_string<char>'</div><div>---</div><div>>     |           `-CXXConstructExpr 0xXXXXXXX <col:XX, col:XX> 'llvm::StringRef':'class llvm::StringRef' 'void (const char *)'</div><div>>     |             `-ConditionalOperator 0xXXXXXXX <col:XX, col:XX> 'const char *'</div><div>>     |               |-CXXBoolLiteralExpr 0xXXXXXXX <col:XX> '_Bool' true</div><div>>     |               |-ImplicitCastExpr 0xXXXXXXX <col:XX> 'const char *' <ArrayToPointerDecay></div><div>>     |               | `-StringLiteral 0xXXXXXXX <col:XX> 'const char [9]' lvalue "noexcept"</div><div>>     |               `-CXXMemberCallExpr 0xXXXXXXX <col:XX, col:XX> 'const char *'</div><div>>     |                 `-MemberExpr 0xXXXXXXX <col:XX, col:XX> '<bound member function type>' .c_str 0xXXXXXXX</div><div>>     |                   `-DeclRefExpr 0xXXXXXXX <col:XX> 'const std::string':'const class std::basic_string<char>' lvalue Var 0xXXXXXXX 'ss' 'const std::string':'const class std::basic_string<char>'</div></font></div></div>