mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Fix a potential infinite loop in appendStringInfo: would lock
up if first string to be appended to an empty StringInfo was longer than the initial space allocation. Also speed it up slightly.
This commit is contained in:
parent
4f920a66f4
commit
8f5ff4cf1c
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/lib/stringinfo.c,v 1.11 1998/09/01 03:22:39 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/lib/stringinfo.c,v 1.12 1998/11/08 19:22:24 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -31,27 +31,22 @@ StringInfo
|
|||||||
makeStringInfo()
|
makeStringInfo()
|
||||||
{
|
{
|
||||||
StringInfo res;
|
StringInfo res;
|
||||||
long size;
|
int size;
|
||||||
|
|
||||||
res = (StringInfo) palloc(sizeof(StringInfoData));
|
res = (StringInfo) palloc(sizeof(StringInfoData));
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
elog(ERROR, "makeStringInfo: Out of memory!");
|
elog(ERROR, "makeStringInfo: Out of memory!");
|
||||||
|
|
||||||
size = 100;
|
size = 256; /* initial default size */
|
||||||
res->data = palloc(size);
|
res->data = palloc(size);
|
||||||
if (res->data == NULL)
|
if (res->data == NULL)
|
||||||
{
|
{
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"makeStringInfo: Out of memory! (%ld bytes requested)", size);
|
"makeStringInfo: Out of memory! (%d bytes requested)", size);
|
||||||
}
|
}
|
||||||
res->maxlen = size;
|
res->maxlen = size;
|
||||||
res->len = 0;
|
res->len = 0;
|
||||||
|
/* Make sure the string is empty initially. */
|
||||||
/*
|
|
||||||
* NOTE: we must initialize `res->data' to the empty string because we
|
|
||||||
* use 'strcat' in 'appendStringInfo', which of course it always
|
|
||||||
* expects a null terminated string.
|
|
||||||
*/
|
|
||||||
res->data[0] = '\0';
|
res->data[0] = '\0';
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@ -71,7 +66,8 @@ void
|
|||||||
appendStringInfo(StringInfo str, char *buffer)
|
appendStringInfo(StringInfo str, char *buffer)
|
||||||
{
|
{
|
||||||
int buflen,
|
int buflen,
|
||||||
newlen;
|
newlen,
|
||||||
|
needed;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
Assert(str != NULL);
|
Assert(str != NULL);
|
||||||
@ -84,15 +80,16 @@ appendStringInfo(StringInfo str, char *buffer)
|
|||||||
* some more.
|
* some more.
|
||||||
*/
|
*/
|
||||||
buflen = strlen(buffer);
|
buflen = strlen(buffer);
|
||||||
if (buflen + str->len >= str->maxlen - 1)
|
needed = str->len + buflen + 1;
|
||||||
|
if (needed > str->maxlen)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* how much more space to allocate ? Let's say double the current
|
* how much more space to allocate ? Let's say double the current
|
||||||
* space... However we must check if this is enough!
|
* space... However we must check if this is enough!
|
||||||
*/
|
*/
|
||||||
newlen = 2 * str->len;
|
newlen = 2 * str->maxlen;
|
||||||
while (buflen + str->len >= newlen - 1)
|
while (needed > newlen)
|
||||||
newlen = 2 * newlen;
|
newlen = 2 * newlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -105,7 +102,11 @@ appendStringInfo(StringInfo str, char *buffer)
|
|||||||
"appendStringInfo: Out of memory (%d bytes requested)",
|
"appendStringInfo: Out of memory (%d bytes requested)",
|
||||||
newlen);
|
newlen);
|
||||||
}
|
}
|
||||||
memmove(s, str->data, str->len + 1);
|
/*
|
||||||
|
* transfer the data. strcpy() would work, but is probably a tad
|
||||||
|
* slower than memcpy(), and since we know the string length...
|
||||||
|
*/
|
||||||
|
memcpy(s, str->data, str->len + 1);
|
||||||
pfree(str->data);
|
pfree(str->data);
|
||||||
str->maxlen = newlen;
|
str->maxlen = newlen;
|
||||||
str->data = s;
|
str->data = s;
|
||||||
@ -113,10 +114,10 @@ appendStringInfo(StringInfo str, char *buffer)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* OK, we have enough space now, append 'buffer' at the end of the
|
* OK, we have enough space now, append 'buffer' at the end of the
|
||||||
* string & update the string length. NOTE: this is a text string
|
* string & update the string length. NOTE: strcat() would work,
|
||||||
* (i.e. printable characters) so 'strcat' will do the job (no need to
|
* but is certainly slower than just memcpy'ing the data to the right
|
||||||
* use 'bcopy' et all...)
|
* place.
|
||||||
*/
|
*/
|
||||||
strcat(str->data, buffer);
|
memcpy(str->data + str->len, buffer, buflen + 1);
|
||||||
str->len += buflen;
|
str->len += buflen;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user