[Asterisk-code-review] res config odbc.c: Fix buffer size limitation creating inval... (asterisk[master])

Anonymous Coward asteriskteam at digium.com
Mon Sep 19 15:21:31 CDT 2016


Anonymous Coward #1000019 has submitted this change and it was merged.

Change subject: res_config_odbc.c: Fix buffer size limitation creating invalid SQL.
......................................................................


res_config_odbc.c: Fix buffer size limitation creating invalid SQL.

Creating ODBC SQL queries resulted in queries too large to fit into the
supplied buffer.  The resulting truncated buffer contained an invalid SQL
query.

* Made SQL query generation code use a thread storage buffer that can
increase in size as needed.

* Fixed bad multi-line warning messages.

ASTERISK-26263 #close
Reported by: Jeppe Ryskov Larsen

Change-Id: I23f3cdd43c2dac80bed3ded4dd77d18cb17f21ae
---
M res/res_config_odbc.c
1 file changed, 94 insertions(+), 80 deletions(-)

Approvals:
  Mark Michelson: Looks good to me, approved
  Anonymous Coward #1000019: Verified
  Joshua Colp: Looks good to me, but someone else must approve



diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c
index 26aa17b..161dc53 100644
--- a/res/res_config_odbc.c
+++ b/res/res_config_odbc.c
@@ -47,6 +47,9 @@
 #include "asterisk/utils.h"
 #include "asterisk/stringfields.h"
 
+/*! Initial SQL query buffer size to allocate. */
+#define SQL_BUF_SIZE	1024
+
 AST_THREADSTORAGE(sql_buf);
 AST_THREADSTORAGE(rowdata_buf);
 
@@ -114,7 +117,7 @@
 
 	res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql);
+		ast_log(LOG_WARNING, "SQL Prepare failed! [%s]\n", cps->sql);
 		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 		return NULL;
 	}
@@ -161,13 +164,13 @@
  *
  * \retval var on success
  * \retval NULL on failure
-*/
+ */
 static struct ast_variable *realtime_odbc(const char *database, const char *table, const struct ast_variable *fields)
 {
 	struct odbc_obj *obj;
 	SQLHSTMT stmt;
-	char sql[1024];
 	char coltitle[256];
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
 	char *op;
 	const struct ast_variable *field = fields;
@@ -183,28 +186,29 @@
 	SQLSMALLINT decimaldigits;
 	SQLSMALLINT nullable;
 	SQLLEN indicator;
-	struct custom_prepare_struct cps = { .sql = sql, .fields = fields, };
+	struct custom_prepare_struct cps = { .fields = fields, };
 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
 
-	if (!table || !field) {
+	if (!table || !field || !sql || !rowdata) {
 		return NULL;
 	}
 
 	obj = ast_odbc_request_obj2(database, connected_flag);
-
 	if (!obj) {
 		ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
 		return NULL;
 	}
 
 	op = !strchr(field->name, ' ') ? " =" : "";
-	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
+	ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
 		strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
 	while ((field = field->next)) {
 		op = !strchr(field->name, ' ') ? " =" : "";
-		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", field->name, op,
+		ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op,
 			strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
 	}
+
+	cps.sql = ast_str_buffer(sql);
 
 	if (ast_string_field_init(&cps, 256)) {
 		ast_odbc_release_obj(obj);
@@ -220,7 +224,7 @@
 
 	res = SQLNumResultCols(stmt, &colcount);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql));
 		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 		ast_odbc_release_obj(obj);
 		return NULL;
@@ -233,7 +237,7 @@
 		return NULL;
 	}
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
 		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 		ast_odbc_release_obj(obj);
 		return NULL;
@@ -244,7 +248,7 @@
 		res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
 					&datatype, &colsize, &decimaldigits, &nullable);
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-			ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
+			ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
 			if (var)
 				ast_variables_destroy(var);
 			ast_odbc_release_obj(obj);
@@ -273,7 +277,7 @@
 		}
 
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-			ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+			ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql));
 			if (var)
 				ast_variables_destroy(var);
 			ast_odbc_release_obj(obj);
@@ -317,13 +321,13 @@
  *
  * \retval var on success
  * \retval NULL on failure
-*/
+ */
 static struct ast_config *realtime_multi_odbc(const char *database, const char *table, const struct ast_variable *fields)
 {
 	struct odbc_obj *obj;
 	SQLHSTMT stmt;
-	char sql[1024];
 	char coltitle[256];
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
 	const char *initfield;
 	char *op;
@@ -343,9 +347,9 @@
 	SQLSMALLINT decimaldigits;
 	SQLSMALLINT nullable;
 	SQLLEN indicator;
-	struct custom_prepare_struct cps = { .sql = sql, .fields = fields, };
+	struct custom_prepare_struct cps = { .fields = fields, };
 
-	if (!table || !field) {
+	if (!table || !field || !sql || !rowdata) {
 		return NULL;
 	}
 
@@ -360,15 +364,16 @@
 	}
 
 	op = !strchr(field->name, ' ') ? " =" : "";
-	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
+	ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s ?%s", table, field->name, op,
 		strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
 	while ((field = field->next)) {
 		op = !strchr(field->name, ' ') ? " =" : "";
-		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", field->name, op,
+		ast_str_append(&sql, 0, " AND %s%s ?%s", field->name, op,
 			strcasestr(field->name, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\\\'" : "");
 	}
+	ast_str_append(&sql, 0, " ORDER BY %s", initfield);
 
-	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
+	cps.sql = ast_str_buffer(sql);
 
 	if (ast_string_field_init(&cps, 256)) {
 		ast_odbc_release_obj(obj);
@@ -384,7 +389,7 @@
 
 	res = SQLNumResultCols(stmt, &colcount);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL Column Count error! [%s]\n", ast_str_buffer(sql));
 		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 		ast_odbc_release_obj(obj);
 		return NULL;
@@ -401,7 +406,7 @@
 	while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
 		var = NULL;
 		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-			ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
+			ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql));
 			continue;
 		}
 		cat = ast_category_new("","",99999);
@@ -415,7 +420,7 @@
 			res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
 						&datatype, &colsize, &decimaldigits, &nullable);
 			if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-				ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
+				ast_log(LOG_WARNING, "SQL Describe Column error! [%s]\n", ast_str_buffer(sql));
 				ast_category_destroy(cat);
 				goto next_sql_fetch;
 			}
@@ -440,7 +445,7 @@
 			}
 
 			if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-				ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
+				ast_log(LOG_WARNING, "SQL Get Data error! [%s]\n", ast_str_buffer(sql));
 				ast_category_destroy(cat);
 				goto next_sql_fetch;
 			}
@@ -482,21 +487,21 @@
  *
  * \retval number of rows affected
  * \retval -1 on failure
-*/
+ */
 static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
 {
 	struct odbc_obj *obj;
 	SQLHSTMT stmt;
-	char sql[256];
 	SQLLEN rowcount=0;
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	const struct ast_variable *field = fields;
 	int res, count = 0, paramcount = 0;
-	struct custom_prepare_struct cps = { .sql = sql, .extra = lookup, .fields = fields, };
+	struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, };
 	struct odbc_cache_tables *tableptr;
 	struct odbc_cache_columns *column = NULL;
 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
 
-	if (!table || !field || !keyfield) {
+	if (!table || !field || !keyfield || !sql) {
 		return -1;
 	}
 
@@ -510,19 +515,19 @@
 		ast_log(LOG_WARNING, "Key field '%s' does not exist in table '%s@%s'.  Update will fail\n", keyfield, table, database);
 	}
 
-	snprintf(sql, sizeof(sql), "UPDATE %s SET ", table);
+	ast_str_set(&sql, 0, "UPDATE %s SET ", table);
 	while (field) {
 		if ((tableptr && (column = ast_odbc_find_column(tableptr, field->name))) || count >= 64) {
 			if (paramcount++) {
-				snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", ");
+				ast_str_append(&sql, 0, ", ");
 			}
 			/* NULL test for non-text columns */
 			if (count < 64 && ast_strlen_zero(field->value) && column->nullable && !is_text(column)) {
-				snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=NULL", field->name);
+				ast_str_append(&sql, 0, "%s=NULL", field->name);
 				cps.skip |= (1LL << count);
 			} else {
 				/* Value is not an empty string, or column is of text type, or we couldn't fit any more into cps.skip (count >= 64 ?!). */
-				snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", field->name);
+				ast_str_append(&sql, 0, "%s=?", field->name);
 			}
 		} else { /* the column does not exist in the table */
 			cps.skip |= (1LL << count);
@@ -530,8 +535,10 @@
 		++count;
 		field = field->next;
 	}
-	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
+	ast_str_append(&sql, 0, " WHERE %s=?", keyfield);
 	ast_odbc_release_table(tableptr);
+
+	cps.sql = ast_str_buffer(sql);
 
 	if (ast_string_field_init(&cps, 256)) {
 		ast_odbc_release_obj(obj);
@@ -550,7 +557,7 @@
 	ast_odbc_release_obj(obj);
 
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
 		return -1;
 	}
 
@@ -573,17 +580,15 @@
 	int res, x = 1, first = 1;
 	struct update2_prepare_struct *ups = data;
 	const struct ast_variable *field;
-	struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	SQLHSTMT stmt;
-	struct odbc_cache_tables *tableptr = ast_odbc_find_table(ups->database, ups->table);
+	struct odbc_cache_tables *tableptr;
 
 	if (!sql) {
-		if (tableptr) {
-			ast_odbc_release_table(tableptr);
-		}
 		return NULL;
 	}
 
+	tableptr = ast_odbc_find_table(ups->database, ups->table);
 	if (!tableptr) {
 		ast_log(LOG_ERROR, "Could not retrieve metadata for table '%s@%s'.  Update will fail!\n", ups->table, ups->database);
 		return NULL;
@@ -628,7 +633,7 @@
 
 	res = SQLPrepare(stmt, (unsigned char *)ast_str_buffer(sql), SQL_NTS);
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", ast_str_buffer(sql));
+		ast_log(LOG_WARNING, "SQL Prepare failed! [%s]\n", ast_str_buffer(sql));
 		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 		return NULL;
 	}
@@ -674,8 +679,9 @@
 
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 		/* Since only a single thread can access this memory, we can retrieve what would otherwise be lost. */
-		sql = ast_str_thread_get(&sql_buf, 16);
-		ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n", ast_str_buffer(sql));
+		sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
+		ast_assert(sql != NULL);
+		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
 		return -1;
 	}
 
@@ -698,36 +704,47 @@
  *
  * \retval number of rows affected
  * \retval -1 on failure
-*/
+ */
 static int store_odbc(const char *database, const char *table, const struct ast_variable *fields)
 {
 	struct odbc_obj *obj;
 	SQLHSTMT stmt;
-	char sql[256];
-	char keys[256];
-	char vals[256];
 	SQLLEN rowcount=0;
 	const struct ast_variable *field = fields;
+	struct ast_str *keys;
+	struct ast_str *vals;
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	int res;
-	struct custom_prepare_struct cps = { .sql = sql, .extra = NULL, .fields = fields, };
+	struct custom_prepare_struct cps = { .fields = fields, };
 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
 
-	if (!table || !field) {
+	keys = ast_str_create(SQL_BUF_SIZE / 2);
+	vals = ast_str_create(SQL_BUF_SIZE / 4);
+	if (!table || !field || !keys || !vals || !sql) {
+		ast_free(vals);
+		ast_free(keys);
 		return -1;
 	}
 
 	obj = ast_odbc_request_obj2(database, connected_flag);
 	if (!obj) {
+		ast_free(vals);
+		ast_free(keys);
 		return -1;
 	}
 
-	snprintf(keys, sizeof(keys), "%s", field->name);
-	ast_copy_string(vals, "?", sizeof(vals));
+	ast_str_set(&keys, 0, "%s", field->name);
+	ast_str_set(&vals, 0, "?");
 	while ((field = field->next)) {
-		snprintf(keys + strlen(keys), sizeof(keys) - strlen(keys), ", %s", field->name);
-		snprintf(vals + strlen(vals), sizeof(vals) - strlen(vals), ", ?");
+		ast_str_append(&keys, 0, ", %s", field->name);
+		ast_str_append(&vals, 0, ", ?");
 	}
-	snprintf(sql, sizeof(sql), "INSERT INTO %s (%s) VALUES (%s)", table, keys, vals);
+	ast_str_set(&sql, 0, "INSERT INTO %s (%s) VALUES (%s)",
+		table, ast_str_buffer(keys), ast_str_buffer(vals));
+
+	ast_free(vals);
+	ast_free(keys);
+	cps.sql = ast_str_buffer(sql);
 
 	if (ast_string_field_init(&cps, 256)) {
 		ast_odbc_release_obj(obj);
@@ -746,7 +763,7 @@
 	ast_odbc_release_obj(obj);
 
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
 		return -1;
 	}
 
@@ -770,19 +787,19 @@
  *
  * \retval number of rows affected
  * \retval -1 on failure
-*/
+ */
 static int destroy_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *fields)
 {
 	struct odbc_obj *obj;
 	SQLHSTMT stmt;
-	char sql[256];
 	SQLLEN rowcount=0;
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	const struct ast_variable *field;
 	int res;
-	struct custom_prepare_struct cps = { .sql = sql, .extra = lookup, .fields = fields, };
+	struct custom_prepare_struct cps = { .extra = lookup, .fields = fields, };
 	struct ast_flags connected_flag = { RES_ODBC_CONNECTED };
 
-	if (!table) {
+	if (!table || !sql) {
 		return -1;
 	}
 
@@ -791,12 +808,13 @@
 		return -1;
 	}
 
-	snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE ", table);
-
+	ast_str_set(&sql, 0, "DELETE FROM %s WHERE ", table);
 	for (field = fields; field; field = field->next) {
-		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=? AND ", field->name);
+		ast_str_append(&sql, 0, "%s=? AND ", field->name);
 	}
-	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), "%s=?", keyfield);
+	ast_str_append(&sql, 0, "%s=?", keyfield);
+
+	cps.sql = ast_str_buffer(sql);
 
 	if (ast_string_field_init(&cps, 256)) {
 		ast_odbc_release_obj(obj);
@@ -815,7 +833,7 @@
 	ast_odbc_release_obj(obj);
 
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL Row Count error! [%s]\n", ast_str_buffer(sql));
 		return -1;
 	}
 
@@ -893,9 +911,7 @@
 	struct ast_category *cur_cat;
 	int res = 0;
 	struct odbc_obj *obj;
-	char sqlbuf[1024] = "";
-	char *sql = sqlbuf;
-	size_t sqlleft = sizeof(sqlbuf);
+	struct ast_str *sql = ast_str_thread_get(&sql_buf, SQL_BUF_SIZE);
 	unsigned int last_cat_metric = 0;
 	SQLSMALLINT rowcount = 0;
 	SQLHSTMT stmt;
@@ -906,21 +922,21 @@
 
 	memset(&q, 0, sizeof(q));
 
-	if (!file || !strcmp (file, "res_config_odbc.conf"))
+	if (!file || !strcmp (file, "res_config_odbc.conf") || !sql) {
 		return NULL;		/* cant configure myself with myself ! */
+	}
 
 	obj = ast_odbc_request_obj2(database, connected_flag);
 	if (!obj)
 		return NULL;
 
-	q.sql = sqlbuf;
-
-	ast_build_string(&sql, &sqlleft, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'", table, file);
+	ast_str_set(&sql, 0, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'",
+		table, file);
+	q.sql = ast_str_buffer(sql);
 
 	stmt = ast_odbc_prepare_and_execute(obj, length_determination_odbc_prepare, &q);
-
 	if (!stmt) {
-		ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL select error! [%s]\n", ast_str_buffer(sql));
 		ast_odbc_release_obj(obj);
 		return NULL;
 	}
@@ -928,7 +944,7 @@
 	res = SQLNumResultCols(stmt, &rowcount);
 
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL NumResultCols error! [%s]\n", ast_str_buffer(sql));
 		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 		ast_odbc_release_obj(obj);
 		return NULL;
@@ -950,12 +966,11 @@
 
 	/* Reset stuff to a fresh state for the actual query which will retrieve all configuration */
 	SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-	sql = sqlbuf;
-	sqlleft = sizeof(sqlbuf);
 
-	ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
-	ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file);
-	ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
+	ast_str_set(&sql, 0, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
+	ast_str_append(&sql, 0, "WHERE filename='%s' AND commented=0 ", file);
+	ast_str_append(&sql, 0, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
+	q.sql = ast_str_buffer(sql);
 
 	q.var_val_size += 1;
 	q.var_val = ast_malloc(q.var_val_size);
@@ -966,9 +981,8 @@
 	}
 
 	stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q);
-
 	if (!stmt) {
-		ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL select error! [%s]\n", ast_str_buffer(sql));
 		ast_odbc_release_obj(obj);
 		ast_free(q.var_val);
 		return NULL;
@@ -977,7 +991,7 @@
 	res = SQLNumResultCols(stmt, &rowcount);
 
 	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
-		ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
+		ast_log(LOG_WARNING, "SQL NumResultCols error! [%s]\n", ast_str_buffer(sql));
 		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 		ast_odbc_release_obj(obj);
 		ast_free(q.var_val);

-- 
To view, visit https://gerrit.asterisk.org/3926
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I23f3cdd43c2dac80bed3ded4dd77d18cb17f21ae
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>



More information about the asterisk-code-review mailing list