[asterisk-commits] seanbright: branch 10 r374135 - in /branches/10: apps/ include/asterisk/ main...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Oct 1 12:52:41 CDT 2012


Author: seanbright
Date: Mon Oct  1 12:52:38 2012
New Revision: 374135

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=374135
Log:
Use ast_copy_string instead of strncpy to guarantee a NUL terminated string.
........

Merged revisions 374132 from http://svn.asterisk.org/svn/asterisk/branches/10

Modified:
    branches/10/apps/app_queue.c
    branches/10/include/asterisk/astdb.h
    branches/10/main/db.c
    branches/10/tests/test_db.c

Modified: branches/10/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/apps/app_queue.c?view=diff&rev=374135&r1=374134&r2=374135
==============================================================================
--- branches/10/apps/app_queue.c (original)
+++ branches/10/apps/app_queue.c Mon Oct  1 12:52:38 2012
@@ -927,8 +927,6 @@
 
 /*! \brief Persistent Members astdb family */
 static const char * const pm_family = "Queue/PersistentMembers";
-/* The maximum length of each persistent member queue database entry */
-#define PM_MAX_LEN 8192
 
 /*! \brief queues.conf [general] option */
 static int queue_persistent_members = 0;
@@ -5311,15 +5309,18 @@
 static void dump_queue_members(struct call_queue *pm_queue)
 {
 	struct member *cur_member;
-	char value[PM_MAX_LEN];
-	int value_len = 0;
-	int res;
+	struct ast_str *value;
 	struct ao2_iterator mem_iter;
 
-	memset(value, 0, sizeof(value));
-
-	if (!pm_queue)
+	if (!pm_queue) {
 		return;
+	}
+
+	/* 4K is a reasonable default for most applications, but we grow to
+	 * accommodate more if necessary. */
+	if (!(value = ast_str_create(4096))) {
+		return;
+	}
 
 	mem_iter = ao2_iterator_init(pm_queue->members, 0);
 	while ((cur_member = ao2_iterator_next(&mem_iter))) {
@@ -5328,25 +5329,27 @@
 			continue;
 		}
 
-		res = snprintf(value + value_len, sizeof(value) - value_len, "%s%s;%d;%d;%s;%s",
-			value_len ? "|" : "", cur_member->interface, cur_member->penalty, cur_member->paused, cur_member->membername, cur_member->state_interface);
+		ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s",
+			ast_str_strlen(value) ? "|" : "",
+			cur_member->interface,
+			cur_member->penalty,
+			cur_member->paused,
+			cur_member->membername,
+			cur_member->state_interface);
 
 		ao2_ref(cur_member, -1);
-
-		if (res != strlen(value + value_len)) {
-			ast_log(LOG_WARNING, "Could not create persistent member string, out of space\n");
-			break;
-		}
-		value_len += res;
 	}
 	ao2_iterator_destroy(&mem_iter);
-	
-	if (value_len && !cur_member) {
-		if (ast_db_put(pm_family, pm_queue->name, value))
+
+	if (ast_str_strlen(value) && !cur_member) {
+		if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value)))
 			ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
-	} else
+	} else {
 		/* Delete the entry if the queue is empty or there is an error */
 		ast_db_del(pm_family, pm_queue->name);
+	}
+
+	ast_free(value);
 }
 
 /*! \brief Remove member from queue 
@@ -5678,7 +5681,7 @@
 	struct ast_db_entry *db_tree;
 	struct ast_db_entry *entry;
 	struct call_queue *cur_queue;
-	char queue_data[PM_MAX_LEN];
+	char *queue_data;
 
 	/* Each key in 'pm_family' is the name of a queue */
 	db_tree = ast_db_gettree(pm_family, NULL);
@@ -5704,7 +5707,7 @@
 			continue;
 		} 
 
-		if (ast_db_get(pm_family, queue_name, queue_data, PM_MAX_LEN)) {
+		if (ast_db_get_allocated(pm_family, queue_name, &queue_data)) {
 			queue_t_unref(cur_queue, "Expire reload reference");
 			continue;
 		}
@@ -5748,6 +5751,7 @@
 			}
 		}
 		queue_t_unref(cur_queue, "Expire reload reference");
+		ast_free(queue_data);
 	}
 
 	if (db_tree) {

Modified: branches/10/include/asterisk/astdb.h
URL: http://svnview.digium.com/svn/asterisk/branches/10/include/asterisk/astdb.h?view=diff&rev=374135&r1=374134&r2=374135
==============================================================================
--- branches/10/include/asterisk/astdb.h (original)
+++ branches/10/include/asterisk/astdb.h Mon Oct  1 12:52:38 2012
@@ -36,6 +36,17 @@
 /*!\brief Get key value specified by family/key */
 int ast_db_get(const char *family, const char *key, char *out, int outlen);
 
+/*!\brief Get key value specified by family/key as a heap allocated string.
+ *
+ * Given a \a family and \a key, sets \a out to a pointer to a heap
+ * allocated string.  In the event of an error, \a out will be set to
+ * NULL.  The string must be freed by calling ast_free().
+ *
+ * \retval -1 An error occurred
+ * \retval 0 Success
+ */
+int ast_db_get_allocated(const char *family, const char *key, char **out);
+
 /*!\brief Store value addressed by family/key */
 int ast_db_put(const char *family, const char *key, const char *value);
 

Modified: branches/10/main/db.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/main/db.c?view=diff&rev=374135&r1=374134&r2=374135
==============================================================================
--- branches/10/main/db.c (original)
+++ branches/10/main/db.c Mon Oct  1 12:52:38 2012
@@ -307,7 +307,21 @@
 	return res;
 }
 
-int ast_db_get(const char *family, const char *key, char *value, int valuelen)
+/*!
+ * \internal
+ * \brief Get key value specified by family/key.
+ *
+ * Gets the value associated with the specified \a family and \a key, and
+ * stores it, either into the fixed sized buffer specified by \a buffer
+ * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
+ *
+ * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
+ *       and must be freed by calling ast_free().
+ *
+ * \retval -1 An error occurred
+ * \retval 0 Success
+ */
+static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
 {
 	const unsigned char *result;
 	char fullkey[MAX_DB_FIELD];
@@ -332,12 +346,35 @@
 		ast_log(LOG_WARNING, "Couldn't get value\n");
 		res = -1;
 	} else {
-		ast_copy_string(value, (const char *) result, valuelen);
+		const char *value = (const char *) result;
+
+		if (bufferlen == -1) {
+			*buffer = ast_strdup(value);
+		} else {
+			ast_copy_string(*buffer, value, bufferlen);
+		}
 	}
 	sqlite3_reset(get_stmt);
 	ast_mutex_unlock(&dblock);
 
 	return res;
+}
+
+int ast_db_get(const char *family, const char *key, char *value, int valuelen)
+{
+	ast_assert(value != NULL);
+
+	/* Make sure we initialize */
+	value[0] = 0;
+
+	return db_get_common(family, key, &value, valuelen);
+}
+
+int ast_db_get_allocated(const char *family, const char *key, char **out)
+{
+	*out = NULL;
+
+	return db_get_common(family, key, out, -1);
 }
 
 int ast_db_del(const char *family, const char *key)

Modified: branches/10/tests/test_db.c
URL: http://svnview.digium.com/svn/asterisk/branches/10/tests/test_db.c?view=diff&rev=374135&r1=374134&r2=374135
==============================================================================
--- branches/10/tests/test_db.c (original)
+++ branches/10/tests/test_db.c Mon Oct  1 12:52:38 2012
@@ -232,11 +232,70 @@
 
 	return res;
 }
+
+AST_TEST_DEFINE(put_get_long)
+{
+	int res = AST_TEST_PASS;
+	struct ast_str *s;
+	int i, j;
+
+#define STR_FILL_32 "abcdefghijklmnopqrstuvwxyz123456"
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "put_get_long";
+		info->category = "/main/astdb/";
+		info->summary = "ast_db_(put|get_allocated) unit test";
+		info->description =
+			"Ensures that the ast_db_put and ast_db_get_allocated functions work";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	if (!(s = ast_str_create(4096))) {
+		return AST_TEST_FAIL;
+	}
+
+	for (i = 1024; i <= 1024 * 1024 * 8; i *= 2) {
+		char *out = NULL;
+
+		ast_str_reset(s);
+
+		for (j = 0; j < i; j += sizeof(STR_FILL_32) - 1) {
+			ast_str_append(&s, 0, "%s", STR_FILL_32);
+		}
+
+		if (ast_db_put("astdbtest", "long", ast_str_buffer(s))) {
+			ast_test_status_update(test, "Failed to put value of %zu bytes\n", ast_str_strlen(s));
+			res = AST_TEST_FAIL;
+		} else if (ast_db_get_allocated("astdbtest", "long", &out)) {
+			ast_test_status_update(test, "Failed to get value of %zu bytes\n", ast_str_strlen(s));
+			res = AST_TEST_FAIL;
+		} else if (strcmp(ast_str_buffer(s), out)) {
+			ast_test_status_update(test, "Failed to match value of %zu bytes\n", ast_str_strlen(s));
+			res = AST_TEST_FAIL;
+		} else if (ast_db_del("astdbtest", "long")) {
+			ast_test_status_update(test, "Failed to delete astdbtest/long\n");
+			res = AST_TEST_FAIL;
+		}
+
+		if (out) {
+			ast_free(out);
+		}
+	}
+
+	ast_free(s);
+
+	return res;
+}
+
 static int unload_module(void)
 {
 	AST_TEST_UNREGISTER(put_get_del);
 	AST_TEST_UNREGISTER(gettree_deltree);
 	AST_TEST_UNREGISTER(perftest);
+	AST_TEST_UNREGISTER(put_get_long);
 	return 0;
 }
 
@@ -245,6 +304,7 @@
 	AST_TEST_REGISTER(put_get_del);
 	AST_TEST_REGISTER(gettree_deltree);
 	AST_TEST_REGISTER(perftest);
+	AST_TEST_REGISTER(put_get_long);
 	return AST_MODULE_LOAD_SUCCESS;
 }
 




More information about the asterisk-commits mailing list