fixed memory leak in Oracle DB driver
authorVictor Kirhenshtein <victor@netxms.org>
Sat, 14 May 2016 15:08:25 +0000 (18:08 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Sat, 14 May 2016 15:08:25 +0000 (18:08 +0300)
src/db/dbdrv/oracle/oracle.cpp

index ae4b6da..8b8929f 100644 (file)
@@ -1,6 +1,6 @@
 /* 
 ** Oracle Database Driver
-** Copyright (C) 2007-2015 Victor Kirhenshtein
+** Copyright (C) 2007-2016 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -160,12 +160,12 @@ static void DestroyQueryResult(ORACLE_RESULT *pResult)
 
        nCount = pResult->nCols * pResult->nRows;
        for(i = 0; i < nCount; i++)
-               safe_free(pResult->pData[i]);
-       safe_free(pResult->pData);
+               free(pResult->pData[i]);
+       free(pResult->pData);
 
        for(i = 0; i < pResult->nCols; i++)
-               safe_free(pResult->columnNames[i]);
-       safe_free(pResult->columnNames);
+               free(pResult->columnNames[i]);
+       free(pResult->columnNames);
 
        free(pResult);
 }
@@ -1204,6 +1204,33 @@ extern "C" void EXPORT DrvFreeResult(ORACLE_RESULT *pResult)
                DestroyQueryResult(pResult);
 }
 
+/**
+ * Destroy unbuffered query result
+ */
+static void DestroyUnbufferedQueryResult(ORACLE_UNBUFFERED_RESULT *result, bool freeStatement)
+{
+   int i;
+
+   if (freeStatement)
+      OCIStmtRelease(result->handleStmt, result->connection->handleError, NULL, 0, OCI_DEFAULT);
+
+   for(i = 0; i < result->nCols; i++)
+   {
+      free(result->pBuffers[i].pData);
+      if (result->pBuffers[i].lobLocator != NULL)
+      {
+         OCIDescriptorFree(result->pBuffers[i].lobLocator, OCI_DTYPE_LOB);
+      }
+   }
+   free(result->pBuffers);
+
+   for(i = 0; i < result->nCols; i++)
+      free(result->columnNames[i]);
+   free(result->columnNames);
+
+   free(result);
+}
+
 /**
  * Process results of unbuffered query execution (prepare for fetching results)
  */
@@ -1219,9 +1246,8 @@ static ORACLE_UNBUFFERED_RESULT *ProcessUnbufferedQueryResults(ORACLE_CONN *pCon
    if (result->nCols > 0)
    {
       // Prepare receive buffers and fetch column names
-      result->columnNames = (char **)malloc(sizeof(char *) * result->nCols);
-      result->pBuffers = (ORACLE_FETCH_BUFFER *)malloc(sizeof(ORACLE_FETCH_BUFFER) * result->nCols);
-      memset(result->pBuffers, 0, sizeof(ORACLE_FETCH_BUFFER) * result->nCols);
+      result->columnNames = (char **)calloc(result->nCols, sizeof(char *));
+      result->pBuffers = (ORACLE_FETCH_BUFFER *)calloc(result->nCols, sizeof(ORACLE_FETCH_BUFFER));
       for(int i = 0; i < result->nCols; i++)
       {
          OCIParam *handleParam;
@@ -1268,6 +1294,7 @@ static ORACLE_UNBUFFERED_RESULT *ProcessUnbufferedQueryResults(ORACLE_CONN *pCon
                                         SQLT_CHR, &result->pBuffers[i].isNull, &result->pBuffers[i].nLength,
                                         &result->pBuffers[i].nCode, OCI_DEFAULT);
             }
+            OCIDescriptorFree(handleParam, OCI_DTYPE_PARAM);
             if (nStatus == OCI_SUCCESS)
             {
                *pdwError = DBERR_SUCCESS;
@@ -1276,14 +1303,16 @@ static ORACLE_UNBUFFERED_RESULT *ProcessUnbufferedQueryResults(ORACLE_CONN *pCon
             {
                SetLastError(pConn);
                *pdwError = IsConnectionError(pConn);
+               DestroyUnbufferedQueryResult(result, false);
+               result = NULL;
+               break;
             }
-            OCIDescriptorFree(handleParam, OCI_DTYPE_PARAM);
          }
          else
          {
             SetLastError(pConn);
             *pdwError = IsConnectionError(pConn);
-            free(result);
+            DestroyUnbufferedQueryResult(result, false);
             result = NULL;
             break;
          }
@@ -1505,29 +1534,12 @@ extern "C" const char EXPORT *DrvGetColumnNameUnbuffered(ORACLE_UNBUFFERED_RESUL
  */
 extern "C" void EXPORT DrvFreeUnbufferedResult(ORACLE_UNBUFFERED_RESULT *result)
 {
-       int i;
-
        if (result == NULL)
                return;
 
-       OCIStmtRelease(result->handleStmt, result->connection->handleError, NULL, 0, OCI_DEFAULT);
-
-       for(i = 0; i < result->nCols; i++)
-   {
-               free(result->pBuffers[i].pData);
-      if (result->pBuffers[i].lobLocator != NULL)
-      {
-         OCIDescriptorFree(result->pBuffers[i].lobLocator, OCI_DTYPE_LOB);
-      }
-   }
-       free(result->pBuffers);
-
-       for(i = 0; i < result->nCols; i++)
-               free(result->columnNames[i]);
-       free(result->columnNames);
-
-       MutexUnlock(result->connection->mutexQueryLock);
-       free(result);
+       MUTEX mutex = result->connection->mutexQueryLock;
+       DestroyUnbufferedQueryResult(result, true);
+       MutexUnlock(mutex);
 }
 
 /**