[svn-commits] file: branch 1.8 r414693 - in /branches/1.8: funcs/ res/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Wed May 28 06:35:06 CDT 2014
Author: file
Date: Wed May 28 06:34:55 2014
New Revision: 414693
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=414693
Log:
res_config_odbc: Use dynamically sized buffers to store row data so values do not get truncated.
ASTERISK-23582 #close
ASTERISk-23582 #comment Reported by: Walter Doekes
Review: https://reviewboard.asterisk.org/r/3557/
Modified:
branches/1.8/funcs/func_odbc.c
branches/1.8/res/res_config_odbc.c
Modified: branches/1.8/funcs/func_odbc.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/funcs/func_odbc.c?view=diff&rev=414693&r1=414692&r2=414693
==============================================================================
--- branches/1.8/funcs/func_odbc.c (original)
+++ branches/1.8/funcs/func_odbc.c Wed May 28 06:34:55 2014
@@ -109,9 +109,9 @@
AST_RWLIST_ENTRY(acf_odbc_query) list;
char readhandle[5][30];
char writehandle[5][30];
- char sql_read[2048];
- char sql_write[2048];
- char sql_insert[2048];
+ char *sql_read;
+ char *sql_write;
+ char *sql_insert;
unsigned int flags;
int rowlimit;
struct ast_custom_function *acf;
@@ -855,6 +855,23 @@
return 0;
}
+static int free_acf_query(struct acf_odbc_query *query)
+{
+ if (query) {
+ if (query->acf) {
+ if (query->acf->name)
+ ast_free((char *)query->acf->name);
+ ast_string_field_free_memory(query->acf);
+ ast_free(query->acf);
+ }
+ ast_free(query->sql_read);
+ ast_free(query->sql_write);
+ ast_free(query->sql_insert);
+ ast_free(query);
+ }
+ return 0;
+}
+
static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_query **query)
{
const char *tmp;
@@ -899,35 +916,35 @@
}
if ((tmp = ast_variable_retrieve(cfg, catg, "readsql")))
- ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read));
+ (*query)->sql_read = ast_strdup(tmp);
else if ((tmp = ast_variable_retrieve(cfg, catg, "read"))) {
ast_log(LOG_WARNING, "Parameter 'read' is deprecated for category %s. Please use 'readsql' instead.\n", catg);
- ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read));
+ (*query)->sql_read = ast_strdup(tmp);
}
if (!ast_strlen_zero((*query)->sql_read) && ast_strlen_zero((*query)->readhandle[0])) {
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
ast_log(LOG_ERROR, "There is SQL, but no ODBC class to be used for reading: %s\n", catg);
return EINVAL;
}
if ((tmp = ast_variable_retrieve(cfg, catg, "writesql")))
- ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write));
+ (*query)->sql_write = ast_strdup(tmp);
else if ((tmp = ast_variable_retrieve(cfg, catg, "write"))) {
ast_log(LOG_WARNING, "Parameter 'write' is deprecated for category %s. Please use 'writesql' instead.\n", catg);
- ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write));
+ (*query)->sql_write = ast_strdup(tmp);
}
if (!ast_strlen_zero((*query)->sql_write) && ast_strlen_zero((*query)->writehandle[0])) {
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
ast_log(LOG_ERROR, "There is SQL, but no ODBC class to be used for writing: %s\n", catg);
return EINVAL;
}
if ((tmp = ast_variable_retrieve(cfg, catg, "insertsql"))) {
- ast_copy_string((*query)->sql_insert, tmp, sizeof((*query)->sql_insert));
+ (*query)->sql_insert = ast_strdup(tmp);
}
/* Allow escaping of embedded commas in fields to be turned off */
@@ -946,13 +963,12 @@
(*query)->acf = ast_calloc(1, sizeof(struct ast_custom_function));
if (! (*query)->acf) {
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
return ENOMEM;
}
if (ast_string_field_init((*query)->acf, 128)) {
- ast_free((*query)->acf);
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
return ENOMEM;
}
@@ -968,9 +984,7 @@
}
if (!((*query)->acf->name)) {
- ast_string_field_free_memory((*query)->acf);
- ast_free((*query)->acf);
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
return ENOMEM;
}
@@ -982,10 +996,7 @@
}
if (ast_strlen_zero((*query)->acf->syntax)) {
- ast_free((char *)(*query)->acf->name);
- ast_string_field_free_memory((*query)->acf);
- ast_free((*query)->acf);
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
return ENOMEM;
}
@@ -997,10 +1008,7 @@
}
if (ast_strlen_zero((*query)->acf->synopsis)) {
- ast_free((char *)(*query)->acf->name);
- ast_string_field_free_memory((*query)->acf);
- ast_free((*query)->acf);
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
return ENOMEM;
}
@@ -1042,19 +1050,14 @@
ast_strlen_zero((*query)->sql_insert) ? "" : (*query)->sql_insert,
ast_strlen_zero((*query)->sql_insert) ? "" : "\n");
} else {
- ast_string_field_free_memory((*query)->acf);
- ast_free((char *)(*query)->acf->name);
- ast_free((*query)->acf);
- ast_free(*query);
+ free_acf_query(*query);
+ *query = NULL;
ast_log(LOG_WARNING, "Section '%s' was found, but there was no SQL to execute. Ignoring.\n", catg);
return EINVAL;
}
if (ast_strlen_zero((*query)->acf->desc)) {
- ast_string_field_free_memory((*query)->acf);
- ast_free((char *)(*query)->acf->name);
- ast_free((*query)->acf);
- ast_free(*query);
+ free_acf_query(*query);
*query = NULL;
return ENOMEM;
}
@@ -1071,20 +1074,6 @@
(*query)->acf->write = acf_odbc_write;
}
- return 0;
-}
-
-static int free_acf_query(struct acf_odbc_query *query)
-{
- if (query) {
- if (query->acf) {
- if (query->acf->name)
- ast_free((char *)query->acf->name);
- ast_string_field_free_memory(query->acf);
- ast_free(query->acf);
- }
- ast_free(query);
- }
return 0;
}
Modified: branches/1.8/res/res_config_odbc.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/res/res_config_odbc.c?view=diff&rev=414693&r1=414692&r2=414693
==============================================================================
--- branches/1.8/res/res_config_odbc.c (original)
+++ branches/1.8/res/res_config_odbc.c Wed May 28 06:34:55 2014
@@ -48,6 +48,7 @@
#include "asterisk/stringfields.h"
AST_THREADSTORAGE(sql_buf);
+AST_THREADSTORAGE(rowdata_buf);
struct custom_prepare_struct {
const char *sql;
@@ -168,7 +169,7 @@
SQLHSTMT stmt;
char sql[1024];
char coltitle[256];
- char rowdata[2048];
+ struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
char *op;
const char *newparam;
char *stringp;
@@ -252,7 +253,6 @@
return NULL;
}
for (x = 0; x < colcount; x++) {
- rowdata[0] = '\0';
colsize = 0;
collen = sizeof(coltitle);
res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
@@ -265,14 +265,25 @@
return NULL;
}
+ ast_str_reset(rowdata);
indicator = 0;
- res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
- if (indicator == SQL_NULL_DATA)
- rowdata[0] = '\0';
- else if (ast_strlen_zero(rowdata)) {
+
+ res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
+ ast_str_update(rowdata);
+ if (indicator == SQL_NULL_DATA) {
+ ast_str_reset(rowdata);
+ } else if (!ast_str_strlen(rowdata)) {
/* Because we encode the empty string for a NULL, we will encode
* actual empty strings as a string containing a single whitespace. */
- ast_copy_string(rowdata, " ", sizeof(rowdata));
+ ast_str_set(&rowdata, -1, "%s", " ");
+ } else if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
+ if (indicator != ast_str_strlen(rowdata)) {
+ /* If the available space was not enough to contain the row data enlarge and read in the rest */
+ ast_str_make_space(&rowdata, indicator + 1);
+ res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
+ ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
+ ast_str_update(rowdata);
+ }
}
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
@@ -282,7 +293,8 @@
ast_odbc_release_obj(obj);
return NULL;
}
- stringp = rowdata;
+
+ stringp = ast_str_buffer(rowdata);
while (stringp) {
chunk = strsep(&stringp, ";");
if (!ast_strlen_zero(ast_strip(chunk))) {
@@ -326,7 +338,7 @@
SQLHSTMT stmt;
char sql[1024];
char coltitle[256];
- char rowdata[2048];
+ struct ast_str *rowdata = ast_str_thread_get(&rowdata_buf, 128);
const char *initfield;
char *op;
const char *newparam;
@@ -426,7 +438,6 @@
continue;
}
for (x=0;x<colcount;x++) {
- rowdata[0] = '\0';
colsize = 0;
collen = sizeof(coltitle);
res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
@@ -437,17 +448,31 @@
goto next_sql_fetch;
}
+ ast_str_reset(rowdata);
indicator = 0;
- res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
- if (indicator == SQL_NULL_DATA)
+
+ res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata), ast_str_size(rowdata), &indicator);
+ ast_str_update(rowdata);
+ if (indicator == SQL_NULL_DATA) {
continue;
+ }
+
+ if ((res == SQL_SUCCESS) || (res == SQL_SUCCESS_WITH_INFO)) {
+ if (indicator != ast_str_strlen(rowdata)) {
+ /* If the available space was not enough to contain the row data enlarge and read in the rest */
+ ast_str_make_space(&rowdata, indicator + 1);
+ res = SQLGetData(stmt, x + 1, SQL_CHAR, ast_str_buffer(rowdata) + ast_str_strlen(rowdata),
+ ast_str_size(rowdata) - ast_str_strlen(rowdata), &indicator);
+ ast_str_update(rowdata);
+ }
+ }
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
ast_category_destroy(cat);
goto next_sql_fetch;
}
- stringp = rowdata;
+ stringp = ast_str_buffer(rowdata);
while (stringp) {
chunk = strsep(&stringp, ";");
if (!ast_strlen_zero(ast_strip(chunk))) {
@@ -872,17 +897,18 @@
return -1;
}
-
struct config_odbc_obj {
char *sql;
unsigned long cat_metric;
char category[128];
char var_name[128];
- char var_val[1024]; /* changed from 128 to 1024 via bug 8251 */
+ char *var_val;
+ unsigned long var_val_size;
SQLLEN err;
};
-static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
+
+static SQLHSTMT length_determination_odbc_prepare(struct odbc_obj *obj, void *data)
{
struct config_odbc_obj *q = data;
SQLHSTMT sth;
@@ -901,10 +927,34 @@
return NULL;
}
+ SQLBindCol(sth, 1, SQL_C_ULONG, &q->var_val_size, sizeof(q->var_val_size), &q->err);
+
+ return sth;
+}
+
+static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
+{
+ struct config_odbc_obj *q = data;
+ SQLHSTMT sth;
+ int res;
+
+ res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_verb(4, "Failure in AllocStatement %d\n", res);
+ return NULL;
+ }
+
+ res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
+ if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
+ ast_verb(4, "Error in PREPARE %d\n", res);
+ SQLFreeHandle(SQL_HANDLE_STMT, sth);
+ return NULL;
+ }
+
SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
- SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err);
+ SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, q->var_val_size, &q->err);
return sth;
}
@@ -935,16 +985,64 @@
if (!obj)
return NULL;
+ q.sql = sqlbuf;
+
+ ast_build_string(&sql, &sqlleft, "SELECT MAX(LENGTH(var_val)) FROM %s WHERE filename='%s'", table, file);
+
+ 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_odbc_release_obj(obj);
+ return NULL;
+ }
+
+ 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);
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ return NULL;
+ }
+
+ if (!rowcount) {
+ ast_log(LOG_NOTICE, "found nothing\n");
+ ast_odbc_release_obj(obj);
+ return cfg;
+ }
+
+ /* There will be only one result for this, the maximum length of a variable value */
+ if (SQLFetch(stmt) == SQL_NO_DATA) {
+ ast_log(LOG_NOTICE, "Failed to determine maximum length of a configuration value\n");
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+ ast_odbc_release_obj(obj);
+ return NULL;
+ }
+
+ /* 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 ");
- q.sql = sqlbuf;
+
+ q.var_val_size += 1;
+ q.var_val = ast_malloc(q.var_val_size);
+ if (!q.var_val) {
+ ast_log(LOG_WARNING, "Could not create buffer for reading in configuration values for '%s'\n", file);
+ ast_odbc_release_obj(obj);
+ return NULL;
+ }
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_odbc_release_obj(obj);
+ ast_free(q.var_val);
return NULL;
}
@@ -954,12 +1052,14 @@
ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
+ ast_free(q.var_val);
return NULL;
}
if (!rowcount) {
ast_log(LOG_NOTICE, "found nothing\n");
ast_odbc_release_obj(obj);
+ ast_free(q.var_val);
return cfg;
}
@@ -970,6 +1070,7 @@
if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) {
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
+ ast_free(q.var_val);
return NULL;
}
continue;
@@ -991,6 +1092,7 @@
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj);
+ ast_free(q.var_val);
return cfg;
}
More information about the svn-commits
mailing list