[asterisk-commits] twilson: branch twilson/res_config_sqlite3 r334432 - /team/twilson/res_config...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Sep 3 22:44:06 CDT 2011


Author: twilson
Date: Sat Sep  3 22:43:55 2011
New Revision: 334432

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=334432
Log:
Add escaping

Modified:
    team/twilson/res_config_sqlite3/res/res_config_sqlite3.c

Modified: team/twilson/res_config_sqlite3/res/res_config_sqlite3.c
URL: http://svnview.digium.com/svn/asterisk/team/twilson/res_config_sqlite3/res/res_config_sqlite3.c?view=diff&rev=334432&r1=334431&r2=334432
==============================================================================
--- team/twilson/res_config_sqlite3/res/res_config_sqlite3.c (original)
+++ team/twilson/res_config_sqlite3/res/res_config_sqlite3.c Sat Sep  3 22:43:55 2011
@@ -101,9 +101,69 @@
 
 AST_MUTEX_DEFINE_STATIC(config_lock);
 
+/* We need a separate buffer for each field we might use concurrently */
+AST_THREADSTORAGE(escape_table_buf);
+AST_THREADSTORAGE(escape_column_buf);
+AST_THREADSTORAGE(escape_value_buf);
+
 static int realtime_sqlite3_execute_handle(struct realtime_sqlite3_db *db, const char *sql, int (*callback)(void*, int, char **, char **), void *arg, int sync);
 void db_start_batch(struct realtime_sqlite3_db *db);
 void db_stop_batch(struct realtime_sqlite3_db *db);
+
+static inline const char *sqlite3_escape_string_helper(struct ast_threadstorage *ts, const char *param)
+{
+	size_t maxlen = strlen(param) * 2 + sizeof("\"\"");
+	/* It doesn't appear that sqlite3_snprintf will do more than double the
+	 * length of a string with %q as an option. %Q could double and possibly
+	 * add two quotes, and convert NULL pointers to the word "NULL", but we
+	 * don't allow those anyway. Just going to use %q for now. */
+	struct ast_str *buf = ast_str_thread_get(ts, maxlen);
+	const char *result;
+	char q = ts == &escape_value_buf ? '\'' : '"'; 
+
+	ast_str_reset(buf);
+	result = S_OR(sqlite3_snprintf(maxlen, ast_str_buffer(buf), "%c%q%c", q, param, q), "");
+	ast_str_update(buf);
+
+	return result;
+}
+
+static inline const char *sqlite3_escape_table(const char *param)
+{
+	return sqlite3_escape_string_helper(&escape_table_buf, param);
+}
+
+static inline const char *sqlite3_escape_column(const char *param)
+{
+	return sqlite3_escape_string_helper(&escape_column_buf, param);
+}
+
+/* Not inlining this function because it uses strdupa and I don't know if the compiler would be dumb */
+static const char *sqlite3_escape_column_op(const char *param)
+{
+	size_t maxlen = strlen(param) * 2 + sizeof("\"\" =");
+	struct ast_str *buf = ast_str_thread_get(&escape_column_buf, maxlen);
+	char *op, *dup;
+	const char *result;
+
+	dup = ast_strdupa(param);
+
+	if ((op = strchr(dup, ' '))) {
+		*op = '\0';
+		op++;
+	}
+
+	ast_str_reset(buf);
+	result = sqlite3_snprintf(maxlen, ast_str_buffer(buf), "\"%q\" %s", dup, S_OR(op, "="));
+	ast_str_update(buf);
+
+	return result;
+}
+
+static inline const char *sqlite3_escape_value(const char *param)
+{
+	return sqlite3_escape_string_helper(&escape_value_buf, param);
+}
 
 static int db_hash_fn(const void *obj, const int flags)
 {
@@ -568,10 +628,12 @@
 
 	while ((param = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
 		if (first) {
-			ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s%s '%s'", table, param, strchr(param, ' ') ? "" : " =", value);
+			ast_str_set(&sql, 0, "SELECT * FROM %s WHERE %s %s", sqlite3_escape_table(table),
+					sqlite3_escape_column_op(param), sqlite3_escape_value(value));
 			first = 0;
 		} else {
-			ast_str_append(&sql, 0, " AND %s%s '%s'", param, strchr(param, ' ') ? "" : " =", value);
+			ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(param),
+					sqlite3_escape_value(value));
 		}
 	}
 
@@ -640,14 +702,15 @@
 
 	while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
 		if (first) {
-			ast_str_set(&sql, 0, "UPDATE %s SET `%s` = '%s'", table, key, value);
+			ast_str_set(&sql, 0, "UPDATE %s SET %s = %s",
+					sqlite3_escape_table(table), sqlite3_escape_column(key), sqlite3_escape_value(value));
 			first = 0;
 		} else {
-			ast_str_append(&sql, 0, ", `%s` = '%s'", key, value);
-		}
-	}
-
-	ast_str_append(&sql, 0, " WHERE %s%s '%s'", keyfield, strchr(keyfield, ' ') ? "" : " =", entity);
+			ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(key), sqlite3_escape_value(value));
+		}
+	}
+
+	ast_str_append(&sql, 0, " WHERE %s %s", sqlite3_escape_column_op(keyfield), sqlite3_escape_value(entity));
 
 	res = realtime_sqlite3_execute(database, ast_str_buffer(sql), NULL, NULL, 1);
 	ast_free(sql);
@@ -681,20 +744,20 @@
 
 	while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
 		if (first) {
-			ast_str_append(&where_clause, 0, " WHERE %s%s '%s'", key, strchr(key, ' ') ? "" : " =", value);
+			ast_str_set(&where_clause, 0, " WHERE %s %s", sqlite3_escape_column_op(key), sqlite3_escape_value(value));
 			first = 0;
 		} else {
-			ast_str_append(&where_clause, 0, " AND %s%s '%s'", key, strchr(key, ' ') ? "" : " =", value);
+			ast_str_append(&where_clause, 0, " AND %s %s", sqlite3_escape_column_op(key), sqlite3_escape_value(value));
 		}
 	}
 
 	first = 1;
 	while ((key = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
 		if (first) {
-			ast_str_set(&sql, 0, "UPDATE %s SET `%s` = '%s'", table, key, value);
+			ast_str_set(&sql, 0, "UPDATE %s SET %s = %s", sqlite3_escape_table(table), sqlite3_escape_column(key), sqlite3_escape_value(value));
 			first = 0;
 		} else {
-			ast_str_append(&sql, 0, ", `%s` = '%s'", key, value);
+			ast_str_append(&sql, 0, ", %s = %s", sqlite3_escape_column(key), sqlite3_escape_value(value));
 		}
 	}
 
@@ -733,12 +796,12 @@
 
 	while ((column = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
 		if (first) {
-			ast_str_set(&sql, 0, "INSERT INTO %s (`%s`", table, column);
-			ast_str_set(&values, 0, ") VALUES ('%s'", value);
+			ast_str_set(&sql, 0, "INSERT INTO %s (%s", sqlite3_escape_table(table), sqlite3_escape_column(column));
+			ast_str_set(&values, 0, ") VALUES (%s", sqlite3_escape_value(value));
 			first = 0;
 		} else {
-			ast_str_append(&sql, 0, ", `%s`", column);
-			ast_str_append(&values, 0, ", '%s'", value);
+			ast_str_append(&sql, 0, ", %s", sqlite3_escape_column(column));
+			ast_str_append(&values, 0, ", %s", sqlite3_escape_value(value));
 		}
 	}
 
@@ -772,10 +835,11 @@
 
 	while ((param = va_arg(ap, const char *)) && (value = va_arg(ap, const char *))) {
 		if (first) {
-			ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s%s '%s'", table, param, strchr(param, ' ') ? "" : " =", value);
+			ast_str_set(&sql, 0, "DELETE FROM %s WHERE %s %s", sqlite3_escape_table(table),
+					sqlite3_escape_column_op(param), sqlite3_escape_value(value));
 			first = 0;
 		} else {
-			ast_str_append(&sql, 0, " AND %s%s '%s'", param, strchr(param, ' ') ? "" : " =", value);
+			ast_str_append(&sql, 0, " AND %s %s", sqlite3_escape_column_op(param), sqlite3_escape_value(value));
 		}
 	}
 
@@ -834,10 +898,11 @@
 
 	while ((column = va_arg(ap, typeof(column))) && (type = va_arg(ap, typeof(type))) && (sz = va_arg(ap, typeof(sz)))) {
 		if (first) {
-			ast_str_set(&sql, 0, "CREATE TABLE IF NOT EXISTS %s (%s %s", table, column, get_sqlite_column_type(type));
+			ast_str_set(&sql, 0, "CREATE TABLE IF NOT EXISTS %s (%s %s", sqlite3_escape_table(table),
+					sqlite3_escape_column(column), get_sqlite_column_type(type));
 			first = 0;
 		} else {
-			ast_str_append(&sql, 0, ", %s %s", column, get_sqlite_column_type(type));
+			ast_str_append(&sql, 0, ", %s %s", sqlite3_escape_column(column), get_sqlite_column_type(type));
 		}
 	}
 




More information about the asterisk-commits mailing list