Skip to content

Commit 906fc46

Browse files
authored
Fix ASAN memory leak in FileChecker (#5718)
AllocVFSIncludeHandler was returning it's IUnknown object by Detach()ing from a CComPtr, then assiging to CComPtr. This would result in the object have a ref count of 2, and when the second CComPtr destructed, it would go down to 1, and leak memory. The fix is to return the object as a CComPtr; however, with Clang, this failed to compile because it finds no conversion from a CComPtr of child class type to a CComPtr of base class type. This compiles fine on MSVC, so I debugged it, and realized that MSVC compiles this as first a conversion to T*, then a constructor call. I suspect MSVC is wrong here. In any case, this change adds a template conversion constructor to CComPtr, very much like the existing template assignment operator.
1 parent 08215da commit 906fc46

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

include/dxc/WinAdapter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,13 @@ template <class T> class CComPtr : public CComPtrBase<T> {
748748
return *this;
749749
}
750750

751+
// NOTE: This conversion constructor is not part of the official CComPtr spec;
752+
// however, it is needed to convert CComPtr<Q> to CComPtr<T> where T derives from Q on Clang.
753+
// MSVC compiles this conversion as first a call to CComPtr<Q>::operator T*, followed by CComPtr<T>(T*),
754+
// but Clang fails to compile with error: no viable conversion from 'CComPtr<Q>' to 'CComPtr<T>'.
755+
template <typename Q>
756+
CComPtr(const CComPtr<Q> &lp) throw() : CComPtrBase<T>(lp.p) {}
757+
751758
T *operator=(const CComPtr<T> &lp) throw() {
752759
if (*this != lp) {
753760
CComPtr(lp).Swap(*this);

tools/clang/unittests/HLSLTestLib/FileCheckerTest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class IncludeHandlerVFSOverlayForTest : public IDxcIncludeHandler {
256256
}
257257
};
258258

259-
static IncludeHandlerVFSOverlayForTest *AllocVFSIncludeHandler(IUnknown *pUnkLibrary, const FileMap *pVFS) {
259+
static CComPtr<IncludeHandlerVFSOverlayForTest> AllocVFSIncludeHandler(IUnknown *pUnkLibrary, const FileMap *pVFS) {
260260
CComPtr<IncludeHandlerVFSOverlayForTest> pVFSIncludeHandler = IncludeHandlerVFSOverlayForTest::Alloc(DxcGetThreadMallocNoRef());
261261
IFTBOOL(pVFSIncludeHandler, E_OUTOFMEMORY);
262262
if (pUnkLibrary) {
@@ -273,7 +273,7 @@ static IncludeHandlerVFSOverlayForTest *AllocVFSIncludeHandler(IUnknown *pUnkLib
273273
pVFSIncludeHandler->pInnerIncludeHandler = pInnerIncludeHandler;
274274
}
275275
pVFSIncludeHandler->pVFS = pVFS;
276-
return pVFSIncludeHandler.Detach();
276+
return pVFSIncludeHandler;
277277
}
278278

279279
static void AddOutputsToFileMap(IUnknown *pUnkResult, FileMap *pVFS) {

0 commit comments

Comments
 (0)