Issue 138881
Summary [clang-c CXString] What is the lifetime of a CXString?
Labels new issue
Assignees
Reporter illusory0x0
    In the `clang-c/Index.h` header file, there is no clear description of the CXString's lifetime.

CXString's lifetime might be static, not relevant to `CXTranslationUnit` and `CXIndex`, or depending on both `CXTranslationUnit` and `CXIndex`.Those behaviors I've observed. But what is the actually lifetime of the CXString?

```c++
/**
 * A character string.
 *
 * The \c CXString type is used to return strings from the interface when
 * the ownership of that string might differ from one call to the next.
 * Use \c clang_getCString() to retrieve the string data and, once finished
 * with the string data, call \c clang_disposeString() to free the string.
 */
typedef struct {
  const void *data;
  unsigned private_flags;
} CXString;
```


### Example 1 (depending on CXTranslationUnit and CXIndex)


```c++
#include <clang-c/Index.h>
#include <iostream>
#include <vector>

int main() {
 CXIndex index = clang_createIndex(0, 0); // Create index
  CXTranslationUnit unit =
      clang_parseTranslationUnit(index, "file.cpp", nullptr, 0, nullptr, 0,
 CXTranslationUnit_DetailedPreprocessingRecord); // Parse "file.cpp"

  if (unit == nullptr) {
    std::cerr << "Unable to parse translation unit. Quitting.\n";
    return 0;
  }
  CXCursor cursor = clang_getTranslationUnitCursor(
      unit); // Obtain a cursor at the root of the translation unit
  std::vector<CXString> vec;

 clang_visitChildren(
      cursor,
      [](CXCursor current_cursor, CXCursor parent, CXClientData client_data) {
        CXString css =
 clang_getCursorSpelling(current_cursor);
        auto vec = (std::vector<CXString> *)client_data;
        vec->push_back(css);
 return CXChildVisit_Recurse;
      },
      &vec);

 clang_disposeTranslationUnit(unit);
  clang_disposeIndex(index);
  for (auto x : vec) {
    std::cout << clang_getCString(x) << '\n';
 clang_disposeString(x);
  }
}
```

```
==29048==ERROR: AddressSanitizer: heap-use-after-free on address 0x52100006fa08 at pc 0x7b8d76a7d96f bp 0x7ffecc6e3a90 sp 0x7ffecc6e3238
READ of size 9 at 0x52100006fa08 thread T0
    #0 0x7b8d76a7d96e in strlen ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:391
 #1 0x7b8d7455712d in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (/lib/x86_64-linux-gnu/libstdc++.so.6+0x15712d) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 0x633abfaa6b9f in main (/home/illu/playgound/cxx/libclang-example/build/main+0x2b9f) (BuildId: d56c11e25e7e94615c48a390146a7373f424c47f)
    #3 0x7b8d7402a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #4 0x7b8d7402a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #5 0x633abfaa6484 in _start (/home/illu/playgound/cxx/libclang-example/build/main+0x2484) (BuildId: d56c11e25e7e94615c48a390146a7373f424c47f)

0x52100006fa08 is located 1288 bytes inside of 4096-byte region [0x52100006f500,0x521000070500)
freed by thread T0 here:
    #0 0x7b8d76aff888 in operator delete(void*, std::align_val_t) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:170
 #1 0x7b8d74c4f71e  (/usr/lib/llvm-18/lib/libclang-18.so.18+0x44f71e) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #2 0x7b8d754d2430 (/usr/lib/llvm-18/lib/libclang-18.so.18+0xcd2430) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #3 0x7b8d753320a1 (/usr/lib/llvm-18/lib/libclang-18.so.18+0xb320a1) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #4 0x7b8d74c27a98 in clang_disposeTranslationUnit (/usr/lib/llvm-18/lib/libclang-18.so.18+0x427a98) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #5 0x633abfaa6a36 in main (/home/illu/playgound/cxx/libclang-example/build/main+0x2a36) (BuildId: d56c11e25e7e94615c48a390146a7373f424c47f)
    #6 0x7b8d7402a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #7 0x7b8d7402a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #8 0x633abfaa6484 in _start (/home/illu/playgound/cxx/libclang-example/build/main+0x2484) (BuildId: d56c11e25e7e94615c48a390146a7373f424c47f)

previously allocated by thread T1 here:
    #0 0x7b8d76afeaf8 in operator new(unsigned long, std::align_val_t) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:107
 #1 0x7b8d74c414b3  (/usr/lib/llvm-18/lib/libclang-18.so.18+0x4414b3) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #2 0x7b8d74c43dc0 (/usr/lib/llvm-18/lib/libclang-18.so.18+0x443dc0) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #3 0x7b8d750d281d (/usr/lib/llvm-18/lib/libclang-18.so.18+0x8d281d) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #4 0x7b8d753cfd92 (/usr/lib/llvm-18/lib/libclang-18.so.18+0xbcfd92) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #5 0x7b8d75334e23 (/usr/lib/llvm-18/lib/libclang-18.so.18+0xb34e23) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #6 0x7b8d75338596 (/usr/lib/llvm-18/lib/libclang-18.so.18+0xb38596) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #7 0x7b8d753393c2 (/usr/lib/llvm-18/lib/libclang-18.so.18+0xb393c2) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #8 0x7b8d74c48a13 (/usr/lib/llvm-18/lib/libclang-18.so.18+0x448a13) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #9 0x7b8d6d4eff76 in llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/usr/lib/llvm-18/lib/../lib/libLLVM.so.18.1+0xceff76) (BuildId: 495b188fed20e21b476ccb1eaea212f4304fad28)
    #10 0x7b8d6d4f016c (/usr/lib/llvm-18/lib/../lib/libLLVM.so.18.1+0xcf016c) (BuildId: 495b188fed20e21b476ccb1eaea212f4304fad28)
    #11 0x7b8d6d4f02b2 (/usr/lib/llvm-18/lib/../lib/libLLVM.so.18.1+0xcf02b2) (BuildId: 495b188fed20e21b476ccb1eaea212f4304fad28)
    #12 0x7b8d76a5ea41 in asan_thread_start ../../../../src/libsanitizer/asan/asan_interceptors.cpp:234
    #13 0x7b8d7409caa3 in start_thread nptl/pthread_create.c:447

Thread T1 created by T0 here:
    #0 0x7b8d76af51f9 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:245
    #1 0x7b8d6d5a7981 in llvm::llvm_execute_on_thread_impl(void* (*)(void*), void*, std::optional<unsigned int>) (/usr/lib/llvm-18/lib/../lib/libLLVM.so.18.1+0xda7981) (BuildId: 495b188fed20e21b476ccb1eaea212f4304fad28)
    #2 0x7b8d6d4f00f4 in llvm::CrashRecoveryContext::RunSafelyOnThread(llvm::function_ref<void ()>, unsigned int) (/usr/lib/llvm-18/lib/../lib/libLLVM.so.18.1+0xcf00f4) (BuildId: 495b188fed20e21b476ccb1eaea212f4304fad28)
    #3 0x7b8d74c3156d in clang_parseTranslationUnit2FullArgv (/usr/lib/llvm-18/lib/libclang-18.so.18+0x43156d) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #4 0x7b8d74c31188 in clang_parseTranslationUnit2 (/usr/lib/llvm-18/lib/libclang-18.so.18+0x431188) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #5 0x7b8d74c31087 in clang_parseTranslationUnit (/usr/lib/llvm-18/lib/libclang-18.so.18+0x431087) (BuildId: ea056e259864b6af08c46875208cc97be270ce0e)
    #6 0x633abfaa689f in main (/home/illu/playgound/cxx/libclang-example/build/main+0x289f) (BuildId: d56c11e25e7e94615c48a390146a7373f424c47f)
    #7 0x7b8d7402a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #8 0x7b8d7402a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #9 0x633abfaa6484 in _start (/home/illu/playgound/cxx/libclang-example/build/main+0x2484) (BuildId: d56c11e25e7e94615c48a390146a7373f424c47f)

SUMMARY: AddressSanitizer: heap-use-after-free ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:391 in strlen
Shadow bytes around the buggy address:
  0x52100006f780: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x52100006f800: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x52100006f880: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x52100006f900: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x52100006f980: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x52100006fa00: fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 0x52100006fa80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 0x52100006fb00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 0x52100006fb80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 0x52100006fc00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 0x52100006fc80: 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
==29048==ABORTING
make: *** [Makefile:5: run_main] Error 1

```

### Example 2 (Not Relevant to CXTranslationUnit and CXIndex)

```C++
#include <clang-c/Index.h>
#include <iostream>
#include <vector>

int main() {
  CXIndex index = clang_createIndex(0, 0); // Create index
  CXTranslationUnit unit =
 clang_parseTranslationUnit(index, "file.cpp", nullptr, 0, nullptr, 0,
 CXTranslationUnit_None); // Parse "file.cpp"

  if (unit == nullptr) {
    std::cerr << "Unable to parse translation unit. Quitting.\n";
    return 0;
  }
  CXCursor cursor = clang_getTranslationUnitCursor(
      unit); // Obtain a cursor at the root of the translation unit
  std::vector<CXString> vec;

 clang_visitChildren(
      cursor,
      [](CXCursor current_cursor, CXCursor parent, CXClientData client_data) {
        CXString css =
 clang_getCursorSpelling(current_cursor);
        auto vec = (std::vector<CXString> *)client_data;
        vec->push_back(css);
 return CXChildVisit_Recurse;
      },
      &vec);

 clang_disposeTranslationUnit(unit);
  clang_disposeIndex(index);
  for (auto x : vec) {
    std::cout << clang_getCString(x) << '\n';
 clang_disposeString(x);
  }
}
```

```
cmake -G Ninja -B build -S .; cmake --build build
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/illu/playgound/cxx/libclang-example/build
[2/2] Linking CXX executable main
./build/main
A
value
B
value
struct_value
struct A

```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to