Skip to content

Commit 9a93280

Browse files
committed
Make createlang and droplang proof against weird search_path settings
by forcing search_path to be just pg_catalog.
1 parent 866ffc2 commit 9a93280

File tree

4 files changed

+115
-42
lines changed

4 files changed

+115
-42
lines changed

src/bin/scripts/common.c

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
/*-------------------------------------------------------------------------
22
*
3-
* Miscellaneous shared code
3+
* common.c
4+
* Common support routines for bin/scripts/
5+
*
46
*
57
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
68
* Portions Copyright (c) 1994, Regents of the University of California
79
*
8-
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.17 2005/02/22 04:41:30 momjian Exp $
10+
* $PostgreSQL: pgsql/src/bin/scripts/common.c,v 1.18 2005/08/15 21:02:26 tgl Exp $
911
*
1012
*-------------------------------------------------------------------------
1113
*/
1214

1315
#include "postgres_fe.h"
14-
#include "common.h"
15-
#include "libpq-fe.h"
1616

1717
#include <pwd.h>
1818
#include <unistd.h>
1919

20+
#include "common.h"
21+
22+
#ifndef HAVE_INT_OPTRESET
23+
int optreset;
24+
#endif
25+
2026

2127
/*
2228
* Returns the current user name.
@@ -55,7 +61,8 @@ get_user_name(const char *progname)
5561
* options.
5662
*/
5763
void
58-
handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp)
64+
handle_help_version_opts(int argc, char *argv[],
65+
const char *fixed_progname, help_handler hlp)
5966
{
6067
if (argc > 1)
6168
{
@@ -79,7 +86,8 @@ handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, hel
7986
*/
8087
PGconn *
8188
connectDatabase(const char *dbname, const char *pghost, const char *pgport,
82-
const char *pguser, bool require_password, const char *progname)
89+
const char *pguser, bool require_password,
90+
const char *progname)
8391
{
8492
PGconn *conn;
8593
char *password = NULL;
@@ -146,8 +154,10 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
146154
if (!res ||
147155
PQresultStatus(res) != PGRES_TUPLES_OK)
148156
{
149-
fprintf(stderr, _("%s: query failed: %s"), progname, PQerrorMessage(conn));
150-
fprintf(stderr, _("%s: query was: %s\n"), progname, query);
157+
fprintf(stderr, _("%s: query failed: %s"),
158+
progname, PQerrorMessage(conn));
159+
fprintf(stderr, _("%s: query was: %s\n"),
160+
progname, query);
151161
PQfinish(conn);
152162
exit(1);
153163
}
@@ -156,6 +166,34 @@ executeQuery(PGconn *conn, const char *query, const char *progname, bool echo)
156166
}
157167

158168

169+
/*
170+
* As above for a SQL command (which returns nothing).
171+
*/
172+
void
173+
executeCommand(PGconn *conn, const char *query,
174+
const char *progname, bool echo)
175+
{
176+
PGresult *res;
177+
178+
if (echo)
179+
printf("%s\n", query);
180+
181+
res = PQexec(conn, query);
182+
if (!res ||
183+
PQresultStatus(res) != PGRES_COMMAND_OK)
184+
{
185+
fprintf(stderr, _("%s: query failed: %s"),
186+
progname, PQerrorMessage(conn));
187+
fprintf(stderr, _("%s: query was: %s\n"),
188+
progname, query);
189+
PQfinish(conn);
190+
exit(1);
191+
}
192+
193+
PQclear(res);
194+
}
195+
196+
159197
/*
160198
* Check yes/no answer in a localized way. 1=yes, 0=no, -1=neither.
161199
*/

src/bin/scripts/common.h

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
1-
#include "postgres_fe.h"
1+
/*
2+
* common.h
3+
* Common support routines for bin/scripts/
4+
*
5+
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
6+
*
7+
* $PostgreSQL: pgsql/src/bin/scripts/common.h,v 1.11 2005/08/15 21:02:26 tgl Exp $
8+
*/
9+
#ifndef COMMON_H
10+
#define COMMON_H
211

312
#include "libpq-fe.h"
413
#include "pqexpbuffer.h"
514
#include "getopt_long.h"
615

716
#ifndef HAVE_INT_OPTRESET
8-
int optreset;
17+
extern int optreset;
918
#endif
1019

11-
const char *get_user_name(const char *progname);
20+
typedef void (*help_handler) (const char *progname);
1221

13-
typedef void (*help_handler) (const char *);
22+
extern const char *get_user_name(const char *progname);
1423

15-
void handle_help_version_opts(int argc, char *argv[], const char *fixed_progname, help_handler hlp);
24+
extern void handle_help_version_opts(int argc, char *argv[],
25+
const char *fixed_progname,
26+
help_handler hlp);
1627

17-
PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
18-
const char *pguser, bool require_password, const char *progname);
28+
extern PGconn *connectDatabase(const char *dbname, const char *pghost,
29+
const char *pgport, const char *pguser,
30+
bool require_password, const char *progname);
1931

20-
PGresult *
21-
executeQuery(PGconn *conn, const char *command, const char *progname, bool echo);
32+
extern PGresult *executeQuery(PGconn *conn, const char *query,
33+
const char *progname, bool echo);
2234

23-
int
24-
check_yesno_response(const char *string);
35+
extern void executeCommand(PGconn *conn, const char *query,
36+
const char *progname, bool echo);
37+
38+
extern int check_yesno_response(const char *string);
39+
40+
#endif /* COMMON_H */

src/bin/scripts/createlang.c

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
66
* Portions Copyright (c) 1994, Regents of the University of California
77
*
8-
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.18 2005/07/10 14:26:30 momjian Exp $
8+
* $PostgreSQL: pgsql/src/bin/scripts/createlang.c,v 1.19 2005/08/15 21:02:26 tgl Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -138,11 +138,12 @@ main(int argc, char *argv[])
138138
{
139139
printQueryOpt popt;
140140

141-
conn = connectDatabase(dbname, host, port, username, password, progname);
141+
conn = connectDatabase(dbname, host, port, username, password,
142+
progname);
142143

143-
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE WHEN lanpltrusted "
144-
"THEN '%s' ELSE '%s' END) as \"%s\" FROM pg_language "
145-
"WHERE lanispl IS TRUE;",
144+
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
145+
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
146+
"FROM pg_catalog.pg_language WHERE lanispl;",
146147
_("Name"), _("yes"), _("no"), _("Trusted?"));
147148
result = executeQuery(conn, sql.data, progname, echo);
148149

@@ -221,6 +222,13 @@ main(int argc, char *argv[])
221222

222223
conn = connectDatabase(dbname, host, port, username, password, progname);
223224

225+
/*
226+
* Force schema search path to be just pg_catalog, so that we don't
227+
* have to be paranoid about search paths below.
228+
*/
229+
executeCommand(conn, "SET search_path = pg_catalog;",
230+
progname, echo);
231+
224232
/*
225233
* Make sure the language isn't already installed
226234
*/
@@ -232,8 +240,7 @@ main(int argc, char *argv[])
232240
{
233241
PQfinish(conn);
234242
fprintf(stderr,
235-
_("%s: language \"%s\" is already installed in "
236-
"database \"%s\"\n"),
243+
_("%s: language \"%s\" is already installed in database \"%s\"\n"),
237244
progname, langname, dbname);
238245
/* separate exit status for "already installed" */
239246
exit(2);
@@ -244,7 +251,8 @@ main(int argc, char *argv[])
244251
* Check whether the call handler exists
245252
*/
246253
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
247-
"AND prorettype = 'pg_catalog.language_handler'::regtype "
254+
"AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
255+
"AND prorettype = 'language_handler'::regtype "
248256
"AND pronargs = 0;", handler);
249257
result = executeQuery(conn, sql.data, progname, echo);
250258
handlerexists = (PQntuples(result) > 0);
@@ -255,9 +263,10 @@ main(int argc, char *argv[])
255263
*/
256264
if (validator)
257265
{
258-
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s'"
259-
" AND proargtypes[0] = 'pg_catalog.oid'::regtype "
260-
" AND pronargs = 1;", validator);
266+
printfPQExpBuffer(&sql, "SELECT oid FROM pg_proc WHERE proname = '%s' "
267+
"AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') "
268+
"AND proargtypes[0] = 'oid'::regtype "
269+
"AND pronargs = 1;", validator);
261270
result = executeQuery(conn, sql.data, progname, echo);
262271
validatorexists = (PQntuples(result) > 0);
263272
PQclear(result);
@@ -267,27 +276,30 @@ main(int argc, char *argv[])
267276

268277
/*
269278
* Create the function(s) and the language
279+
*
280+
* NOTE: the functions will be created in pg_catalog because
281+
* of our previous "SET search_path".
270282
*/
271283
resetPQExpBuffer(&sql);
272284

273285
if (!handlerexists)
274286
appendPQExpBuffer(&sql,
275-
"CREATE FUNCTION pg_catalog.\"%s\" () RETURNS "
276-
"language_handler AS '%s/%s' LANGUAGE C;\n",
287+
"CREATE FUNCTION \"%s\" () RETURNS language_handler "
288+
"AS '%s/%s' LANGUAGE C;\n",
277289
handler, pglib, object);
278290

279291
if (!validatorexists)
280292
appendPQExpBuffer(&sql,
281-
"CREATE FUNCTION pg_catalog.\"%s\" (oid) RETURNS "
282-
"void AS '%s/%s' LANGUAGE C;\n",
293+
"CREATE FUNCTION \"%s\" (oid) RETURNS void "
294+
"AS '%s/%s' LANGUAGE C;\n",
283295
validator, pglib, object);
284296

285297
appendPQExpBuffer(&sql,
286-
"CREATE %sLANGUAGE \"%s\" HANDLER pg_catalog.\"%s\"",
298+
"CREATE %sLANGUAGE \"%s\" HANDLER \"%s\"",
287299
(trusted ? "TRUSTED " : ""), langname, handler);
288300

289301
if (validator)
290-
appendPQExpBuffer(&sql, " VALIDATOR pg_catalog.\"%s\"", validator);
302+
appendPQExpBuffer(&sql, " VALIDATOR \"%s\"", validator);
291303

292304
appendPQExpBuffer(&sql, ";\n");
293305

src/bin/scripts/droplang.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
66
* Portions Copyright (c) 1994, Regents of the University of California
77
*
8-
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.16 2005/07/10 14:26:30 momjian Exp $
8+
* $PostgreSQL: pgsql/src/bin/scripts/droplang.c,v 1.17 2005/08/15 21:02:26 tgl Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -140,9 +140,9 @@ main(int argc, char *argv[])
140140
conn = connectDatabase(dbname, host, port, username, password,
141141
progname);
142142

143-
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", (CASE "
144-
"WHEN lanpltrusted THEN '%s' ELSE '%s' END) "
145-
"as \"%s\" FROM pg_language WHERE lanispl IS TRUE;",
143+
printfPQExpBuffer(&sql, "SELECT lanname as \"%s\", "
144+
"(CASE WHEN lanpltrusted THEN '%s' ELSE '%s' END) as \"%s\" "
145+
"FROM pg_catalog.pg_language WHERE lanispl;",
146146
_("Name"), _("yes"), _("no"), _("Trusted?"));
147147
result = executeQuery(conn, sql.data, progname, echo);
148148

@@ -172,6 +172,13 @@ main(int argc, char *argv[])
172172

173173
conn = connectDatabase(dbname, host, port, username, password, progname);
174174

175+
/*
176+
* Force schema search path to be just pg_catalog, so that we don't
177+
* have to be paranoid about search paths below.
178+
*/
179+
executeCommand(conn, "SET search_path = pg_catalog;",
180+
progname, echo);
181+
175182
/*
176183
* Make sure the language is installed and find the OIDs of the
177184
* handler and validator functions
@@ -248,8 +255,8 @@ main(int argc, char *argv[])
248255
*/
249256
if (OidIsValid(lanvalidator))
250257
{
251-
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language WHERE "
252-
"lanvalidator = %u AND lanname <> '%s';",
258+
printfPQExpBuffer(&sql, "SELECT count(*) FROM pg_language "
259+
"WHERE lanvalidator = %u AND lanname <> '%s';",
253260
lanvalidator, langname);
254261
result = executeQuery(conn, sql.data, progname, echo);
255262
if (strcmp(PQgetvalue(result, 0, 0), "0") == 0)

0 commit comments

Comments
 (0)