Skip to content

Commit ab758ec

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 5e6d561 commit ab758ec

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
@@ -1234,8 +1234,9 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
12341234
}
12351235
else
12361236
{
1237-
text *t;
1237+
const char *name;
12381238
const char *value;
1239+
text *t;
12391240
Size len;
12401241

12411242
/*
@@ -1282,19 +1283,27 @@ transformRelOptions(Datum oldOptions, List *defList, const char *namspace,
12821283
* have just "name", assume "name=true" is meant. Note: the
12831284
* namespace is not output.
12841285
*/
1286+
name = def->defname;
12851287
if (def->arg != NULL)
12861288
value = defGetString(def);
12871289
else
12881290
value = "true";
12891291

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

1307-
len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
1316+
len = VARHDRSZ + strlen(name) + 1 + strlen(value);
13081317
/* +1 leaves room for sprintf's trailing null */
13091318
t = (text *) palloc(len + 1);
13101319
SET_VARSIZE(t, len);
1311-
sprintf(VARDATA(t), "%s=%s", def->defname, value);
1320+
sprintf(VARDATA(t), "%s=%s", name, value);
13121321

13131322
astate = accumArrayResult(astate, PointerGetDatum(t),
13141323
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