Fix caching of std::string type.

If the Transaction that holds std::string type is unloaded LookupHelper::m_StringTy will point to invalid memory.
LookupHelper::findType can return an invalid QualType causing dereference of null.
This commit is contained in:
Frederich Munch 2017-06-03 16:23:50 -04:00 committed by sftnight
parent dc100ca69f
commit 8fab0d5be8
5 changed files with 34 additions and 6 deletions

View File

@ -48,6 +48,7 @@ namespace clang {
class Sema;
class SourceLocation;
class SourceManager;
class Type;
class PresumedLoc;
}
@ -196,6 +197,12 @@ namespace cling {
///
mutable std::vector<ClangInternalState*> m_StoredStates;
enum {
kStdStringTransaction = 0, // Transaction known to contain std::string
kNumTransactions
};
mutable const Transaction* m_CachedTrns[kNumTransactions] = {};
///\brief Worker function, building block for interpreter's public
/// interfaces.
///
@ -690,6 +697,12 @@ namespace cling {
///
const Transaction* getLatestTransaction() const;
///\brief Returns a reference to a Transaction known to contain std::string.
///
const Transaction*& getStdStringTransaction() const {
return m_CachedTrns[kStdStringTransaction];
}
///\brief Compile extern "C" function and return its address.
///
///\param[in] name - function name

View File

@ -33,6 +33,8 @@ namespace llvm {
namespace cling {
class Interpreter;
class Transaction;
///\brief Reflection information query interface. The class performs lookups
/// in the currently loaded information in the AST, using the same Parser,
/// Sema and Preprocessor objects.
@ -225,7 +227,6 @@ namespace cling {
///\brief Retrieve the QualType of `std::string`.
const clang::Type* getStringType();
};
} // end namespace

View File

@ -1275,6 +1275,14 @@ namespace cling {
}
}
// Clear any cached transaction states.
for (unsigned i = 0; i < kNumTransactions; ++i) {
if (m_CachedTrns[i] == &T) {
m_CachedTrns[i] = nullptr;
break;
}
}
if (InterpreterCallbacks* callbacks = getCallbacks())
callbacks->TransactionUnloaded(T);
if (m_Executor) { // we also might be in fsyntax-only mode.

View File

@ -1899,8 +1899,12 @@ namespace cling {
}
const Type* LookupHelper::getStringType() {
if (!m_StringTy)
m_StringTy = findType("std::string", WithDiagnostics).getTypePtr();
const Transaction*& Cache = m_Interpreter->getStdStringTransaction();
if (!Cache || !m_StringTy) {
QualType Qt = findType("std::string", WithDiagnostics);
if ((m_StringTy = Qt.isNull() ? nullptr : Qt.getTypePtr()))
Cache = m_Interpreter->getLatestTransaction();
}
return m_StringTy;
}

View File

@ -776,9 +776,11 @@ static std::string printUnpackedClingValue(const Value &V) {
} else if (clang::CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl()) {
if (CXXRD->isLambda())
return printAddress(V.getPtr(), '@');
LookupHelper& LH= V.getInterpreter()->getLookupHelper();
if (C.hasSameType(CXXRD->getTypeForDecl(), LH.getStringType()))
return executePrintValue<std::string>(V, *(std::string*)V.getPtr());
if (const clang::Type* StrTy =
V.getInterpreter()->getLookupHelper().getStringType()) {
if (C.hasSameType(CXXRD->getTypeForDecl(), StrTy))
return executePrintValue<std::string>(V, *(std::string*)V.getPtr());
}
} else if (const clang::BuiltinType *BT
= llvm::dyn_cast<clang::BuiltinType>(Td.getCanonicalType().getTypePtr())) {
switch (BT->getKind()) {