[Mesa-dev] [PATCH 041/140] amdgpu/addrlib: fix crash on allocation failure

Marek Olšák maraeo at gmail.com
Mon Mar 20 22:42:51 UTC 2017


From: Sabre Shao <sabre.shao at amd.com>

---
 src/amd/addrlib/core/addrelemlib.cpp |  6 +++++-
 src/amd/addrlib/core/addrobject.cpp  | 41 ++++++++++++------------------------
 src/amd/addrlib/core/addrobject.h    | 14 ++++++------
 src/amd/addrlib/r800/ciaddrlib.h     |  3 ++-
 src/amd/addrlib/r800/siaddrlib.h     |  3 ++-
 5 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/src/amd/addrlib/core/addrelemlib.cpp b/src/amd/addrlib/core/addrelemlib.cpp
index c9d2074..770cee3 100644
--- a/src/amd/addrlib/core/addrelemlib.cpp
+++ b/src/amd/addrlib/core/addrelemlib.cpp
@@ -103,21 +103,25 @@ ElemLib::~ElemLib()
 *       Returns point to ADDR_CREATEINFO if successful.
 ****************************************************************************************************
 */
 ElemLib* ElemLib::Create(
     const Lib* pAddrLib)   ///< [in] Pointer of parent AddrLib instance
 {
     ElemLib* pElemLib = NULL;
 
     if (pAddrLib)
     {
-        pElemLib = new(pAddrLib->GetClient()) ElemLib(const_cast<Lib* const>(pAddrLib));
+        VOID* pObj = Object::ClientAlloc(sizeof(ElemLib), pAddrLib->GetClient());
+        if (pObj)
+        {
+            pElemLib = new(pObj) ElemLib(const_cast<Lib* const>(pAddrLib));
+        }
     }
 
     return pElemLib;
 }
 
 /**************************************************************************************************
 *   ElemLib::Flt32sToInt32s
 *
 *   @brief
 *       Convert a ADDR_FLT_32 value to Int32 value
diff --git a/src/amd/addrlib/core/addrobject.cpp b/src/amd/addrlib/core/addrobject.cpp
index cb62aa0..dcdb1bf 100644
--- a/src/amd/addrlib/core/addrobject.cpp
+++ b/src/amd/addrlib/core/addrobject.cpp
@@ -80,21 +80,21 @@ Object::~Object()
 
 /**
 ****************************************************************************************************
 *   Object::ClientAlloc
 *
 *   @brief
 *       Calls instanced allocSysMem inside Client
 ****************************************************************************************************
 */
 VOID* Object::ClientAlloc(
-    size_t             objSize,    ///< [in] Size to allocate
+    size_t         objSize,    ///< [in] Size to allocate
     const Client*  pClient)    ///< [in] Client pointer
 {
     VOID* pObjMem = NULL;
 
     if (pClient->callbacks.allocSysMem != NULL)
     {
         ADDR_ALLOCSYSMEM_INPUT allocInput = {0};
 
         allocInput.size        = sizeof(ADDR_ALLOCSYSMEM_INPUT);
         allocInput.flags.value = 0;
@@ -109,35 +109,36 @@ VOID* Object::ClientAlloc(
 
 /**
 ****************************************************************************************************
 *   Object::Alloc
 *
 *   @brief
 *       A wrapper of ClientAlloc
 ****************************************************************************************************
 */
 VOID* Object::Alloc(
-    size_t objSize) const   ///< [in] Size to allocate
+    size_t objSize      ///< [in] Size to allocate
+    ) const
 {
     return ClientAlloc(objSize, &m_client);
 }
 
 /**
 ****************************************************************************************************
 *   Object::ClientFree
 *
 *   @brief
 *       Calls freeSysMem inside Client
 ****************************************************************************************************
 */
 VOID Object::ClientFree(
-    VOID*              pObjMem,    ///< [in] User virtual address to free.
+    VOID*          pObjMem,    ///< [in] User virtual address to free.
     const Client*  pClient)    ///< [in] Client pointer
 {
     if (pClient->callbacks.freeSysMem != NULL)
     {
         if (pObjMem != NULL)
         {
             ADDR_FREESYSMEM_INPUT freeInput = {0};
 
             freeInput.size      = sizeof(ADDR_FREESYSMEM_INPUT);
             freeInput.hClient   = pClient->handle;
@@ -150,88 +151,74 @@ VOID Object::ClientFree(
 
 /**
 ****************************************************************************************************
 *   Object::Free
 *
 *   @brief
 *       A wrapper of ClientFree
 ****************************************************************************************************
 */
 VOID Object::Free(
-    VOID* pObjMem) const                 ///< [in] User virtual address to free.
+    VOID* pObjMem       ///< [in] User virtual address to free.
+    ) const
 {
     ClientFree(pObjMem, &m_client);
 }
 
 /**
 ****************************************************************************************************
 *   Object::operator new
 *
 *   @brief
-*       Allocates memory needed for Object object. (with ADDR_CLIENT_HANDLE)
+*       Placement new operator. (with pre-allocated memory pointer)
 *
 *   @return
-*       Returns NULL if unsuccessful.
+*       Returns pre-allocated memory pointer.
 ****************************************************************************************************
 */
 VOID* Object::operator new(
-    size_t             objSize,    ///< [in] Size to allocate
-    const Client*  pClient)    ///< [in] Client pointer
-{
-    return ClientAlloc(objSize, pClient);
-}
-
-
-/**
-****************************************************************************************************
-*   Object::operator delete
-*
-*   @brief
-*       Frees Object object memory.
-****************************************************************************************************
-*/
-VOID Object::operator delete(
-    VOID* pObjMem,              ///< [in] User virtual address to free.
-    const Client* pClient)  ///< [in] Client handle
+    size_t objSize,     ///< [in] Size to allocate
+    VOID*  pMem)        ///< [in] Pre-allocated pointer
 {
-    ClientFree(pObjMem, pClient);
+    return pMem;
 }
 
 /**
 ****************************************************************************************************
 *   Object::operator delete
 *
 *   @brief
 *       Frees Object object memory.
 ****************************************************************************************************
 */
 VOID Object::operator delete(
-    VOID* pObjMem)                  ///< [in] User virtual address to free.
+    VOID* pObjMem)      ///< [in] User virtual address to free.
 {
     Object* pObj = static_cast<Object*>(pObjMem);
     ClientFree(pObjMem, &pObj->m_client);
 }
 
 /**
 ****************************************************************************************************
 *   Object::DebugPrint
 *
 *   @brief
 *       Print debug message
 *
 *   @return
 *       N/A
 ****************************************************************************************************
 */
 VOID Object::DebugPrint(
     const CHAR* pDebugString,     ///< [in] Debug string
-    ...) const
+    ...
+    ) const
 {
 #if DEBUG
     if (m_client.callbacks.debugPrint != NULL)
     {
         va_list ap;
 
         va_start(ap, pDebugString);
 
         ADDR_DEBUGPRINT_INPUT debugPrintInput = {0};
 
diff --git a/src/amd/addrlib/core/addrobject.h b/src/amd/addrlib/core/addrobject.h
index 031103b..66886f6 100644
--- a/src/amd/addrlib/core/addrobject.h
+++ b/src/amd/addrlib/core/addrobject.h
@@ -55,39 +55,41 @@ struct Client
 * @brief This class is the base class for all ADDR class objects.
 ****************************************************************************************************
 */
 class Object
 {
 public:
     Object();
     Object(const Client* pClient);
     virtual ~Object();
 
-    VOID* operator new(size_t size, const Client* pClient);
-    VOID  operator delete(VOID* pObj, const Client* pClient);
+    VOID* operator new(size_t size, VOID* pMem);
     VOID  operator delete(VOID* pObj);
+    /// Microsoft compiler requires a matching delete implementation, which seems to be called when
+    /// bad_alloc is thrown. But currently C++ exception isn't allowed so a dummy implementation is
+    /// added to eliminate the warning.
+    VOID  operator delete(VOID* pObj, VOID* pMem) { ADDR_ASSERT_ALWAYS(); }
+
     VOID* Alloc(size_t size) const;
     VOID  Free(VOID* pObj) const;
 
-    VOID DebugPrint(
-        const CHAR* pDebugString,
-        ...) const;
+    VOID DebugPrint(const CHAR* pDebugString, ...) const;
 
     const Client* GetClient() const {return &m_client;}
 
 protected:
     Client m_client;
 
-private:
     static VOID* ClientAlloc(size_t size, const Client* pClient);
     static VOID  ClientFree(VOID* pObj, const Client* pClient);
 
+private:
     // disallow the copy constructor
     Object(const Object& a);
 
     // disallow the assignment operator
     Object& operator=(const Object& a);
 };
 
 } // Addr
 #endif
 
diff --git a/src/amd/addrlib/r800/ciaddrlib.h b/src/amd/addrlib/r800/ciaddrlib.h
index c59a0b1..f6c8655 100644
--- a/src/amd/addrlib/r800/ciaddrlib.h
+++ b/src/amd/addrlib/r800/ciaddrlib.h
@@ -78,21 +78,22 @@ struct CIChipSettings
 * @brief This class is the CI specific address library
 *        function set.
 ****************************************************************************************************
 */
 class CiLib : public SiLib
 {
 public:
     /// Creates CiLib object
     static Addr::Lib* CreateObj(const Client* pClient)
     {
-        return new(pClient) CiLib(pClient);
+        VOID* pMem = Object::ClientAlloc(sizeof(CiLib), pClient);
+        return (pMem != NULL) ? new (pMem) CiLib(pClient) : NULL;
     }
 
 private:
     CiLib(const Client* pClient);
     virtual ~CiLib();
 
 protected:
 
     // Hwl interface - defined in AddrLib1
     virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo(
diff --git a/src/amd/addrlib/r800/siaddrlib.h b/src/amd/addrlib/r800/siaddrlib.h
index 80c5cf4..86d2116 100644
--- a/src/amd/addrlib/r800/siaddrlib.h
+++ b/src/amd/addrlib/r800/siaddrlib.h
@@ -78,21 +78,22 @@ struct SIChipSettings
 * @brief This class is the SI specific address library
 *        function set.
 ****************************************************************************************************
 */
 class SiLib : public EgBasedLib
 {
 public:
     /// Creates SiLib object
     static Addr::Lib* CreateObj(const Client* pClient)
     {
-        return new(pClient) SiLib(pClient);
+        VOID* pMem = Object::ClientAlloc(sizeof(SiLib), pClient);
+        return (pMem != NULL) ? new (pMem) SiLib(pClient) : NULL;
     }
 
 protected:
     SiLib(const Client* pClient);
     virtual ~SiLib();
 
     // Hwl interface - defined in AddrLib1
     virtual ADDR_E_RETURNCODE HwlComputeSurfaceInfo(
         const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn,
         ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut) const;
-- 
2.7.4



More information about the mesa-dev mailing list