buf: Fix possible infinite loop in EscapeString, VSnprintf
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 accommodate
for it.
Here's a bug where we are actually hitting this issue:
https://bugzilla.redhat.com/show_bug.cgi?id=602772
v2: Eric's improvements: while -> if (), remove extra va_list variable,
make sure we report buffer error if snprintf fails
v3: Add tests/virbuftest which reproduces the infinite loop before this
patch, works correctly after
2010-09-01 21:51:35 +04:00
# include <config.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "internal.h"
# include "util.h"
# include "testutils.h"
# include "buf.h"
# include "memory.h"
# define TEST_ERROR(...) \
do { \
if ( virTestGetDebug ( ) ) \
fprintf ( stderr , __VA_ARGS__ ) ; \
} while ( 0 )
struct testInfo {
int doEscape ;
} ;
static int testBufInfiniteLoop ( const void * data ATTRIBUTE_UNUSED )
{
virBuffer bufinit = VIR_BUFFER_INITIALIZER ;
virBufferPtr buf = & bufinit ;
char * addstr = NULL , * bufret = NULL ;
int ret = - 1 ;
const struct testInfo * info = data ;
/* This relies of virBuffer internals, so may break if things change
* in the future */
virBufferAddChar ( buf , ' a ' ) ;
if ( buf - > a ! = 1002 | | buf - > b ! = 1 ) {
TEST_ERROR ( " Buf was not expected size, size=%d use=%d \n " ,
buf - > a , buf - > b ) ;
goto out ;
}
/*
* Infinite loop triggers if :
* ( strlen + 1 > 1000 ) & & ( strlen = = buf - size - buf - use - 1 )
*/
if ( virAsprintf ( & addstr , " %*s " , buf - > a - buf - > b - 1 , " a " ) < 0 ) {
goto out ;
}
if ( info - > doEscape )
virBufferEscapeString ( buf , " %s " , addstr ) ;
else
2011-04-30 20:34:49 +04:00
virBufferAsprintf ( buf , " %s " , addstr ) ;
buf: Fix possible infinite loop in EscapeString, VSnprintf
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 accommodate
for it.
Here's a bug where we are actually hitting this issue:
https://bugzilla.redhat.com/show_bug.cgi?id=602772
v2: Eric's improvements: while -> if (), remove extra va_list variable,
make sure we report buffer error if snprintf fails
v3: Add tests/virbuftest which reproduces the infinite loop before this
patch, works correctly after
2010-09-01 21:51:35 +04:00
ret = 0 ;
out :
bufret = virBufferContentAndReset ( buf ) ;
if ( ! bufret ) {
TEST_ERROR ( " Buffer had error set " ) ;
ret = - 1 ;
}
VIR_FREE ( addstr ) ;
VIR_FREE ( bufret ) ;
return ret ;
}
static int
2011-04-29 20:21:20 +04:00
mymain ( void )
buf: Fix possible infinite loop in EscapeString, VSnprintf
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 accommodate
for it.
Here's a bug where we are actually hitting this issue:
https://bugzilla.redhat.com/show_bug.cgi?id=602772
v2: Eric's improvements: while -> if (), remove extra va_list variable,
make sure we report buffer error if snprintf fails
v3: Add tests/virbuftest which reproduces the infinite loop before this
patch, works correctly after
2010-09-01 21:51:35 +04:00
{
int ret = 0 ;
2010-09-13 15:33:31 +04:00
# define DO_TEST(msg, cb, data) \
buf: Fix possible infinite loop in EscapeString, VSnprintf
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 accommodate
for it.
Here's a bug where we are actually hitting this issue:
https://bugzilla.redhat.com/show_bug.cgi?id=602772
v2: Eric's improvements: while -> if (), remove extra va_list variable,
make sure we report buffer error if snprintf fails
v3: Add tests/virbuftest which reproduces the infinite loop before this
patch, works correctly after
2010-09-01 21:51:35 +04:00
do { \
struct testInfo info = { data } ; \
if ( virtTestRun ( " Buf: " msg , 1 , cb , & info ) < 0 ) \
ret = - 1 ; \
} while ( 0 )
DO_TEST ( " EscapeString infinite loop " , testBufInfiniteLoop , 1 ) ;
DO_TEST ( " VSprintf infinite loop " , testBufInfiniteLoop , 0 ) ;
return ( ret = = 0 ? EXIT_SUCCESS : EXIT_FAILURE ) ;
}
VIRT_TEST_MAIN ( mymain )