From baf82b0fdf5c23dff80660add40bb92bd850bba0 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 17 Aug 2011 22:19:53 +0000 Subject: [PATCH] [libclang] Workaround potential race condition with code completion AllocatedResults being freed after a CXTranslationUnit. The Container USR's CXString had its underlying data owned by the CXTranslationUnit's string pool. This would result in trying to access freed memory. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137887 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CIndexCodeCompletion.cpp | 13 +++++++++++++ tools/libclang/CXString.cpp | 4 ++++ tools/libclang/CXString.h | 3 +++ 3 files changed, 20 insertions(+) diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index 93571e0c35..2159298989 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -16,6 +16,7 @@ #include "CXTranslationUnit.h" #include "CXString.h" #include "CXCursor.h" +#include "CXString.h" #include "CIndexDiagnostic.h" #include "clang/AST/Type.h" #include "clang/AST/Decl.h" @@ -541,8 +542,20 @@ namespace { CXCursorKind cursorKind = clang_getCursorKind(cursor); CXString cursorUSR = clang_getCursorUSR(cursor); + // Normally, clients of CXString shouldn't care whether or not + // a CXString is managed by a pool or by explicitly malloc'ed memory. + // However, there are cases when AllocatedResults outlives the + // CXTranslationUnit. This is a workaround that failure mode. + if (cxstring::isManagedByPool(cursorUSR)) { + CXString heapStr = + cxstring::createCXString(clang_getCString(cursorUSR), true); + clang_disposeString(cursorUSR); + cursorUSR = heapStr; + } + AllocatedResults.ContainerKind = cursorKind; AllocatedResults.ContainerUSR = cursorUSR; + const Type *type = baseType.getTypePtrOrNull(); if (type != NULL) { AllocatedResults.ContainerIsIncomplete = type->isIncompleteType(); diff --git a/tools/libclang/CXString.cpp b/tools/libclang/CXString.cpp index 268655ab8a..bb09cd5cdc 100644 --- a/tools/libclang/CXString.cpp +++ b/tools/libclang/CXString.cpp @@ -101,6 +101,10 @@ void cxstring::disposeCXStringBuf(CXStringBuf *buf) { static_cast(buf->TU->StringPool)->push_back(buf); } +bool cxstring::isManagedByPool(CXString str) { + return ((CXStringFlag) str.private_flags) == CXS_StringBuf; +} + //===----------------------------------------------------------------------===// // libClang public APIs. //===----------------------------------------------------------------------===// diff --git a/tools/libclang/CXString.h b/tools/libclang/CXString.h index 45d13eb3e3..d36c7c1e68 100644 --- a/tools/libclang/CXString.h +++ b/tools/libclang/CXString.h @@ -47,6 +47,9 @@ CXStringBuf *getCXStringBuf(CXTranslationUnit TU); void disposeCXStringBuf(CXStringBuf *buf); +/// \brief Returns true if the CXString data is managed by a pool. +bool isManagedByPool(CXString str); + } } -- 2.40.0