Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3147acd

Browse files
committed
Use improved vsnprintf calling logic in more places.
When we are using a C99-compliant vsnprintf implementation (which should bemost places, these days) it is worth the trouble to make use of its reportof how large the buffer needs to be to succeed. This patch adjustsstringinfo.c and some miscellaneous usages in pg_dump to do that, relyingon the logic recently added in libpgcommon's psprintf.c. Since theseplaces want to know the number of bytes written once we succeed, modify theAPI of pvsnprintf() to report that.There remains near-duplicate logic in pqexpbuffer.c, but since that codeis in libpq, psprintf.c's approach of exit()-on-error isn't appropriatefor use there. Also note that I didn't bother touching the multitudeof places that call (v)snprintf without any attempt to provide a resizablebuffer.Release-note-worthy incompatibility: the API of appendStringInfoVA()changed. If there's any third-party code that's calling that directly,it will need tweaking along the same lines as in this patch.David Rowley and Tom Lane
1 parent98c5065 commit3147acd

File tree

8 files changed

+153
-137
lines changed

8 files changed

+153
-137
lines changed

‎src/backend/lib/stringinfo.c

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,18 @@ appendStringInfo(StringInfo str, const char *fmt,...)
8080
for (;;)
8181
{
8282
va_listargs;
83-
boolsuccess;
83+
intneeded;
8484

8585
/* Try to format the data. */
8686
va_start(args,fmt);
87-
success=appendStringInfoVA(str,fmt,args);
87+
needed=appendStringInfoVA(str,fmt,args);
8888
va_end(args);
8989

90-
if (success)
91-
break;
90+
if (needed==0)
91+
break;/* success */
9292

93-
/*Double the buffer size and try again. */
94-
enlargeStringInfo(str,str->maxlen);
93+
/*Increase the buffer size and try again. */
94+
enlargeStringInfo(str,needed);
9595
}
9696
}
9797

@@ -100,59 +100,51 @@ appendStringInfo(StringInfo str, const char *fmt,...)
100100
*
101101
* Attempt to format text data under the control of fmt (an sprintf-style
102102
* format string) and append it to whatever is already in str.If successful
103-
* return true; if not (because there's not enough space), return false
104-
* without modifying str. Typically the caller would enlarge str and retry
105-
* on false return --- see appendStringInfo for standard usage pattern.
103+
* return zero; if not (because there's not enough space), return an estimate
104+
* of the space needed, without modifying str. Typically the caller should
105+
* pass the return value to enlargeStringInfo() before trying again; see
106+
* appendStringInfo for standard usage pattern.
106107
*
107108
* XXX This API is ugly, but there seems no alternative given the C spec's
108109
* restrictions on what can portably be done with va_list arguments: you have
109110
* to redo va_start before you can rescan the argument list, and we can't do
110111
* that from here.
111112
*/
112-
bool
113+
int
113114
appendStringInfoVA(StringInfostr,constchar*fmt,va_listargs)
114115
{
115-
intavail,
116-
nprinted;
116+
intavail;
117+
size_tnprinted;
117118

118119
Assert(str!=NULL);
119120

120121
/*
121122
* If there's hardly any space, don't bother trying, just fail to make the
122-
* caller enlarge the buffer first.
123+
* caller enlarge the buffer first. We have to guess at how much to
124+
* enlarge, since we're skipping the formatting work.
123125
*/
124-
avail=str->maxlen-str->len-1;
126+
avail=str->maxlen-str->len;
125127
if (avail<16)
126-
returnfalse;
128+
return32;
127129

128-
/*
129-
* Assert check here is to catch buggy vsnprintf that overruns the
130-
* specified buffer length. Solaris 7 in 64-bit mode is an example of a
131-
* platform with such a bug.
132-
*/
133-
#ifdefUSE_ASSERT_CHECKING
134-
str->data[str->maxlen-1]='\0';
135-
#endif
136-
137-
nprinted=vsnprintf(str->data+str->len,avail,fmt,args);
130+
nprinted=pvsnprintf(str->data+str->len, (size_t)avail,fmt,args);
138131

139-
Assert(str->data[str->maxlen-1]=='\0');
140-
141-
/*
142-
* Note: some versions of vsnprintf return the number of chars actually
143-
* stored, but at least one returns -1 on failure. Be conservative about
144-
* believing whether the print worked.
145-
*/
146-
if (nprinted >=0&&nprinted<avail-1)
132+
if (nprinted< (size_t)avail)
147133
{
148134
/* Success. Note nprinted does not include trailing null. */
149-
str->len+=nprinted;
150-
returntrue;
135+
str->len+=(int)nprinted;
136+
return0;
151137
}
152138

153139
/* Restore the trailing null so that str is unmodified. */
154140
str->data[str->len]='\0';
155-
return false;
141+
142+
/*
143+
* Return pvsnprintf's estimate of the space needed. (Although this is
144+
* given as a size_t, we know it will fit in int because it's not more
145+
* than MaxAllocSize.)
146+
*/
147+
return (int)nprinted;
156148
}
157149

158150
/*

‎src/backend/utils/error/elog.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -715,13 +715,13 @@ errcode_for_socket_access(void)
715715
for (;;) \
716716
{ \
717717
va_listargs; \
718-
boolsuccess; \
718+
intneeded; \
719719
va_start(args,fmt); \
720-
success=appendStringInfoVA(&buf,fmtbuf,args); \
720+
needed=appendStringInfoVA(&buf,fmtbuf,args); \
721721
va_end(args); \
722-
if (success) \
722+
if (needed==0) \
723723
break; \
724-
enlargeStringInfo(&buf,buf.maxlen); \
724+
enlargeStringInfo(&buf,needed); \
725725
} \
726726
/* Done with expanded fmt */ \
727727
pfree(fmtbuf); \
@@ -758,13 +758,13 @@ errcode_for_socket_access(void)
758758
for (;;) \
759759
{ \
760760
va_listargs; \
761-
boolsuccess; \
761+
intneeded; \
762762
va_start(args,n); \
763-
success=appendStringInfoVA(&buf,fmtbuf,args); \
763+
needed=appendStringInfoVA(&buf,fmtbuf,args); \
764764
va_end(args); \
765-
if (success) \
765+
if (needed==0) \
766766
break; \
767-
enlargeStringInfo(&buf,buf.maxlen); \
767+
enlargeStringInfo(&buf,needed); \
768768
} \
769769
/* Done with expanded fmt */ \
770770
pfree(fmtbuf); \

‎src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,29 +1183,33 @@ archputs(const char *s, Archive *AH)
11831183
int
11841184
archprintf(Archive*AH,constchar*fmt,...)
11851185
{
1186-
char*p=NULL;
1187-
va_listap;
1188-
intbSize=strlen(fmt)+256;
1189-
intcnt=-1;
1186+
char*p;
1187+
size_tlen=128;/* initial assumption about buffer size */
1188+
size_tcnt;
11901189

1191-
/*
1192-
* This is paranoid: deal with the possibility that vsnprintf is willing
1193-
* to ignore trailing null or returns > 0 even if string does not fit. It
1194-
* may be the case that it returns cnt = bufsize
1195-
*/
1196-
while (cnt<0||cnt >= (bSize-1))
1190+
for (;;)
11971191
{
1198-
if (p!=NULL)
1199-
free(p);
1200-
bSize *=2;
1201-
p= (char*)pg_malloc(bSize);
1202-
va_start(ap,fmt);
1203-
cnt=vsnprintf(p,bSize,fmt,ap);
1204-
va_end(ap);
1192+
va_listargs;
1193+
1194+
/* Allocate work buffer. */
1195+
p= (char*)pg_malloc(len);
1196+
1197+
/* Try to format the data. */
1198+
va_start(args,fmt);
1199+
cnt=pvsnprintf(p,len,fmt,args);
1200+
va_end(args);
1201+
1202+
if (cnt<len)
1203+
break;/* success */
1204+
1205+
/* Release buffer and loop around to try again with larger len. */
1206+
free(p);
1207+
len=cnt;
12051208
}
1209+
12061210
WriteData(AH,p,cnt);
12071211
free(p);
1208-
returncnt;
1212+
return(int)cnt;
12091213
}
12101214

12111215

@@ -1312,29 +1316,33 @@ RestoreOutput(ArchiveHandle *AH, OutputContext savedContext)
13121316
int
13131317
ahprintf(ArchiveHandle*AH,constchar*fmt,...)
13141318
{
1315-
char*p=NULL;
1316-
va_listap;
1317-
intbSize=strlen(fmt)+256;/* Usually enough */
1318-
intcnt=-1;
1319+
char*p;
1320+
size_tlen=128;/* initial assumption about buffer size */
1321+
size_tcnt;
13191322

1320-
/*
1321-
* This is paranoid: deal with the possibility that vsnprintf is willing
1322-
* to ignore trailing null or returns > 0 even if string does not fit. It
1323-
* may be the case that it returns cnt = bufsize.
1324-
*/
1325-
while (cnt<0||cnt >= (bSize-1))
1323+
for (;;)
13261324
{
1327-
if (p!=NULL)
1328-
free(p);
1329-
bSize *=2;
1330-
p= (char*)pg_malloc(bSize);
1331-
va_start(ap,fmt);
1332-
cnt=vsnprintf(p,bSize,fmt,ap);
1333-
va_end(ap);
1325+
va_listargs;
1326+
1327+
/* Allocate work buffer. */
1328+
p= (char*)pg_malloc(len);
1329+
1330+
/* Try to format the data. */
1331+
va_start(args,fmt);
1332+
cnt=pvsnprintf(p,len,fmt,args);
1333+
va_end(args);
1334+
1335+
if (cnt<len)
1336+
break;/* success */
1337+
1338+
/* Release buffer and loop around to try again with larger len. */
1339+
free(p);
1340+
len=cnt;
13341341
}
1342+
13351343
ahwrite(p,1,cnt,AH);
13361344
free(p);
1337-
returncnt;
1345+
return(int)cnt;
13381346
}
13391347

13401348
void

‎src/bin/pg_dump/pg_backup_tar.c

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -996,33 +996,33 @@ _EndBlobs(ArchiveHandle *AH, TocEntry *te)
996996
staticint
997997
tarPrintf(ArchiveHandle*AH,TAR_MEMBER*th,constchar*fmt,...)
998998
{
999-
char*p=NULL;
1000-
va_listap;
1001-
size_tbSize=strlen(fmt)+256;/* Should be enough */
1002-
intcnt=-1;
1003-
1004-
/*
1005-
* This is paranoid: deal with the possibility that vsnprintf is willing
1006-
* to ignore trailing null
1007-
*/
999+
char*p;
1000+
size_tlen=128;/* initial assumption about buffer size */
1001+
size_tcnt;
10081002

1009-
/*
1010-
* or returns > 0 even if string does not fit. It may be the case that it
1011-
* returns cnt = bufsize
1012-
*/
1013-
while (cnt<0||cnt >= (bSize-1))
1003+
for (;;)
10141004
{
1015-
if (p!=NULL)
1016-
free(p);
1017-
bSize *=2;
1018-
p= (char*)pg_malloc(bSize);
1019-
va_start(ap,fmt);
1020-
cnt=vsnprintf(p,bSize,fmt,ap);
1021-
va_end(ap);
1005+
va_listargs;
1006+
1007+
/* Allocate work buffer. */
1008+
p= (char*)pg_malloc(len);
1009+
1010+
/* Try to format the data. */
1011+
va_start(args,fmt);
1012+
cnt=pvsnprintf(p,len,fmt,args);
1013+
va_end(args);
1014+
1015+
if (cnt<len)
1016+
break;/* success */
1017+
1018+
/* Release buffer and loop around to try again with larger len. */
1019+
free(p);
1020+
len=cnt;
10221021
}
1022+
10231023
cnt=tarWrite(p,cnt,th);
10241024
free(p);
1025-
returncnt;
1025+
return(int)cnt;
10261026
}
10271027

10281028
bool

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp