Bugfix: memory corruption possible after reallocs. Using a static buffer instead. Will need to check for overflows on static buffer.

Sat, 20 Dec 2008 11:15:15 +0000

author
nrich@ii.net
date
Sat, 20 Dec 2008 11:15:15 +0000
changeset 23
a4825c3e65e9
parent 22
fd78e9cdc6e9
child 24
abb9499bef51

Bugfix: memory corruption possible after reallocs. Using a static buffer instead. Will need to check for overflows on static buffer.

dbd/db2/connection.c file | annotate | diff | comparison | revisions
dbd/db2/statement.c file | annotate | diff | comparison | revisions
dbd/mysql/connection.c file | annotate | diff | comparison | revisions
dbd/mysql/statement.c file | annotate | diff | comparison | revisions
--- a/dbd/db2/connection.c	Sat Dec 20 02:37:22 2008 +0000
+++ b/dbd/db2/connection.c	Sat Dec 20 11:15:15 2008 +0000
@@ -223,6 +223,8 @@
  * __gc
  */
 static int connection_gc(lua_State *L) {
+    printf("Freeing connection\n");
+
     /* always close the connection */
     connection_close(L);
 
--- a/dbd/db2/statement.c	Sat Dec 20 02:37:22 2008 +0000
+++ b/dbd/db2/statement.c	Sat Dec 20 11:15:15 2008 +0000
@@ -46,10 +46,9 @@
  */
 static int statement_close(lua_State *L) {
     statement_t *statement = (statement_t *)luaL_checkudata(L, 1, DBD_DB2_STATEMENT);
-    SQLRETURN rc = SQL_SUCCESS;
 
     if (statement->stmt) {
-	rc = SQLFreeHandle(SQL_HANDLE_STMT, statement->stmt);
+        SQLFreeStmt(statement->stmt, SQL_CLOSE);
 
 	if (statement->resultset) 
 	    free(statement->resultset);
@@ -81,7 +80,8 @@
     int errflag = 0;
     const char *errstr = NULL;
     SQLRETURN rc = SQL_SUCCESS;
-    unsigned char *buffer = NULL;
+    unsigned char b[1024];
+    unsigned char *buffer = &b[0];
     int offset = 0;
     resultset_t *resultset = NULL; 
     bindparams_t *bind; /* variable to read the results */
@@ -134,7 +134,6 @@
 	    errflag = rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO;
 	    break;
 	case LUA_TNUMBER:
-	    buffer = realloc(buffer, offset + sizeof(double));
 	    num = (double *)buffer + offset;
 	    *num = lua_tonumber(L, p);
 	    offset += sizeof(double);
@@ -147,7 +146,6 @@
 	    errflag = rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO;
 	    break;
 	case LUA_TBOOLEAN:
-	    buffer = realloc(buffer, offset + sizeof(int));
 	    boolean = (int *)buffer + offset;
 	    *boolean = lua_toboolean(L, p);
 	    offset += sizeof(int);
@@ -168,7 +166,6 @@
     }
 
     if (errflag) {
-	realloc(buffer, 0);
 	lua_pushboolean(L, 0);
 
 	if (errstr) {
@@ -252,11 +249,6 @@
 	statement->bind = bind;
     }
 
-    /*
-     * free the buffer with a resize to 0
-     */
-    realloc(buffer, 0);
-
     lua_pushboolean(L, 1);
     return 1;
 }
@@ -268,6 +260,11 @@
     int i;
     int d;
 
+    SQLCHAR message[SQL_MAX_MESSAGE_LENGTH + 1];
+    SQLCHAR sqlstate[SQL_SQLSTATE_SIZE + 1];
+    SQLINTEGER sqlcode;
+    SQLSMALLINT length;
+
     SQLRETURN rc = SQL_SUCCESS;
  
     if (!statement->resultset || !statement->bind) {
@@ -278,15 +275,22 @@
     /* fetch each row, and display */
     rc = SQLFetch(statement->stmt);
     if (rc == SQL_NO_DATA_FOUND) {
+        SQLFreeStmt(statement->stmt, SQL_RESET_PARAMS);
 	lua_pushnil(L);
 	return 1;
     }
 
+    if (rc != SQL_SUCCESS) {
+        SQLGetDiagRec(SQL_HANDLE_STMT, statement->stmt, 1, sqlstate, &sqlcode, message, SQL_MAX_MESSAGE_LENGTH + 1, &length);
+
+        luaL_error(L, DBI_ERR_FETCH_FAILED, message);
+    }
+
     d = 1; 
     lua_newtable(L);
     for (i = 0; i < statement->num_result_columns; i++) {
 	lua_push_type_t lua_push = db2_to_lua_push(statement->resultset[i].type, statement->bind[i].len);
-	const char *name = strlower((char *)statement->resultset[i].name);
+	const char *name = strlower(statement->resultset[i].name);
 	double val;
 	char *value = (char *)statement->bind[i].buffer;
 
--- a/dbd/mysql/connection.c	Sat Dec 20 02:37:22 2008 +0000
+++ b/dbd/mysql/connection.c	Sat Dec 20 11:15:15 2008 +0000
@@ -157,6 +157,7 @@
     quoted_len = mysql_real_escape_string(conn->mysql, to, from, len);
 
     lua_pushlstring(L, to, quoted_len);
+    free(to);
 
     return 1;
 }
--- a/dbd/mysql/statement.c	Sat Dec 20 02:37:22 2008 +0000
+++ b/dbd/mysql/statement.c	Sat Dec 20 11:15:15 2008 +0000
@@ -70,7 +70,8 @@
     int num_bind_params = n - 1;
     int expected_params;
 
-    unsigned char *buffer = NULL;
+    unsigned char b[1024];
+    unsigned char *buffer = &b[0];
     int offset = 0;
     
     MYSQL_BIND *bind = NULL;
@@ -100,6 +101,11 @@
     }
 
     bind = malloc(sizeof(MYSQL_BIND) * num_bind_params);
+    
+    if (bind == NULL) {
+        luaL_error(L, "Could not alloc bind params\n");
+    }
+
     memset(bind, 0, sizeof(MYSQL_BIND) * num_bind_params);
 
     for (p = 2; p <= n; p++) {
@@ -119,7 +125,6 @@
 		break;
 
 	    case LUA_TBOOLEAN:
-		buffer = realloc(buffer, offset + sizeof(int));
 		boolean = (int *)buffer + offset;
 		offset += sizeof(int);
 		*boolean = lua_toboolean(L, p);
@@ -135,7 +140,6 @@
 		 * num needs to be it's own 
 		 * memory here
                  */
-		buffer = realloc(buffer, offset + sizeof(double));
 		num = (double *)buffer + offset;
 		offset += sizeof(double);
 		*num = lua_tonumber(L, p);
@@ -147,7 +151,6 @@
 		break;
 
 	    case LUA_TSTRING:
-		buffer = realloc(buffer, offset + sizeof(size_t));
 		str_len = (size_t *)buffer + offset;
 		offset += sizeof(size_t);
 		str = lua_tolstring(L, p, str_len);
@@ -183,13 +186,9 @@
     }
 
 cleanup:
-    /*
-     * free the buffer with a resize to 0
-     */
-    realloc(buffer, 0);
-
-    if (bind) 
+    if (bind) { 
 	free(bind);
+    }
 
     if (error_message) {
 	lua_pushboolean(L, 0);
@@ -223,6 +222,7 @@
 	return 1;
     }
 
+
     column_count = mysql_num_fields(statement->metadata);
 
     if (column_count > 0) {

mercurial