Make createlang and droplang proof against weird search_path settings

by forcing search_path to be just pg_catalog.
This commit is contained in:
Tom Lane 2005-08-15 21:02:26 +00:00
parent 866ffc2fe3
commit 9a9328003d
4 changed files with 115 additions and 42 deletions

View File

@ -1,22 +1,28 @@
/*-------------------------------------------------------------------------
*
* Miscellaneous shared code
* common.c
* Common support routines for bin/scripts/
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.17 2005/02/22 04:41:30 momjian Exp $
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.18 2005/08/15 21:02:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres_fe.h"
#include "common.h"
#include "libpq-fe.h"
#include <pwd.h>
#include <unistd.h>
#include "common.h"
#ifndef HAVE_INT_OPTRESET
int optreset;
#endif
/*
* Returns the current user name.
@ -55,7 +61,8 @@ get_user_name(const char *progname)
* options.
*/
void
handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
handle_help_version_opts(int argc, char *argv[],
const char *fixed_progname, help_handler hlp)
{
if (argc > 1)
{
@ -79,7 +86,8 @@ handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, hel
*/
PGconn *
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
const char *pguser, bool require_password, const char *progname)
const char *pguser, bool require_password,
const char *progname)
{
PGconn *conn;
char *password = NULL;
@ -146,8 +154,10 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
fprintf(stderr, _("%s: query was: %s\n"), progname, query);
fprintf(stderr, _("%s: query failed: %s"),
progname, PQerrorMessage(conn));
fprintf(stderr, _("%s: query was: %s\n"),
progname, query);
PQfinish(conn);
exit(1);
}
@ -156,6 +166,34 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
}
/*
* As above for a SQL command (which returns nothing).
*/
void
executeCommand(PGconn *conn, const char *query,
const char *progname, bool echo)
{
PGresult *res;
if (echo)
printf("%s\n", query);
res = PQexec(conn, query);
if (!res ||
PQresultStatus(res) != PGRES_COMMAND_OK)
{
fprintf(stderr, _("%s: query failed: %s"),
progname, PQerrorMessage(conn));
fprintf(stderr, _("%s: query was: %s\n"),
progname, query);
PQfinish(conn);
exit(1);
}
PQclear(res);
}
/*
* Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
*/

View File

@ -1,24 +1,40 @@
#include "postgres_fe.h"
/*
* common.h
* Common support routines for bin/scripts/
*
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/scripts/common.h,v 1.11 2005/08/15 21:02:26 tgl Exp $
*/
#ifndef COMMON_H
#define COMMON_H
#include "libpq-fe.h"
#include "pqexpbuffer.h"
#include "getopt_long.h"
#ifndef HAVE_INT_OPTRESET
int optreset;
extern int optreset;
#endif
const char *get_user_name(const char *progname);
typedef void (*help_handler) (const char *progname);
typedef void (*help_handler) (const char *);
extern const char *get_user_name(const char *progname);
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp);
extern void handle_help_version_opts(int argc, char *argv[],
const char *fixed_progname,
help_handler hlp);
PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
const char *pguser, bool require_password, const char *progname);
extern PGconn *connectDatabase(const char *dbname, const char *pghost,
const char *pgport, const char *pguser,
bool require_password, const char *progname);
PGresult *
executeQuery(PGconn *conn, const char *command, const char *progname, bool echo);
extern PGresult *executeQuery(PGconn *conn, const char *query,
const char *progname, bool echo);
int
check_yesno_response(const char *string);
extern void executeCommand(PGconn *conn, const char *query,
const char *progname, bool echo);
extern int check_yesno_response(const char *string);
#endif /* COMMON_H */

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.18 2005/07/10 14:26:30 momjian Exp $
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.19 2005/08/15 21:02:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -138,11 +138,12 @@ main(int argc, char *argv[])
{
printQueryOpt popt;
conn = connectDatabase(dbname, host, port, username, password, progname);
conn = connectDatabase(dbname, host, port, username, password,
progname);
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE WHEN lanpltrusted "
"THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language "
"WHERE lanispl IS TRUE;",
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
"FROM pg_catalog.pg_language WHERE lanispl;",
_("Name"), _("yes"), _("no"), _("Trusted?"));
result = executeQuery(conn, sql.data, progname, echo);
@ -221,6 +222,13 @@ main(int argc, char *argv[])
conn = connectDatabase(dbname, host, port, username, password, progname);
/*
* Force schema search path to be just pg_catalog, so that we don't
* have to be paranoid about search paths below.
*/
executeCommand(conn, "SET search_path = pg_catalog;",
progname, echo);
/*
* Make sure the language isn't already installed
*/
@ -232,8 +240,7 @@ main(int argc, char *argv[])
{
PQfinish(conn);
fprintf(stderr,
_("%s: language \"%s\" is already installed in "
"database \"%s\"\n"),
_("%s: language \"%s\" is already installed in database \"%s\"\n"),
progname, langname, dbname);
/* separate exit status for "already installed" */
exit(2);
@ -244,7 +251,8 @@ main(int argc, char *argv[])
* Check whether the call handler exists
*/
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
"AND prorettype = 'pg_catalog.language_handler'::regtype "
"AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
"AND prorettype = 'language_handler'::regtype "
"AND pronargs = 0;", handler);
result = executeQuery(conn, sql.data, progname, echo);
handlerexists = (PQntuples(result) > 0);
@ -255,9 +263,10 @@ main(int argc, char *argv[])
*/
if (validator)
{
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s'"
" AND proargtypes[0] = 'pg_catalog.oid'::regtype "
" AND pronargs = 1;", validator);
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
"AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
"AND proargtypes[0] = 'oid'::regtype "
"AND pronargs = 1;", validator);
result = executeQuery(conn, sql.data, progname, echo);
validatorexists = (PQntuples(result) > 0);
PQclear(result);
@ -267,27 +276,30 @@ main(int argc, char *argv[])
/*
* Create the function(s) and the language
*
* NOTE: the functions will be created in pg_catalog because
* of our previous "SET search_path".
*/
resetPQExpBuffer(&sql);
if (!handlerexists)
appendPQExpBuffer(&sql,
"CREATE FUNCTION pg_catalog.\"%s\" () RETURNS "
"language_handler AS '%s/%s' LANGUAGE C;\n",
"CREATE FUNCTION \"%s\" () RETURNS language_handler "
"AS '%s/%s' LANGUAGE C;\n",
handler, pglib, object);
if (!validatorexists)
appendPQExpBuffer(&sql,
"CREATE FUNCTION pg_catalog.\"%s\" (oid) RETURNS "
"void AS '%s/%s' LANGUAGE C;\n",
"CREATE FUNCTION \"%s\" (oid) RETURNS void "
"AS '%s/%s' LANGUAGE C;\n",
validator, pglib, object);
appendPQExpBuffer(&sql,
"CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"",
"CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"",
(trusted ? "TRUSTED " : ""), langname, handler);
if (validator)
appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator);
appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator);
appendPQExpBuffer(&sql, ";\n");

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.16 2005/07/10 14:26:30 momjian Exp $
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.17 2005/08/15 21:02:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -140,9 +140,9 @@ main(int argc, char *argv[])
conn = connectDatabase(dbname, host, port, username, password,
progname);
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE "
"WHEN lanpltrusted THEN '%s' ELSE '%s' END) "
"as \"%s\" FROM pg_language WHERE lanispl IS TRUE;",
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
"FROM pg_catalog.pg_language WHERE lanispl;",
_("Name"), _("yes"), _("no"), _("Trusted?"));
result = executeQuery(conn, sql.data, progname, echo);
@ -172,6 +172,13 @@ main(int argc, char *argv[])
conn = connectDatabase(dbname, host, port, username, password, progname);
/*
* Force schema search path to be just pg_catalog, so that we don't
* have to be paranoid about search paths below.
*/
executeCommand(conn, "SET search_path = pg_catalog;",
progname, echo);
/*
* Make sure the language is installed and find the OIDs of the
* handler and validator functions
@ -248,8 +255,8 @@ main(int argc, char *argv[])
*/
if (OidIsValid(lanvalidator))
{
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE "
"lanvalidator = %u AND lanname <> '%s';",
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
"WHERE lanvalidator = %u AND lanname <> '%s';",
lanvalidator, langname);
result = executeQuery(conn, sql.data, progname, echo);
if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)