[libvirt] [PATCH] buf: Fix possible infinite loop in EscapeString, VSnprintf

Cole Robinson crobinso at redhat.com
Wed Sep 1 19:43:44 UTC 2010


The current code will go into an infinite loop if the printf generated
string is >= 1000, AND exactly 1 character smaller than the amount of free
space in the buffer. When this happens, we are dropped into the loop body,
but nothing will actually change, because count == (buf->size - buf->use - 1),
and virBufferGrow returns unchanged if count < (buf->size - buf->use)

Fix this by removing the '- 1' bit from 'size'. The *nprintf functions handle
the NULL byte for us anyways, so we shouldn't need to manually accomodate
for it.

Here's a bug where we are actually hitting this issue:
https://bugzilla.redhat.com/show_bug.cgi?id=602772

Signed-off-by: Cole Robinson <crobinso at redhat.com>
---
 src/util/buf.c |   14 ++++++--------
 1 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/util/buf.c b/src/util/buf.c
index fc1217b..734b8f6 100644
--- a/src/util/buf.c
+++ b/src/util/buf.c
@@ -236,11 +236,11 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...)
         virBufferGrow(buf, 100) < 0)
         return;
 
-    size = buf->size - buf->use - 1;
+    size = buf->size - buf->use;
     va_start(argptr, format);
     va_copy(locarg, argptr);
     while (((count = vsnprintf(&buf->content[buf->use], size, format,
-                               locarg)) < 0) || (count >= size - 1)) {
+                               locarg)) < 0) || (count >= size)) {
         buf->content[buf->use] = 0;
         va_end(locarg);
 
@@ -250,13 +250,12 @@ virBufferVSprintf(const virBufferPtr buf, const char *format, ...)
             return;
         }
 
-        size = buf->size - buf->use - 1;
+        size = buf->size - buf->use;
         va_copy(locarg, argptr);
     }
     va_end(argptr);
     va_end(locarg);
     buf->use += count;
-    buf->content[buf->use] = '\0';
 }
 
 /**
@@ -340,19 +339,18 @@ virBufferEscapeString(const virBufferPtr buf, const char *format, const char *st
         return;
     }
 
-    size = buf->size - buf->use - 1;
+    size = buf->size - buf->use;
     while (((count = snprintf(&buf->content[buf->use], size, format,
-                              (char *)escaped)) < 0) || (count >= size - 1)) {
+                              (char *)escaped)) < 0) || (count >= size)) {
         buf->content[buf->use] = 0;
         grow_size = (count > 1000) ? count : 1000;
         if (virBufferGrow(buf, grow_size) < 0) {
             VIR_FREE(escaped);
             return;
         }
-        size = buf->size - buf->use - 1;
+        size = buf->size - buf->use;
     }
     buf->use += count;
-    buf->content[buf->use] = '\0';
     VIR_FREE(escaped);
 }
 
-- 
1.7.2.1




More information about the libvir-list mailing list