Avoid using NAMEDATALEN in pg_upgrade

Because the client encoding might not match the server encoding,
pg_upgrade can't allocate NAMEDATALEN bytes for storage of database,
relation, and namespace identifiers.  Instead pg_strdup() the memory and
free it.

Also add C comment in initdb.c about safe NAMEDATALEN usage.
This commit is contained in:
Bruce Momjian 2012-12-20 13:56:24 -05:00
parent af275a12df
commit dc9896a245
3 changed files with 27 additions and 17 deletions

View File

@ -23,7 +23,7 @@ static void get_db_infos(ClusterInfo *cluster);
static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo); static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo);
static void free_rel_infos(RelInfoArr *rel_arr); static void free_rel_infos(RelInfoArr *rel_arr);
static void print_db_infos(DbInfoArr *dbinfo); static void print_db_infos(DbInfoArr *dbinfo);
static void print_rel_infos(RelInfoArr *arr); static void print_rel_infos(RelInfoArr *rel_arr);
/* /*
@ -130,8 +130,8 @@ create_rel_filename_map(const char *old_data, const char *new_data,
map->new_relfilenode = new_rel->relfilenode; map->new_relfilenode = new_rel->relfilenode;
/* used only for logging and error reporing, old/new are identical */ /* used only for logging and error reporing, old/new are identical */
snprintf(map->nspname, sizeof(map->nspname), "%s", old_rel->nspname); map->nspname = old_rel->nspname;
snprintf(map->relname, sizeof(map->relname), "%s", old_rel->relname); map->relname = old_rel->relname;
} }
@ -223,8 +223,7 @@ get_db_infos(ClusterInfo *cluster)
for (tupnum = 0; tupnum < ntups; tupnum++) for (tupnum = 0; tupnum < ntups; tupnum++)
{ {
dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid)); dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
snprintf(dbinfos[tupnum].db_name, sizeof(dbinfos[tupnum].db_name), "%s", dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
PQgetvalue(res, tupnum, i_datname));
snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s", snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s",
PQgetvalue(res, tupnum, i_spclocation)); PQgetvalue(res, tupnum, i_spclocation));
} }
@ -349,10 +348,10 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
curr->reloid = atooid(PQgetvalue(res, relnum, i_oid)); curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
nspname = PQgetvalue(res, relnum, i_nspname); nspname = PQgetvalue(res, relnum, i_nspname);
strlcpy(curr->nspname, nspname, sizeof(curr->nspname)); curr->nspname = pg_strdup(nspname);
relname = PQgetvalue(res, relnum, i_relname); relname = PQgetvalue(res, relnum, i_relname);
strlcpy(curr->relname, relname, sizeof(curr->relname)); curr->relname = pg_strdup(relname);
curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode)); curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
@ -380,7 +379,10 @@ free_db_and_rel_infos(DbInfoArr *db_arr)
int dbnum; int dbnum;
for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++) for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
{
free_rel_infos(&db_arr->dbs[dbnum].rel_arr); free_rel_infos(&db_arr->dbs[dbnum].rel_arr);
pg_free(db_arr->dbs[dbnum].db_name);
}
pg_free(db_arr->dbs); pg_free(db_arr->dbs);
db_arr->dbs = NULL; db_arr->dbs = NULL;
db_arr->ndbs = 0; db_arr->ndbs = 0;
@ -390,6 +392,13 @@ free_db_and_rel_infos(DbInfoArr *db_arr)
static void static void
free_rel_infos(RelInfoArr *rel_arr) free_rel_infos(RelInfoArr *rel_arr)
{ {
int relnum;
for (relnum = 0; relnum < rel_arr->nrels; relnum++)
{
pg_free(rel_arr->rels[relnum].nspname);
pg_free(rel_arr->rels[relnum].relname);
}
pg_free(rel_arr->rels); pg_free(rel_arr->rels);
rel_arr->nrels = 0; rel_arr->nrels = 0;
} }
@ -410,12 +419,12 @@ print_db_infos(DbInfoArr *db_arr)
static void static void
print_rel_infos(RelInfoArr *arr) print_rel_infos(RelInfoArr *rel_arr)
{ {
int relnum; int relnum;
for (relnum = 0; relnum < arr->nrels; relnum++) for (relnum = 0; relnum < rel_arr->nrels; relnum++)
pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n", pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n",
arr->rels[relnum].nspname, arr->rels[relnum].relname, rel_arr->rels[relnum].nspname, rel_arr->rels[relnum].relname,
arr->rels[relnum].reloid, arr->rels[relnum].tablespace); rel_arr->rels[relnum].reloid, rel_arr->rels[relnum].tablespace);
} }

View File

@ -114,8 +114,9 @@ extern char *output_files[];
*/ */
typedef struct typedef struct
{ {
char nspname[NAMEDATALEN]; /* namespace name */ /* Can't use NAMEDATALEN; not guaranteed to fit on client */
char relname[NAMEDATALEN]; /* relation name */ char *nspname; /* namespace name */
char *relname; /* relation name */
Oid reloid; /* relation oid */ Oid reloid; /* relation oid */
Oid relfilenode; /* relation relfile node */ Oid relfilenode; /* relation relfile node */
/* relation tablespace path, or "" for the cluster default */ /* relation tablespace path, or "" for the cluster default */
@ -143,8 +144,8 @@ typedef struct
Oid old_relfilenode; Oid old_relfilenode;
Oid new_relfilenode; Oid new_relfilenode;
/* the rest are used only for logging and error reporting */ /* the rest are used only for logging and error reporting */
char nspname[NAMEDATALEN]; /* namespaces */ char *nspname; /* namespaces */
char relname[NAMEDATALEN]; char *relname;
} FileNameMap; } FileNameMap;
/* /*
@ -153,7 +154,7 @@ typedef struct
typedef struct typedef struct
{ {
Oid db_oid; /* oid of the database */ Oid db_oid; /* oid of the database */
char db_name[NAMEDATALEN]; /* database name */ char *db_name; /* database name */
char db_tblspace[MAXPGPATH]; /* database default tablespace path */ char db_tblspace[MAXPGPATH]; /* database default tablespace path */
RelInfoArr rel_arr; /* array of all user relinfos */ RelInfoArr rel_arr; /* array of all user relinfos */
} DbInfo; } DbInfo;

View File

@ -1836,7 +1836,7 @@ setup_collation(void)
#if defined(HAVE_LOCALE_T) && !defined(WIN32) #if defined(HAVE_LOCALE_T) && !defined(WIN32)
int i; int i;
FILE *locale_a_handle; FILE *locale_a_handle;
char localebuf[NAMEDATALEN]; char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
int count = 0; int count = 0;
PG_CMD_DECL; PG_CMD_DECL;