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

Commit54cd4f0

Browse files
committed
Work around a subtle portability problem in use of printf %s format.
Depending on which spec you read, field widths and precisions in %s may becounted either in bytes or characters. Our code was assuming bytes, whichis wrong at least for glibc's implementation, and in any case libc mighthave a different idea of the prevailing encoding than we do. Hence, forportable results we must avoid using anything more complex than just "%s"unless the string to be printed is known to be all-ASCII.This patch fixes the cases I could find, including the psql formattingfailure reported by Hernan Gonzalez. In HEAD only, I also added commentsto some places where it appears safe to continue using "%.*s".
1 parent71a185a commit54cd4f0

File tree

11 files changed

+111
-31
lines changed

11 files changed

+111
-31
lines changed

‎src/backend/lib/stringinfo.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
12-
* $PostgreSQL: pgsql/src/backend/lib/stringinfo.c,v 1.52 2010/01/02 16:57:45 momjian Exp $
12+
* $PostgreSQL: pgsql/src/backend/lib/stringinfo.c,v 1.53 2010/05/08 16:39:49 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -226,7 +226,8 @@ appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
226226

227227
/*
228228
* Keep a trailing null in place, even though it's probably useless for
229-
* binary data...
229+
* binary data. (Some callers are dealing with text but call this
230+
* because their input isn't null-terminated.)
230231
*/
231232
str->data[str->len]='\0';
232233
}

‎src/backend/parser/scansup.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/parser/scansup.c,v 1.39 2010/01/02 16:57:50 momjian Exp $
12+
* $PostgreSQL: pgsql/src/backend/parser/scansup.c,v 1.40 2010/05/08 16:39:49 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -176,10 +176,20 @@ truncate_identifier(char *ident, int len, bool warn)
176176
{
177177
len=pg_mbcliplen(ident,len,NAMEDATALEN-1);
178178
if (warn)
179+
{
180+
/*
181+
* Cannot use %.*s here because some machines interpret %s's
182+
* precision in characters, others in bytes.
183+
*/
184+
charbuf[NAMEDATALEN];
185+
186+
memcpy(buf,ident,len);
187+
buf[len]='\0';
179188
ereport(NOTICE,
180189
(errcode(ERRCODE_NAME_TOO_LONG),
181-
errmsg("identifier \"%s\" will be truncated to \"%.*s\"",
182-
ident,len,ident)));
190+
errmsg("identifier \"%s\" will be truncated to \"%s\"",
191+
ident,buf)));
192+
}
183193
ident[len]='\0';
184194
}
185195
}

‎src/backend/tsearch/wparser_def.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/tsearch/wparser_def.c,v 1.30 2010/04/28 02:04:16 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/tsearch/wparser_def.c,v 1.31 2010/05/08 16:39:49 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -322,6 +322,12 @@ TParserInit(char *str, int len)
322322
prs->state->state=TPS_Base;
323323

324324
#ifdefWPARSER_TRACE
325+
/*
326+
* Use of %.*s here is not portable when the string contains multibyte
327+
* characters: some machines interpret the length in characters, others
328+
* in bytes. Since it's only a debugging aid, we haven't bothered to
329+
* fix this.
330+
*/
325331
fprintf(stderr,"parsing \"%.*s\"\n",len,str);
326332
#endif
327333

@@ -361,6 +367,7 @@ TParserCopyInit(const TParser *orig)
361367
prs->state->state=TPS_Base;
362368

363369
#ifdefWPARSER_TRACE
370+
/* See note above about %.*s */
364371
fprintf(stderr,"parsing copy of \"%.*s\"\n",prs->lenstr,prs->str);
365372
#endif
366373

‎src/backend/utils/adt/datetime.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.210 2010/01/02 16:57:53 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.211 2010/05/08 16:39:51 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -3740,6 +3740,14 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
37403740

37413741
AppendTimestampSeconds(str+strlen(str),tm,fsec);
37423742

3743+
/*
3744+
* Note: the uses of %.*s in this function would be unportable
3745+
* if the timezone names ever contain non-ASCII characters,
3746+
* since some platforms think the string length is measured
3747+
* in characters not bytes. However, all TZ abbreviations in
3748+
* the Olson database are plain ASCII.
3749+
*/
3750+
37433751
if (tzp!=NULL&&tm->tm_isdst >=0)
37443752
{
37453753
if (*tzn!=NULL)
@@ -4091,6 +4099,7 @@ CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
40914099
{
40924100
if (strncmp(base[i-1].token,base[i].token,TOKMAXLEN) >=0)
40934101
{
4102+
/* %.*s is safe since all our tokens are ASCII */
40944103
elog(LOG,"ordering error in %s table: \"%.*s\" >= \"%.*s\"",
40954104
tablename,
40964105
TOKMAXLEN,base[i-1].token,

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
*
4343
*
4444
* IDENTIFICATION
45-
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.223 2010/02/26 02:01:12 momjian Exp $
45+
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.224 2010/05/08 16:39:51 tgl Exp $
4646
*
4747
*-------------------------------------------------------------------------
4848
*/
@@ -1871,7 +1871,7 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
18711871
intdisplen;
18721872

18731873
psdisp=get_ps_display(&displen);
1874-
appendStringInfo(buf,"%.*s",displen,psdisp);
1874+
appendBinaryStringInfo(buf,psdisp,displen);
18751875
}
18761876
break;
18771877
case'r':
@@ -2029,7 +2029,7 @@ write_csvlog(ErrorData *edata)
20292029
initStringInfo(&msgbuf);
20302030

20312031
psdisp=get_ps_display(&displen);
2032-
appendStringInfo(&msgbuf,"%.*s",displen,psdisp);
2032+
appendBinaryStringInfo(&msgbuf,psdisp,displen);
20332033
appendCSVLiteral(&buf,msgbuf.data);
20342034

20352035
pfree(msgbuf.data);

‎src/bin/psql/command.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.218 2010/04/03 20:55:57 tgl Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.219 2010/05/08 16:39:51 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99
#include"command.h"
@@ -651,6 +651,13 @@ exec_command(const char *cmd,
651651
{
652652
char*opt=psql_scan_slash_option(scan_state,
653653
OT_WHOLE_LINE,NULL, false);
654+
size_tlen;
655+
656+
/* strip any trailing spaces and semicolons */
657+
len=strlen(opt);
658+
while (len>0&&
659+
(isspace((unsignedchar)opt[len-1])||opt[len-1]==';'))
660+
opt[--len]='\0';
654661

655662
helpSQL(opt,pset.popt.topt.pager);
656663
free(opt);

‎src/bin/psql/help.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.157 2010/03/07 17:02:34 mha Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.158 2010/05/08 16:39:51 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99

@@ -284,6 +284,7 @@ slashUsage(unsigned short int pager)
284284
/*
285285
* helpSQL -- help with SQL commands
286286
*
287+
* Note: we assume caller removed any trailing spaces in "topic".
287288
*/
288289
void
289290
helpSQL(constchar*topic,unsigned shortintpager)
@@ -352,17 +353,16 @@ helpSQL(const char *topic, unsigned short int pager)
352353
wordlen;
353354
intnl_count=0;
354355

355-
/* User gets two chances: exact match, then the first word */
356-
357-
/* First pass : strip trailing spaces and semicolons */
356+
/*
357+
* We first try exact match, then first + second words, then first
358+
* word only.
359+
*/
358360
len=strlen(topic);
359-
while (topic[len-1]==' '||topic[len-1]==';')
360-
len--;
361361

362-
for (x=1;x <=3;x++)/* Three chances to guess that word... */
362+
for (x=1;x <=3;x++)
363363
{
364364
if (x>1)/* Nothing on first pass - try the opening
365-
*words */
365+
*word(s) */
366366
{
367367
wordlen=j=1;
368368
while (topic[j]!=' '&&j++<len)
@@ -423,7 +423,7 @@ helpSQL(const char *topic, unsigned short int pager)
423423
}
424424

425425
if (!help_found)
426-
fprintf(output,_("No help available for \"%-.*s\".\nTry \\h with no arguments to see available help.\n"), (int)len,topic);
426+
fprintf(output,_("No help available for \"%s\".\nTry \\h with no arguments to see available help.\n"),topic);
427427

428428
/* Only close if we used the pager */
429429
if (output!=stdout)

‎src/bin/psql/print.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.124 2010/03/01 21:27:26 heikki Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.125 2010/05/08 16:39:52 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99

@@ -252,6 +252,20 @@ format_numeric_locale(const char *my_str)
252252
}
253253

254254

255+
/*
256+
* fputnbytes: print exactly N bytes to a file
257+
*
258+
* Think not to use fprintf with a %.*s format for this. Some machines
259+
* believe %s's precision is measured in characters, others in bytes.
260+
*/
261+
staticvoid
262+
fputnbytes(FILE*f,constchar*str,size_tn)
263+
{
264+
while (n-->0)
265+
fputc(*str++,f);
266+
}
267+
268+
255269
/*************************/
256270
/* Unaligned text */
257271
/*************************/
@@ -913,14 +927,16 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
913927
{
914928
/* spaces first */
915929
fprintf(fout,"%*s",width_wrap[j]-chars_to_output,"");
916-
fprintf(fout,"%.*s",bytes_to_output,
917-
this_line->ptr+bytes_output[j]);
930+
fputnbytes(fout,
931+
this_line->ptr+bytes_output[j],
932+
bytes_to_output);
918933
}
919934
else/* Left aligned cell */
920935
{
921936
/* spaces second */
922-
fprintf(fout,"%.*s",bytes_to_output,
923-
this_line->ptr+bytes_output[j]);
937+
fputnbytes(fout,
938+
this_line->ptr+bytes_output[j],
939+
bytes_to_output);
924940
}
925941

926942
bytes_output[j]+=bytes_to_output;

‎src/interfaces/ecpg/ecpglib/error.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.25 2010/03/0812:15:24 meskes Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.26 2010/05/0816:39:52 tgl Exp $ */
22

33
#definePOSTGRES_ECPG_INTERNAL
44
#include"postgres_fe.h"
@@ -332,6 +332,7 @@ ecpg_raise_backend(int line, PGresult *result, PGconn *conn, int compat)
332332
else
333333
sqlca->sqlcode=ECPG_PGSQL;
334334

335+
/* %.*s is safe here as long as sqlstate is all-ASCII */
335336
ecpg_log("raising sqlstate %.*s (sqlcode %d): %s\n",
336337
sizeof(sqlca->sqlstate),sqlca->sqlstate,sqlca->sqlcode,sqlca->sqlerrm.sqlerrmc);
337338

‎src/interfaces/ecpg/pgtypeslib/dt_common.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.51 2009/06/11 14:49:13 momjian Exp $ */
1+
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.52 2010/05/08 16:39:52 tgl Exp $ */
22

33
#include"postgres_fe.h"
44

@@ -855,6 +855,14 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
855855
if (tm->tm_year <=0)
856856
sprintf(str+strlen(str)," BC");
857857

858+
/*
859+
* Note: the uses of %.*s in this function would be unportable
860+
* if the timezone names ever contain non-ASCII characters,
861+
* since some platforms think the string length is measured
862+
* in characters not bytes. However, all TZ abbreviations in
863+
* the Olson database are plain ASCII.
864+
*/
865+
858866
if (tzp!=NULL&&tm->tm_isdst >=0)
859867
{
860868
if (*tzn!=NULL)

‎src/interfaces/libpq/fe-misc.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* Portions Copyright (c) 1994, Regents of the University of California
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.141 2010/01/02 16:58:12 momjian Exp $
26+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.142 2010/05/08 16:39:53 tgl Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/
@@ -67,6 +67,20 @@ static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
6767
staticintpqSocketPoll(intsock,intforRead,intforWrite,time_tend_time);
6868

6969

70+
/*
71+
* fputnbytes: print exactly N bytes to a file
72+
*
73+
* Think not to use fprintf with a %.*s format for this. Some machines
74+
* believe %s's precision is measured in characters, others in bytes.
75+
*/
76+
staticvoid
77+
fputnbytes(FILE*f,constchar*str,size_tn)
78+
{
79+
while (n-->0)
80+
fputc(*str++,f);
81+
}
82+
83+
7084
/*
7185
* pqGetc: get 1 character from the connection
7286
*
@@ -187,8 +201,11 @@ pqGetnchar(char *s, size_t len, PGconn *conn)
187201
conn->inCursor+=len;
188202

189203
if (conn->Pfdebug)
190-
fprintf(conn->Pfdebug,"From backend (%lu)> %.*s\n",
191-
(unsigned long)len, (int)len,s);
204+
{
205+
fprintf(conn->Pfdebug,"From backend (%lu)> ", (unsigned long)len);
206+
fputnbytes(conn->Pfdebug,s,len);
207+
fprintf(conn->Pfdebug,"\n");
208+
}
192209

193210
return0;
194211
}
@@ -204,7 +221,11 @@ pqPutnchar(const char *s, size_t len, PGconn *conn)
204221
returnEOF;
205222

206223
if (conn->Pfdebug)
207-
fprintf(conn->Pfdebug,"To backend> %.*s\n", (int)len,s);
224+
{
225+
fprintf(conn->Pfdebug,"To backend> ");
226+
fputnbytes(conn->Pfdebug,s,len);
227+
fprintf(conn->Pfdebug,"\n");
228+
}
208229

209230
return0;
210231
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp