Whether or not vsnprintf() allows NULL as pointer to destination
string to calculate length depends on the implementation.

Revert more efficient, but non-portable implementation.

This reverts commit 338a674faa96ae321560efa3f1b1e8122d61aac4.
---
 src/helper/log.c |   43 +++++++++++++++++++++++++++----------------
 1 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/src/helper/log.c b/src/helper/log.c
index 3067ecc..f1aa6d7 100644
--- a/src/helper/log.c
+++ b/src/helper/log.c
@@ -417,26 +417,37 @@ int log_remove_callback(log_callback_fn fn, void *priv)
 /* return allocated string w/printf() result */
 char *alloc_vprintf(const char *fmt, va_list ap)
 {
-       va_list ap_copy;
-       int len;
-       char *string;
+       /* no buffer at the beginning, force realloc to do the job */
+       char *string = NULL;
 
-       /* determine the length of the buffer needed */
-       va_copy(ap_copy, ap);
-       len = vsnprintf(NULL, 0, fmt, ap_copy);
-       va_end(ap_copy);
+       /* start with buffer size suitable for typical messages */
+       int size = 128;
 
-       /* allocate and make room for terminating zero. */
-       /* FIXME: The old version always allocated at least one byte extra and
-        * other code depend on that. They should be probably be fixed, but for
-        * now reserve the extra byte. */
-       string = malloc(len + 2);
-       if (string == NULL)
-               return NULL;
+       for (;;)
+       {
+               char *t = string;
+               va_list ap_copy;
+               int ret;
+               string = realloc(string, size);
+               if (string == NULL)
+               {
+                       if (t != NULL)
+                               free(t);
+                       return NULL;
+               }
 
-       /* do the real work */
-       vsnprintf(string, len + 1, fmt, ap);
+               va_copy(ap_copy, ap);
+
+               ret = vsnprintf(string, size, fmt, ap_copy);
+               /* NB! The result of the vsnprintf() might be an *EMPTY* 
string! */
+               if ((ret >= 0) && ((ret + 1) < size))
+                       break;
+
+               /* there was just enough or not enough space, allocate more in 
the next round */
+               size *= 2; /* double the buffer size */
+       }
 
+       /* the returned buffer is by principle guaranteed to be at least one 
character longer */
        return string;
 }
 
-- 
1.6.3.3

_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to