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 17:51:35 +00: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;
|
|
|
|
};
|
|
|
|
|
2011-10-20 21:48:47 +00:00
|
|
|
static int testBufInfiniteLoop(const void *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 17:51:35 +00:00
|
|
|
{
|
|
|
|
virBuffer bufinit = VIR_BUFFER_INITIALIZER;
|
|
|
|
virBufferPtr buf = &bufinit;
|
|
|
|
char *addstr = NULL, *bufret = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
const struct testInfo *info = data;
|
|
|
|
|
|
|
|
virBufferAddChar(buf, 'a');
|
|
|
|
|
|
|
|
/*
|
2011-10-20 21:48:47 +00:00
|
|
|
* Infinite loop used to trigger if:
|
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 17:51:35 +00:00
|
|
|
* (strlen + 1 > 1000) && (strlen == buf-size - buf-use - 1)
|
2011-10-20 21:48:47 +00:00
|
|
|
* which was the case after the above addchar at the time of the bug.
|
|
|
|
* This test is a bit fragile, since it relies on virBuffer internals.
|
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 17:51:35 +00:00
|
|
|
*/
|
|
|
|
if (virAsprintf(&addstr, "%*s", buf->a - buf->b - 1, "a") < 0) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info->doEscape)
|
|
|
|
virBufferEscapeString(buf, "%s", addstr);
|
|
|
|
else
|
2011-04-30 16:34:49 +00: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 17:51:35 +00: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;
|
|
|
|
}
|
|
|
|
|
2011-10-20 21:48:47 +00:00
|
|
|
static int testBufAutoIndent(const void *data ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virBuffer bufinit = VIR_BUFFER_INITIALIZER;
|
|
|
|
virBufferPtr buf = &bufinit;
|
|
|
|
const char expected[] =
|
|
|
|
" 1\n 2\n 3\n 4\n 5\n 6\n 7\n &\n 8\n 9\n 10\n ' 11'\n";
|
|
|
|
char *result = NULL;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (virBufferGetIndent(buf, false) != 0 ||
|
|
|
|
virBufferGetIndent(buf, true) != 0) {
|
|
|
|
TEST_ERROR("Wrong indentation");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
virBufferAdjustIndent(buf, 3);
|
|
|
|
if (virBufferGetIndent(buf, false) != 3 ||
|
|
|
|
virBufferGetIndent(buf, true) != 3 ||
|
|
|
|
virBufferError(buf)) {
|
|
|
|
TEST_ERROR("Wrong indentation");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
virBufferAdjustIndent(buf, -2);
|
|
|
|
if (virBufferGetIndent(buf, false) != 1 ||
|
|
|
|
virBufferGetIndent(buf, true) != 1 ||
|
|
|
|
virBufferError(buf)) {
|
|
|
|
TEST_ERROR("Wrong indentation");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
virBufferAdjustIndent(buf, -3);
|
|
|
|
if (virBufferGetIndent(buf, false) != -1 ||
|
|
|
|
virBufferGetIndent(buf, true) != -1 ||
|
|
|
|
virBufferError(buf) != -1) {
|
|
|
|
TEST_ERROR("Usage error not flagged");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
virBufferFreeAndReset(buf);
|
|
|
|
if (virBufferGetIndent(buf, false) != 0 ||
|
|
|
|
virBufferGetIndent(buf, true) != 0 ||
|
|
|
|
virBufferError(buf)) {
|
|
|
|
TEST_ERROR("Reset didn't clear indentation");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
virBufferAdjustIndent(buf, 2);
|
|
|
|
virBufferAddLit(buf, "1");
|
|
|
|
if (virBufferGetIndent(buf, false) != 2 ||
|
|
|
|
virBufferGetIndent(buf, true) != 0) {
|
|
|
|
TEST_ERROR("Wrong indentation");
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
virBufferAddLit(buf, "\n");
|
|
|
|
virBufferAdd(buf, "" "2\n", -1); /* Extra "" appeases syntax-check */
|
|
|
|
virBufferAddChar(buf, '3');
|
|
|
|
virBufferAddChar(buf, '\n');
|
|
|
|
virBufferAsprintf(buf, "%d", 4);
|
|
|
|
virBufferAsprintf(buf, "%c", '\n');
|
|
|
|
virBufferStrcat(buf, "5", "\n", "6\n", NULL);
|
|
|
|
virBufferEscapeString(buf, "%s\n", "7");
|
|
|
|
virBufferEscapeString(buf, "%s\n", "&");
|
|
|
|
virBufferEscapeSexpr(buf, "%s", "8\n");
|
|
|
|
virBufferURIEncodeString(buf, "9");
|
|
|
|
virBufferAddChar(buf, '\n');
|
|
|
|
virBufferEscapeShell(buf, "10");
|
|
|
|
virBufferAddChar(buf, '\n');
|
|
|
|
virBufferEscapeShell(buf, " 11");
|
|
|
|
virBufferAddChar(buf, '\n');
|
|
|
|
|
|
|
|
result = virBufferContentAndReset(buf);
|
|
|
|
if (!result || STRNEQ(result, expected)) {
|
|
|
|
virtTestDifference(stderr, expected, result);
|
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
VIR_FREE(result);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
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 17:51:35 +00:00
|
|
|
static int
|
2011-04-29 16:21:20 +00: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 17:51:35 +00:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
2010-09-13 11:33:31 +00: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 17:51:35 +00: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);
|
2011-10-20 21:48:47 +00:00
|
|
|
DO_TEST("Auto-indentation", testBufAutoIndent, 0);
|
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 17:51:35 +00:00
|
|
|
|
|
|
|
return(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIRT_TEST_MAIN(mymain)
|