aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Knight <q@1bpm.net>2022-08-25 18:14:53 +0100
committerRichard Knight <q@1bpm.net>2022-08-25 18:14:53 +0100
commit9ac4dfb0f0ba5be3f21bd3904c99ba67543b1833 (patch)
treeeda9aabe89979289d61f8ef40f605f18a3223438 /src
parentdb5bc3227bf89c0eaf2f2498cf0f1a80cf5eead0 (diff)
downloadcsound-sqldb-9ac4dfb0f0ba5be3f21bd3904c99ba67543b1833.tar.gz
csound-sqldb-9ac4dfb0f0ba5be3f21bd3904c99ba67543b1833.tar.bz2
csound-sqldb-9ac4dfb0f0ba5be3f21bd3904c99ba67543b1833.zip
fixed string and array memory leaks
Diffstat (limited to 'src')
-rw-r--r--src/connection.cpp8
-rw-r--r--src/mysql.cpp30
-rw-r--r--src/opcodes.cpp18
-rw-r--r--src/postgresql.cpp34
-rw-r--r--src/sqlite3.cpp41
-rw-r--r--src/tools.cpp54
6 files changed, 107 insertions, 78 deletions
diff --git a/src/connection.cpp b/src/connection.cpp
index 6ad929f..43175bd 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -136,7 +136,7 @@ MYFLT ConnectionData::Scalar(char* sql, int row, int col) {
}
-char* ConnectionData::ScalarString(char* sql, int row, int col) {
+char* ConnectionData::ScalarString(char* sql, csnd::Csound* csound, int row, int col) {
if (!open) {
throw std::runtime_error(badConnection);
}
@@ -144,17 +144,17 @@ char* ConnectionData::ScalarString(char* sql, int row, int col) {
switch (type) {
#ifdef BUILD_POSTGRES
case POSTGRES:
- return postgres->ScalarString(sql, row, col);
+ return postgres->ScalarString(sql, csound, row, col);
break;
#endif
#ifdef BUILD_SQLITE
case SQLITE:
- return sqlite->ScalarString(sql, row, col);
+ return sqlite->ScalarString(sql, csound, row, col);
break;
#endif
#ifdef BUILD_MYSQL
case MYSQL:
- return mysql->ScalarString(sql, row, col);
+ return mysql->ScalarString(sql, csound, row, col);
break;
#endif
default:
diff --git a/src/mysql.cpp b/src/mysql.cpp
index 2362d60..381898b 100644
--- a/src/mysql.cpp
+++ b/src/mysql.cpp
@@ -20,6 +20,7 @@
*/
#include <plugin.h>
+#include "tools.h"
#include <iostream>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
@@ -67,6 +68,7 @@ MYFLT MySQLConnection::Scalar(char* sql, int row, int col) {
mysql::ResultSetMetaData* meta = res->getMetaData();
int colCount = meta->getColumnCount();
if (col > colCount - 1) {
+ delete res;
throw std::runtime_error("column number out of range");
}
@@ -78,12 +80,13 @@ MYFLT MySQLConnection::Scalar(char* sql, int row, int col) {
return result;
}
-char* MySQLConnection::ScalarString(char* sql, int row, int col) {
+char* MySQLConnection::ScalarString(char* sql, csnd::Csound* csound, int row, int col) {
mysql::ResultSet* res = Query(sql);
mysql::ResultSetMetaData* meta = res->getMetaData();
int colCount = meta->getColumnCount();
if (col > colCount - 1) {
+ delete res;
throw std::runtime_error("column number out of range");
}
@@ -91,7 +94,7 @@ char* MySQLConnection::ScalarString(char* sql, int row, int col) {
for (int rowIndex = 0; rowIndex <= row; rowIndex++) {
res->next();
}
- char* result = (char*) res->getString(col + 1).c_str();
+ char* result = csound->strdup((char*) res->getString(col + 1).c_str());
delete res;
@@ -101,31 +104,18 @@ char* MySQLConnection::ScalarString(char* sql, int row, int col) {
void MySQLConnection::ToArray(mysql::ResultSet* result, csnd::Csound* csound, ARRAYDAT* array, bool asString) {
mysql::ResultSetMetaData* meta = result->getMetaData();
- int colNum = meta->getColumnCount();
- int rowNum = result->rowsCount();
- int totalResults = colNum * rowNum;
- array->sizes = (int32_t*) csound->calloc(sizeof(int32_t) * 2);
- array->sizes[0] = rowNum;
- array->sizes[1] = colNum;
- array->dimensions = 2;
- CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL);
- array->arrayMemberSize = var->memBlockSize;
- array->data = (MYFLT*) csound->calloc(var->memBlockSize * totalResults);
- STRINGDAT* strings;
- if (asString) {
- strings = (STRINGDAT*) array->data;
- }
+ int cols = meta->getColumnCount();
+ int rows = result->rowsCount();
+ STRINGDAT* strings = arrayInit(csound, array, rows, cols);
int colIndex;
int index = 0;
while (result->next()) {
colIndex = 0;
- while (colIndex < colNum) {
+ while (colIndex < cols) {
if (asString) {
- char* item = (char*) result->getString(colIndex + 1).c_str();
- strings[index].size = strlen(item) + 1;
- strings[index].data = csound->strdup(item);
+ insertArrayStringItem(csound, strings, index, (char*) result->getString(colIndex + 1).c_str());
} else {
array->data[index] = (MYFLT) result->getDouble(colIndex + 1);
}
diff --git a/src/opcodes.cpp b/src/opcodes.cpp
index 34bba02..e82ce33 100644
--- a/src/opcodes.cpp
+++ b/src/opcodes.cpp
@@ -95,7 +95,7 @@ public:
try {
switch (queryData->queryType) {
case SCALARSTRING: {
- std::string resultString = connection->ScalarString(queryData->sql, queryData->row, queryData->col);
+ std::string resultString = connection->ScalarString(queryData->sql, csound, queryData->row, queryData->col);
if (charData != NULL) {
csound->free(charData);
}
@@ -480,6 +480,7 @@ struct dbscalarstr : csnd::Plugin<1, 4> {
static constexpr char const *otypes = "S";
static constexpr char const *itypes = "iSoo";
ConnectionData* connection;
+ char* resultString;
int init() {
if (!(connection = getConnection(csound, inargs[0]))) {
@@ -489,9 +490,12 @@ struct dbscalarstr : csnd::Plugin<1, 4> {
STRINGDAT &result = outargs.str_data(0);
LOCK(connection);
try {
- std::string resultString = connection->ScalarString(sql.data, inargs[2], inargs[3]);
- result.size = resultString.length() + 1;
- result.data = csound->strdup((char*)resultString.c_str());
+ if (resultString != NULL) {
+ csound->free(resultString);
+ }
+ resultString = connection->ScalarString(sql.data, csound, inargs[2], inargs[3]);
+ result.size = strlen(resultString) + 1;
+ result.data = resultString;
} catch (const std::exception &e) {
UNLOCK(connection);
return csound->init_error(e.what());
@@ -642,9 +646,9 @@ struct dbscalarstr_kb : csnd::Plugin<1, 4> {
STRINGDAT &result = outargs.str_data(0);
LOCK(connection);
try {
- std::string resultString = connection->ScalarString(sql.data, inargs[2], inargs[3]);
- result.size = resultString.length() + 1;
- result.data = csound->strdup((char*) resultString.c_str());
+ char* resultString = connection->ScalarString(sql.data, csound, inargs[2], inargs[3]);
+ result.size = strlen(resultString) + 1;
+ result.data = resultString;
} catch (const std::exception &e) {
UNLOCK(connection);
return csound->perf_error(e.what(), this);
diff --git a/src/postgresql.cpp b/src/postgresql.cpp
index 6b54e29..7e194c6 100644
--- a/src/postgresql.cpp
+++ b/src/postgresql.cpp
@@ -20,13 +20,13 @@
*/
#include <plugin.h>
+#include "tools.h"
#include <iostream>
#include "libpq-fe.h"
#include "connection.h"
#include "postgresql.h"
-
void PostgresConnection::Init(csnd::Csound* csound, LoginData* login) {
char connectionString[256];
@@ -62,9 +62,11 @@ MYFLT PostgresConnection::Scalar(char* sql, int row, int col) {
int cols = PQnfields(result);
if (row > rows - 1) {
+ PQclear(result);
throw std::runtime_error("row number out of range");
}
if (col > cols - 1) {
+ PQclear(result);
throw std::runtime_error("column number out of range");
}
@@ -73,52 +75,40 @@ MYFLT PostgresConnection::Scalar(char* sql, int row, int col) {
return value;
}
-char* PostgresConnection::ScalarString(char* sql, int row, int col) {
+char* PostgresConnection::ScalarString(char* sql, csnd::Csound* csound, int row, int col) {
PGresult* result = Query(sql);
int rows = PQntuples(result);
int cols = PQnfields(result);
if (row > rows - 1) {
+ PQclear(result);
throw std::runtime_error("row number out of range");
}
if (col > cols -1) {
+ PQclear(result);
throw std::runtime_error("column number out of range");
}
- char* value = (char*) PQgetvalue(result, row, col);
+ char* value = csound->strdup(PQgetvalue(result, row, col));
PQclear(result);
return value;
-
}
void PostgresConnection::ToArray(PGresult* result, csnd::Csound* csound, ARRAYDAT* array, bool asString) {
int rows = PQntuples(result);
int cols = PQnfields(result);
- int totalResults = rows * cols;
- array->sizes = (int32_t*) csound->calloc(sizeof(int32_t) * 2);
- array->sizes[0] = rows;
- array->sizes[1] = cols;
- array->dimensions = 2;
- CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL);
- array->arrayMemberSize = var->memBlockSize;
- array->data = (MYFLT*) csound->calloc(var->memBlockSize * totalResults);
- STRINGDAT* strings;
- if (asString) {
- strings = (STRINGDAT*) array->data;
- }
+ STRINGDAT* strings = arrayInit(csound, array, rows, cols);
int index = 0;
- for (int rowNum = 0; rowNum < rows; ++rowNum) {
- for (int colNum = 0; colNum < cols; ++colNum) {
+ for (int rowIndex = 0; rowIndex < rows; ++rowIndex) {
+ for (int colIndex = 0; colIndex < cols; ++colIndex) {
if (asString) {
- char* item = (char*) PQgetvalue(result, rowNum, colNum);
- strings[index].size = strlen(item) + 1;
- strings[index].data = csound->strdup(item);
+ insertArrayStringItem(csound, strings, index, (char*) PQgetvalue(result, rowIndex, colIndex));
} else {
- array->data[index] = (MYFLT) atof(PQgetvalue(result, rowNum, colNum));
+ array->data[index] = (MYFLT) atof(PQgetvalue(result, rowIndex, colIndex));
}
index++;
}
diff --git a/src/sqlite3.cpp b/src/sqlite3.cpp
index 9724781..cbd4af1 100644
--- a/src/sqlite3.cpp
+++ b/src/sqlite3.cpp
@@ -20,6 +20,7 @@
*/
#include <plugin.h>
+#include "tools.h"
#include <iostream>
#include <sqlite3.h>
#include "connection.h"
@@ -56,14 +57,16 @@ MYFLT SqliteConnection::Scalar(char* sql, int row, int col) {
sqlite3_stmt *stmt = Query(sql);
int colCount = sqlite3_column_count(stmt);
int rc = sqlite3_step(stmt);
+
+ if (col > colCount -1) {
+ rc = sqlite3_finalize(stmt);
+ throw std::runtime_error("column number out of range");
+ }
+
+ rc = sqlite3_step(stmt);
int rowIndex = 0;
while (rc != SQLITE_DONE && rc != SQLITE_OK) {
if (rowIndex == row) {
-
- if (col > colCount -1) {
- rc = sqlite3_finalize(stmt);
- throw std::runtime_error("column number out of range");
- }
MYFLT result = (MYFLT) sqlite3_column_double(stmt, col);
rc = sqlite3_finalize(stmt);
return result;
@@ -75,7 +78,7 @@ MYFLT SqliteConnection::Scalar(char* sql, int row, int col) {
throw std::runtime_error("no result");
}
-char* SqliteConnection::ScalarString(char* sql, int row, int col) {
+char* SqliteConnection::ScalarString(char* sql, csnd::Csound* csound, int row, int col) {
sqlite3_stmt *stmt = Query(sql);
int colCount = sqlite3_column_count(stmt);
int rc = sqlite3_step(stmt);
@@ -87,7 +90,7 @@ char* SqliteConnection::ScalarString(char* sql, int row, int col) {
rc = sqlite3_finalize(stmt);
throw std::runtime_error("column number out of range");
}
- char* result = (char*) sqlite3_column_text(stmt, col);
+ char* result = csound->strdup((char*) sqlite3_column_text(stmt, col));
rc = sqlite3_finalize(stmt);
return result;
}
@@ -110,21 +113,11 @@ int SqliteConnection::RowCount(sqlite3_stmt* stmt) {
return rowCount;
}
+
void SqliteConnection::ToArray(sqlite3_stmt* stmt, csnd::Csound* csound, ARRAYDAT* array, bool asString) {
- int colNum = sqlite3_column_count(stmt);
- int rowNum = RowCount(stmt);
- int totalResults = colNum * rowNum;
- array->sizes = (int32_t*) csound->calloc(sizeof(int32_t) * 2);
- array->sizes[0] = rowNum;
- array->sizes[1] = colNum;
- array->dimensions = 2;
- CS_VARIABLE *var = array->arrayType->createVariable(csound, NULL);
- array->arrayMemberSize = var->memBlockSize;
- array->data = (MYFLT*) csound->calloc(var->memBlockSize * totalResults);
- STRINGDAT* strings;
- if (asString) {
- strings = (STRINGDAT*) array->data;
- }
+ int cols = sqlite3_column_count(stmt);
+ int rows = RowCount(stmt);
+ STRINGDAT* strings = arrayInit(csound, array, rows, cols);
int colIndex;
int rowIndex;
@@ -132,11 +125,9 @@ void SqliteConnection::ToArray(sqlite3_stmt* stmt, csnd::Csound* csound, ARRAYDA
int rc = sqlite3_step(stmt);
while (rc != SQLITE_DONE && rc != SQLITE_OK) {
colIndex = 0;
- while (colIndex < colNum) {
+ while (colIndex < cols) {
if (asString) {
- char* item = (char*) sqlite3_column_text(stmt, colIndex);
- strings[index].size = strlen(item) + 1;
- strings[index].data = csound->strdup(item);
+ insertArrayStringItem(csound, strings, index, (char*) sqlite3_column_text(stmt, colIndex));
} else {
array->data[index] = (MYFLT) sqlite3_column_double(stmt, colIndex);
}
diff --git a/src/tools.cpp b/src/tools.cpp
new file mode 100644
index 0000000..ec8863b
--- /dev/null
+++ b/src/tools.cpp
@@ -0,0 +1,54 @@
+/*
+ tools.cpp
+ Copyright (C) 2022 Richard Knight
+
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+
+#include <plugin.h>
+
+STRINGDAT* arrayInit(csnd::Csound* csound, ARRAYDAT* array, int rows, int cols) {
+ int totalResults = rows * cols;
+ size_t totalAllocated;
+
+ if (array->data == NULL) {
+ array->sizes = (int32_t*) csound->calloc(sizeof(int32_t) * 2);
+ array->sizes[0] = rows;
+ array->sizes[1] = cols;
+ array->dimensions = 2;
+ CS_VARIABLE *var = array->arrayType->createVariable(csound->get_csound(), NULL);
+ array->arrayMemberSize = var->memBlockSize;
+ totalAllocated = array->arrayMemberSize * totalResults;
+ array->data = (MYFLT*) csound->calloc(totalAllocated);
+ } else if ((totalAllocated = array->arrayMemberSize * totalResults) > array->allocated) {
+ array->data = (MYFLT*) csound->realloc(array->data, totalAllocated);
+ memset((char*)(array->data)+array->allocated, '\0', totalAllocated - array->allocated);
+ array->allocated = totalAllocated;
+ }
+
+ // convenience return to be used if it is a string array
+ return (STRINGDAT*) array->data;
+}
+
+
+void insertArrayStringItem(csnd::Csound* csound, STRINGDAT* strings, int index, char* item) {
+ strings[index].size = strlen(item) + 1;
+ if (strings[index].data != NULL) {
+ csound->free(strings[index].data);
+ }
+ strings[index].data = csound->strdup(item);
+} \ No newline at end of file