From 1fe5108763b8a4bb9dede06afc33b5bd5266988a Mon Sep 17 00:00:00 2001
From: "Kevin P. Fleming" <kpfleming@digium.com>
Date: Fri, 6 Jan 2006 19:19:17 +0000
Subject: [PATCH] ensure that string field 'build' operation only evaluates
 arguments one time fix some minor documentation errors return proper type
 from string field space allocator

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7841 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 include/asterisk/stringfields.h | 31 ++++++++++++++++++++-----------
 utils.c                         | 25 +++++++++++++++++++++++--
 2 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/include/asterisk/stringfields.h b/include/asterisk/stringfields.h
index 02811a6112..5631682b2a 100644
--- a/include/asterisk/stringfields.h
+++ b/include/asterisk/stringfields.h
@@ -143,8 +143,22 @@ int __ast_string_field_init(struct ast_string_field_pool *pool, size_t size,
   and the existing fields stored there will be updated to point
   into the new pool.
 */
-char *__ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
-				     ast_string_field *fields, int num_fields);
+ast_string_field __ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
+						ast_string_field *fields, int num_fields);
+
+/*!
+  \internal
+  \brief Set a field to a complex (built) value
+  \param pool Pointer to the pool structure
+  \param fields Pointer to the first entry of the field array
+  \param num_fields Number of fields in the array
+  \param index Index position of the field within the structure
+  \param format printf-style format string
+  \return nothing
+*/
+void __ast_string_field_index_build(struct ast_string_field_pool *pool,
+				    ast_string_field *fields, int num_fields,
+				    int index, const char *format, ...);
 
 /*!
   The default amount of storage to be allocated for a field pool.
@@ -216,23 +230,18 @@ char *__ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t
 	ast_string_field_index_set(x, ast_string_field_index(x, field), data)
 
 /*!
-  \brief Set a field to a simple complex (built) value
+  \brief Set a field to a complex (built) value
   \param x Pointer to a structure containing fields
   \param index Index position of the field within the structure
   \param fmt printf-style format string
   \param args Arguments for format string
   \return nothing
 */
-#define ast_string_field_index_build(x, index, fmt, args...) do { \
-	char s; \
-	size_t needed; \
-	needed = snprintf(&s, 1, fmt, args) + 1; \
-	if ((x->__begin_field[index] = __ast_string_field_alloc_space(&x->__field_pool, needed, &x->__begin_field[0], ast_string_field_count(x)))) \
-		sprintf((char *) x->__begin_field[index], fmt, args); \
-	} while (0)
+#define ast_string_field_index_build(x, index, fmt, args...) \
+	__ast_string_field_index_build(&x->__field_pool, &x->__begin_field[0], ast_string_field_count(x), index, fmt, args)
 
 /*!
-  \brief Set a field to a simple complex (built) value
+  \brief Set a field to a complex (built) value
   \param x Pointer to a structure containing fields
   \param field Name of the field to set
   \param fmt printf-style format string
diff --git a/utils.c b/utils.c
index df2e393eb7..cc35105418 100644
--- a/utils.c
+++ b/utils.c
@@ -943,8 +943,8 @@ int __ast_string_field_init(struct ast_string_field_pool *pool, size_t size,
 	return pool->base ? 0 : -1;
 }
 
-char *__ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
-				     ast_string_field *fields, int num_fields)
+ast_string_field __ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t needed,
+						ast_string_field *fields, int num_fields)
 {
 	char *result = NULL;
 
@@ -974,3 +974,24 @@ char *__ast_string_field_alloc_space(struct ast_string_field_pool *pool, size_t
 	pool->space -= needed;
 	return result;
 }
+
+void __ast_string_field_index_build(struct ast_string_field_pool *pool,
+				    ast_string_field *fields, int num_fields,
+				    int index, const char *format, ...)
+{
+	char s;
+	size_t needed;
+	va_list ap1, ap2;
+
+	va_start(ap1, format);
+	va_copy(ap2, ap1);
+
+	needed = vsnprintf(&s, 1, format, ap1) + 1;
+
+	va_end(ap1);
+
+	if ((fields[index] = __ast_string_field_alloc_space(pool, needed, fields, num_fields)))
+		vsprintf((char *) fields[index], format, ap2);
+
+	va_end(ap2);
+}
-- 
GitLab