Commit 9a932800 authored by Tom Lane's avatar Tom Lane

Make createlang and droplang proof against weird search_path settings

by forcing search_path to be just pg_catalog.
parent 866ffc2f
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* Miscellaneous shared code * common.c
* Common support routines for bin/scripts/
*
* *
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 "postgres_fe.h"
#include "common.h"
#include "libpq-fe.h"
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
#include "common.h"
#ifndef HAVE_INT_OPTRESET
int optreset;
#endif
/* /*
* Returns the current user name. * Returns the current user name.
...@@ -55,7 +61,8 @@ get_user_name(const char *progname) ...@@ -55,7 +61,8 @@ get_user_name(const char *progname)
* options. * options.
*/ */
void 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) if (argc > 1)
{ {
...@@ -79,7 +86,8 @@ handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, hel ...@@ -79,7 +86,8 @@ handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, hel
*/ */
PGconn * PGconn *
connectDatabase(const char *dbname, const char *pghost, const char *pgport, 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; PGconn *conn;
char *password = NULL; char *password = NULL;
...@@ -146,8 +154,10 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo) ...@@ -146,8 +154,10 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
if (!res || if (!res ||
PQresultStatus(res) != PGRES_TUPLES_OK) PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn)); fprintf(stderr, _("%s: query failed: %s"),
fprintf(stderr, _("%s: query was: %s\n"), progname, query); progname, PQerrorMessage(conn));
fprintf(stderr, _("%s: query was: %s\n"),
progname, query);
PQfinish(conn); PQfinish(conn);
exit(1); exit(1);
} }
...@@ -156,6 +166,34 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo) ...@@ -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. * Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
*/ */
......
#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 "libpq-fe.h"
#include "pqexpbuffer.h" #include "pqexpbuffer.h"
#include "getopt_long.h" #include "getopt_long.h"
#ifndef HAVE_INT_OPTRESET #ifndef HAVE_INT_OPTRESET
int optreset; extern int optreset;
#endif #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, extern PGconn *connectDatabase(const char *dbname, const char *pghost,
const char *pguser, bool require_password, const char *progname); const char *pgport, const char *pguser,
bool require_password, const char *progname);
PGresult * extern PGresult *executeQuery(PGconn *conn, const char *query,
executeQuery(PGconn *conn, const char *command, const char *progname, bool echo); const char *progname, bool echo);
int extern void executeCommand(PGconn *conn, const char *query,
check_yesno_response(const char *string); const char *progname, bool echo);
extern int check_yesno_response(const char *string);
#endif /* COMMON_H */
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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[]) ...@@ -138,11 +138,12 @@ main(int argc, char *argv[])
{ {
printQueryOpt popt; 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 " printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
"THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language " "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
"WHERE lanispl IS TRUE;", "FROM pg_catalog.pg_language WHERE lanispl;",
_("Name"), _("yes"), _("no"), _("Trusted?")); _("Name"), _("yes"), _("no"), _("Trusted?"));
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
...@@ -221,6 +222,13 @@ main(int argc, char *argv[]) ...@@ -221,6 +222,13 @@ main(int argc, char *argv[])
conn = connectDatabase(dbname, host, port, username, password, progname); 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 * Make sure the language isn't already installed
*/ */
...@@ -232,8 +240,7 @@ main(int argc, char *argv[]) ...@@ -232,8 +240,7 @@ main(int argc, char *argv[])
{ {
PQfinish(conn); PQfinish(conn);
fprintf(stderr, fprintf(stderr,
_("%s: language \"%s\" is already installed in " _("%s: language \"%s\" is already installed in database \"%s\"\n"),
"database \"%s\"\n"),
progname, langname, dbname); progname, langname, dbname);
/* separate exit status for "already installed" */ /* separate exit status for "already installed" */
exit(2); exit(2);
...@@ -244,7 +251,8 @@ main(int argc, char *argv[]) ...@@ -244,7 +251,8 @@ main(int argc, char *argv[])
* Check whether the call handler exists * Check whether the call handler exists
*/ */
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' " 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); "AND pronargs = 0;", handler);
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
handlerexists = (PQntuples(result) > 0); handlerexists = (PQntuples(result) > 0);
...@@ -255,9 +263,10 @@ main(int argc, char *argv[]) ...@@ -255,9 +263,10 @@ main(int argc, char *argv[])
*/ */
if (validator) if (validator)
{ {
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s'" printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
" AND proargtypes[0] = 'pg_catalog.oid'::regtype " "AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
" AND pronargs = 1;", validator); "AND proargtypes[0] = 'oid'::regtype "
"AND pronargs = 1;", validator);
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
validatorexists = (PQntuples(result) > 0); validatorexists = (PQntuples(result) > 0);
PQclear(result); PQclear(result);
...@@ -267,27 +276,30 @@ main(int argc, char *argv[]) ...@@ -267,27 +276,30 @@ main(int argc, char *argv[])
/* /*
* Create the function(s) and the language * 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); resetPQExpBuffer(&sql);
if (!handlerexists) if (!handlerexists)
appendPQExpBuffer(&sql, appendPQExpBuffer(&sql,
"CREATE FUNCTION pg_catalog.\"%s\" () RETURNS " "CREATE FUNCTION \"%s\" () RETURNS language_handler "
"language_handler AS '%s/%s' LANGUAGE C;\n", "AS '%s/%s' LANGUAGE C;\n",
handler, pglib, object); handler, pglib, object);
if (!validatorexists) if (!validatorexists)
appendPQExpBuffer(&sql, appendPQExpBuffer(&sql,
"CREATE FUNCTION pg_catalog.\"%s\" (oid) RETURNS " "CREATE FUNCTION \"%s\" (oid) RETURNS void "
"void AS '%s/%s' LANGUAGE C;\n", "AS '%s/%s' LANGUAGE C;\n",
validator, pglib, object); validator, pglib, object);
appendPQExpBuffer(&sql, appendPQExpBuffer(&sql,
"CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"", "CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"",
(trusted ? "TRUSTED " : ""), langname, handler); (trusted ? "TRUSTED " : ""), langname, handler);
if (validator) if (validator)
appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator); appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator);
appendPQExpBuffer(&sql, ";\n"); appendPQExpBuffer(&sql, ";\n");
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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[]) ...@@ -140,9 +140,9 @@ main(int argc, char *argv[])
conn = connectDatabase(dbname, host, port, username, password, conn = connectDatabase(dbname, host, port, username, password,
progname); progname);
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE " printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
"WHEN lanpltrusted THEN '%s' ELSE '%s' END) " "(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
"as \"%s\" FROM pg_language WHERE lanispl IS TRUE;", "FROM pg_catalog.pg_language WHERE lanispl;",
_("Name"), _("yes"), _("no"), _("Trusted?")); _("Name"), _("yes"), _("no"), _("Trusted?"));
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
...@@ -172,6 +172,13 @@ main(int argc, char *argv[]) ...@@ -172,6 +172,13 @@ main(int argc, char *argv[])
conn = connectDatabase(dbname, host, port, username, password, progname); 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 * Make sure the language is installed and find the OIDs of the
* handler and validator functions * handler and validator functions
...@@ -248,8 +255,8 @@ main(int argc, char *argv[]) ...@@ -248,8 +255,8 @@ main(int argc, char *argv[])
*/ */
if (OidIsValid(lanvalidator)) if (OidIsValid(lanvalidator))
{ {
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE " printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
"lanvalidator = %u AND lanname <> '%s';", "WHERE lanvalidator = %u AND lanname <> '%s';",
lanvalidator, langname); lanvalidator, langname);
result = executeQuery(conn, sql.data, progname, echo); result = executeQuery(conn, sql.data, progname, echo);
if (strcmp(PQgetvalue(result, 0, 0), "0") == 0) if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)
......
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