Skip to content

Commit d404612

Browse files
committed
Disallow "=" in names of reloptions and foreign-data options.
We store values for these options as array elements with the syntax "name=value", hence a name containing "=" confuses matters when it's time to read the array back in. Since validation of the options is often done (long) after this conversion to array format, that leads to confusing and off-point error messages. We can improve matters by rejecting names containing "=" up-front. (Probably a better design would have involved pairs of array elements, but it's too late now --- and anyway, there's no evident use-case for option names like this. We already reject such names in some other contexts such as GUCs.) Reported-by: Chapman Flack <jcflack@acm.org> Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Chapman Flack <jcflack@acm.org> Discussion: https://postgr.es/m/6830EB30.8090904@acm.org Backpatch-through: 13
1 parent 87be749 commit d404612

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed

contrib/file_fdw/expected/file_fdw.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ SET ROLE regress_file_fdw_superuser;
4848
CREATE USER MAPPING FOR regress_file_fdw_superuser SERVER file_server;
4949
CREATE USER MAPPING FOR regress_no_priv_user SERVER file_server;
5050
-- validator tests
51+
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (foo 'bar'); -- ERROR
52+
ERROR: invalid option "foo"
53+
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS ("a=b" 'true'); -- ERROR
54+
ERROR: invalid option name "a=b": must not contain "="
5155
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'xml'); -- ERROR
5256
ERROR: COPY format "xml" not recognized
5357
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', quote ':'); -- ERROR

contrib/file_fdw/sql/file_fdw.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ CREATE USER MAPPING FOR regress_file_fdw_superuser SERVER file_server;
5555
CREATE USER MAPPING FOR regress_no_priv_user SERVER file_server;
5656

5757
-- validator tests
58+
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (foo 'bar'); -- ERROR
59+
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS ("a=b" 'true'); -- ERROR
5860
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'xml'); -- ERROR
5961
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', quote ':'); -- ERROR
6062
CREATE FOREIGN TABLE tbl () SERVER file_server OPTIONS (format 'text', escape ':'); -- ERROR

src/backend/access/common/reloptions.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,8 +1232,9 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
12321232
}
12331233
else
12341234
{
1235-
text *t;
1235+
const char *name;
12361236
const char *value;
1237+
text *t;
12371238
Size len;
12381239

12391240
/*
@@ -1280,19 +1281,27 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
12801281
* have just "name", assume "name=true" is meant. Note: the
12811282
* namespace is not output.
12821283
*/
1284+
name = def->defname;
12831285
if (def->arg != NULL)
12841286
value = defGetString(def);
12851287
else
12861288
value = "true";
12871289

1290+
/* Insist that name not contain "=", else "a=b=c" is ambiguous */
1291+
if (strchr(name, '=') != NULL)
1292+
ereport(ERROR,
1293+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1294+
errmsg("invalid option name \"%s\": must not contain \"=\"",
1295+
name)));
1296+
12881297
/*
12891298
* This is not a great place for this test, but there's no other
12901299
* convenient place to filter the option out. As WITH (oids =
12911300
* false) will be removed someday, this seems like an acceptable
12921301
* amount of ugly.
12931302
*/
12941303
if (acceptOidsOff && def->defnamespace == NULL &&
1295-
strcmp(def->defname, "oids") == 0)
1304+
strcmp(name, "oids") == 0)
12961305
{
12971306
if (defGetBoolean(def))
12981307
ereport(ERROR,
@@ -1302,11 +1311,11 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
13021311
continue;
13031312
}
13041313

1305-
len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
1314+
len = VARHDRSZ + strlen(name) + 1 + strlen(value);
13061315
/* +1 leaves room for sprintf's trailing null */
13071316
t = (text *) palloc(len + 1);
13081317
SET_VARSIZE(t, len);
1309-
sprintf(VARDATA(t), "%s=%s", def->defname, value);
1318+
sprintf(VARDATA(t), "%s=%s", name, value);
13101319

13111320
astate = accumArrayResult(astate, PointerGetDatum(t),
13121321
false, TEXTOID,

src/backend/commands/foreigncmds.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,26 @@ optionListToArray(List *options)
7171
foreach(cell, options)
7272
{
7373
DefElem *def = lfirst(cell);
74+
const char *name;
7475
const char *value;
7576
Size len;
7677
text *t;
7778

79+
name = def->defname;
7880
value = defGetString(def);
79-
len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
81+
82+
/* Insist that name not contain "=", else "a=b=c" is ambiguous */
83+
if (strchr(name, '=') != NULL)
84+
ereport(ERROR,
85+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
86+
errmsg("invalid option name \"%s\": must not contain \"=\"",
87+
name)));
88+
89+
len = VARHDRSZ + strlen(name) + 1 + strlen(value);
90+
/* +1 leaves room for sprintf's trailing null */
8091
t = palloc(len + 1);
8192
SET_VARSIZE(t, len);
82-
sprintf(VARDATA(t), "%s=%s", def->defname, value);
93+
sprintf(VARDATA(t), "%s=%s", name, value);
8394

8495
astate = accumArrayResult(astate, PointerGetDatum(t),
8596
false, TEXTOID,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy