Commit ed437e2b authored by Tom Lane's avatar Tom Lane

Adjust comments about avoiding use of printf's %.*s.

My initial impression that glibc was measuring the precision in characters
(which is what the Linux man page says it does) was incorrect.  It does take
the precision to be in bytes, but it also tries to truncate the string at a
character boundary.  The bottom line remains the same: it will mess up
if the string is not in the encoding it expects, so we need to avoid %.*s
anytime there's a significant risk of that.  Previous code changes are still
good, but adjust the comments to reflect this knowledge.  Per research by
Hernan Gonzalez.
parent 54cd4f04
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/scansup.c,v 1.40 2010/05/08 16:39:49 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/scansup.c,v 1.41 2010/05/09 02:15:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -178,8 +178,8 @@ truncate_identifier(char *ident, int len, bool warn) ...@@ -178,8 +178,8 @@ truncate_identifier(char *ident, int len, bool warn)
if (warn) if (warn)
{ {
/* /*
* Cannot use %.*s here because some machines interpret %s's * We avoid using %.*s here because it can misbehave if the data
* precision in characters, others in bytes. * is not valid in what libc thinks is the prevailing encoding.
*/ */
char buf[NAMEDATALEN]; char buf[NAMEDATALEN];
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tsearch/wparser_def.c,v 1.31 2010/05/08 16:39:49 tgl Exp $ * $PostgreSQL: pgsql/src/backend/tsearch/wparser_def.c,v 1.32 2010/05/09 02:15:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -323,10 +323,9 @@ TParserInit(char *str, int len) ...@@ -323,10 +323,9 @@ TParserInit(char *str, int len)
#ifdef WPARSER_TRACE #ifdef WPARSER_TRACE
/* /*
* Use of %.*s here is not portable when the string contains multibyte * Use of %.*s here is a bit risky since it can misbehave if the data
* characters: some machines interpret the length in characters, others * is not in what libc thinks is the prevailing encoding. However,
* in bytes. Since it's only a debugging aid, we haven't bothered to * since this is just a debugging aid, we choose to live with that.
* fix this.
*/ */
fprintf(stderr, "parsing \"%.*s\"\n", len, str); fprintf(stderr, "parsing \"%.*s\"\n", len, str);
#endif #endif
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.211 2010/05/08 16:39:51 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.212 2010/05/09 02:15:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -3741,11 +3741,9 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, ...@@ -3741,11 +3741,9 @@ EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn, int style,
AppendTimestampSeconds(str + strlen(str), tm, fsec); AppendTimestampSeconds(str + strlen(str), tm, fsec);
/* /*
* Note: the uses of %.*s in this function would be unportable * Note: the uses of %.*s in this function would be risky if the
* if the timezone names ever contain non-ASCII characters, * timezone names ever contain non-ASCII characters. However, all
* since some platforms think the string length is measured * TZ abbreviations in the Olson database are plain ASCII.
* in characters not bytes. However, all TZ abbreviations in
* the Olson database are plain ASCII.
*/ */
if (tzp != NULL && tm->tm_isdst >= 0) if (tzp != NULL && tm->tm_isdst >= 0)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2010, PostgreSQL Global Development Group * Copyright (c) 2000-2010, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.125 2010/05/08 16:39:52 tgl Exp $ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.126 2010/05/09 02:15:59 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -255,8 +255,8 @@ format_numeric_locale(const char *my_str) ...@@ -255,8 +255,8 @@ format_numeric_locale(const char *my_str)
/* /*
* fputnbytes: print exactly N bytes to a file * fputnbytes: print exactly N bytes to a file
* *
* Think not to use fprintf with a %.*s format for this. Some machines * We avoid using %.*s here because it can misbehave if the data
* believe %s's precision is measured in characters, others in bytes. * is not valid in what libc thinks is the prevailing encoding.
*/ */
static void static void
fputnbytes(FILE *f, const char *str, size_t n) fputnbytes(FILE *f, const char *str, size_t n)
......
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.52 2010/05/08 16:39:52 tgl Exp $ */ /* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/dt_common.c,v 1.53 2010/05/09 02:15:59 tgl Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -856,11 +856,9 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha ...@@ -856,11 +856,9 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
sprintf(str + strlen(str), " BC"); sprintf(str + strlen(str), " BC");
/* /*
* Note: the uses of %.*s in this function would be unportable * Note: the uses of %.*s in this function would be risky if the
* if the timezone names ever contain non-ASCII characters, * timezone names ever contain non-ASCII characters. However, all
* since some platforms think the string length is measured * TZ abbreviations in the Olson database are plain ASCII.
* in characters not bytes. However, all TZ abbreviations in
* the Olson database are plain ASCII.
*/ */
if (tzp != NULL && tm->tm_isdst >= 0) if (tzp != NULL && tm->tm_isdst >= 0)
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.142 2010/05/08 16:39:53 tgl Exp $ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-misc.c,v 1.143 2010/05/09 02:16:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -70,8 +70,8 @@ static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time); ...@@ -70,8 +70,8 @@ static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
/* /*
* fputnbytes: print exactly N bytes to a file * fputnbytes: print exactly N bytes to a file
* *
* Think not to use fprintf with a %.*s format for this. Some machines * We avoid using %.*s here because it can misbehave if the data
* believe %s's precision is measured in characters, others in bytes. * is not valid in what libc thinks is the prevailing encoding.
*/ */
static void static void
fputnbytes(FILE *f, const char *str, size_t n) fputnbytes(FILE *f, const char *str, size_t n)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment