Browse code

db_postgres: Fix heap use after free error in db_postgres module

The result structure for a query holds a pointer returned by
PQfname. When sql_do_query executes the query it gets this
database result structure returned but the PQfname pointer
has already been free'd by a call to db_postgres_free_query
from within db_postgres_store_result.

sql_do_query then tries to copy the free'd string into another
result structure resulting in a heap use after free.

The fix here copies the PQfname result.

Fix by Chris Double

Carsten Bock authored on 28/08/2015 10:08:10
Showing 2 changed files
... ...
@@ -71,10 +71,6 @@ struct pg_con* db_postgres_new_connection(struct db_id* id)
71 71
 	memset(ptr, 0, sizeof(struct pg_con));
72 72
 	ptr->ref = 1;
73 73
 
74
-	memset(keywords, 0, (sizeof(char*) * 10));
75
-	memset(values, 0, (sizeof(char*) * 10));
76
-	memset(to, 0, (sizeof(char) * 16));
77
-
78 74
 	if (id->port) {
79 75
 		ports = int2str(id->port, 0);
80 76
 		keywords[i] = "port";
... ...
@@ -126,8 +126,14 @@ int db_postgres_get_columns(const db1_con_t* _h, db1_res_t* _r)
126 126
 				RES_NAMES(_r)[col]);
127 127
 
128 128
 		/* The pointer that is here returned is part of the result structure. */
129
-		RES_NAMES(_r)[col]->s = PQfname(CON_RESULT(_h), col);
130
-		RES_NAMES(_r)[col]->len = strlen(PQfname(CON_RESULT(_h), col));
129
+		RES_NAMES(_r)[col]->s = pkg_malloc(strlen(PQfname(CON_RESULT(_h), col))+1);
130
+		if (! RES_NAMES(_r)[col]->s) {
131
+			LM_ERR("no private memory left\n");
132
+			db_free_columns(_r);
133
+			return -4;
134
+		}
135
+		strcpy(RES_NAMES(_r)[col]->s, PQfname(CON_RESULT(_h), col));
136
+		RES_NAMES(_r)[col]->len = strlen(RES_NAMES(_r)[col]->s);
131 137
 
132 138
 		LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
133 139
 				RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);