diff options
-rw-r--r-- | doc/src/sgml/config.sgml | 31 | ||||
-rw-r--r-- | src/backend/parser/scan.l | 17 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 40 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 5 | ||||
-rw-r--r-- | src/include/parser/gramparse.h | 14 | ||||
-rw-r--r-- | src/include/utils/guc.h | 3 |
6 files changed, 99 insertions, 11 deletions
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index bd4a5e552dc..bd0c8a6dcc9 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.36.2.5 2006/04/18 12:41:29 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.36.2.6 2006/05/21 20:11:02 tgl Exp $ --> <chapter Id="runtime-config"> <title>Server Configuration</title> @@ -3660,6 +3660,35 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' </listitem> </varlistentry> + <varlistentry id="guc-backslash-quote" xreflabel="backslash_quote"> + <term><varname>backslash_quote</varname> (<type>string</type>)</term> + <indexterm><primary>strings</><secondary>backslash quotes</></> + <indexterm> + <primary><varname>backslash_quote</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + This controls whether a quote mark can be represented by + <literal>\'</> in a string literal. The preferred, SQL-standard way + to represent a quote mark is by doubling it (<literal>''</>) but + <productname>PostgreSQL</> has historically also accepted + <literal>\'</>. However, use of <literal>\'</> creates security risks + because in some client character set encodings, there are multibyte + characters in which the last byte is numerically equivalent to ASCII + <literal>\</>. If client-side code does escaping incorrectly then a + SQL-injection attack is possible. This risk can be prevented by + making the server reject queries in which a quote mark appears to be + escaped by a backslash. + The allowed values of <varname>backslash_quote</> are + <literal>on</> (allow <literal>\'</> always), + <literal>off</> (reject always), and + <literal>safe_encoding</> (allow only if client encoding does not + allow ASCII <literal>\</> within a multibyte character). + <literal>safe_encoding</> is the default setting. + </para> + </listitem> + </varlistentry> + <varlistentry id="guc-default-with-oids" xreflabel="default_with_oids"> <term><varname>default_with_oids</varname> (<type>boolean</type>)</term> <indexterm> diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index 2a56c44a56b..35f2bc4657e 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -24,7 +24,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.128 2005/08/16 00:48:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/scan.l,v 1.128.2.1 2006/05/21 20:11:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,13 +51,14 @@ static int xcdepth = 0; /* depth of nesting in slash-star comments */ static char *dolqstart; /* current $foo$ quote start string */ /* - * GUC variable. This is a DIRECT violation of the warning given at the + * GUC variables. This is a DIRECT violation of the warning given at the * head of gram.y, ie flex/bison code must not depend on any GUC variables; - * as such, changing its value can induce very unintuitive behavior. + * as such, changing their values can induce very unintuitive behavior. * But we shall have to live with it as a short-term thing until the switch * to SQL-standard string syntax is complete. */ -bool escape_string_warning; +BackslashQuoteType backslash_quote = BACKSLASH_QUOTE_SAFE_ENCODING; +bool escape_string_warning = true; static bool warn_on_first_escape; @@ -453,6 +454,14 @@ other . <xq>{xqescape} { if (yytext[1] == '\'') { + if (backslash_quote == BACKSLASH_QUOTE_OFF || + (backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING && + PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding()))) + ereport(ERROR, + (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("unsafe use of \\' in a string literal"), + errhint("Use '' to write quotes in strings. \\' is insecure in client-only encodings."), + errposition(pg_err_position()))); if (warn_on_first_escape && escape_string_warning) ereport(WARNING, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 6d711618f9a..aad13930f70 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.299.2.2 2006/02/12 22:32:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.299.2.3 2006/05/21 20:11:02 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -46,6 +46,7 @@ #include "optimizer/geqo.h" #include "optimizer/paths.h" #include "optimizer/prep.h" +#include "parser/gramparse.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "parser/scansup.h" @@ -135,6 +136,7 @@ static bool assign_stage_log_stats(bool newval, bool doit, GucSource source); static bool assign_log_stats(bool newval, bool doit, GucSource source); static bool assign_transaction_read_only(bool newval, bool doit, GucSource source); static const char *assign_canonical_path(const char *newval, bool doit, GucSource source); +static const char *assign_backslash_quote(const char *newval, bool doit, GucSource source); static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source); static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source); @@ -203,6 +205,7 @@ static char *syslog_ident_str; static bool phony_autocommit; static bool session_auth_is_superuser; static double phony_random_seed; +static char *backslash_quote_string; static char *client_encoding_string; static char *datestyle_string; static char *default_iso_level_string; @@ -1660,6 +1663,15 @@ static struct config_string ConfigureNamesString[] = }, { + {"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS, + gettext_noop("Sets whether \"\\'\" is allowed in string literals."), + gettext_noop("Valid values are ON, OFF, and SAFE_ENCODING.") + }, + &backslash_quote_string, + "safe_encoding", assign_backslash_quote, NULL + }, + + { {"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE, gettext_noop("Sets the client's character set encoding."), NULL, @@ -5930,6 +5942,32 @@ assign_canonical_path(const char *newval, bool doit, GucSource source) return newval; } +static const char * +assign_backslash_quote(const char *newval, bool doit, GucSource source) +{ + BackslashQuoteType bq; + bool bqbool; + + /* + * Although only "on", "off", and "safe_encoding" are documented, + * we use parse_bool so we can accept all the likely variants of + * "on" and "off". + */ + if (pg_strcasecmp(newval, "safe_encoding") == 0) + bq = BACKSLASH_QUOTE_SAFE_ENCODING; + else if (parse_bool(newval, &bqbool)) + { + bq = bqbool ? BACKSLASH_QUOTE_ON : BACKSLASH_QUOTE_OFF; + } + else + return NULL; /* reject */ + + if (doit) + backslash_quote = bq; + + return newval; +} + static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source) { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 773899e8b77..b1bdd3b4be4 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -413,10 +413,11 @@ # - Previous Postgres Versions - #add_missing_from = off -#regex_flavor = advanced # advanced, extended, or basic -#sql_inheritance = on +#backslash_quote = safe_encoding # on, off, or safe_encoding #default_with_oids = off #escape_string_warning = off +#regex_flavor = advanced # advanced, extended, or basic +#sql_inheritance = on # - Other Platforms & Clients - diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h index 8095ef2300a..25935e69aa6 100644 --- a/src/include/parser/gramparse.h +++ b/src/include/parser/gramparse.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.31 2004/12/31 22:03:38 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.31.6.1 2006/05/21 20:11:02 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,18 @@ #include "nodes/parsenodes.h" +typedef enum +{ + BACKSLASH_QUOTE_OFF, + BACKSLASH_QUOTE_ON, + BACKSLASH_QUOTE_SAFE_ENCODING +} BackslashQuoteType; + +/* GUC variables in scan.l (every one of these is a bad idea :-() */ +extern BackslashQuoteType backslash_quote; +extern bool escape_string_warning; + + /* from parser.c */ extern int yylex(void); diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index fdfd5dbeb71..dfeb2bc2644 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -7,7 +7,7 @@ * Copyright (c) 2000-2005, PostgreSQL Global Development Group * Written by Peter Eisentraut <peter_e@gmx.net>. * - * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.63 2005/10/15 02:49:46 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.63.2.1 2006/05/21 20:11:02 tgl Exp $ *-------------------------------------------------------------------- */ #ifndef GUC_H @@ -120,7 +120,6 @@ extern bool SQL_inheritance; extern bool Australian_timezones; extern bool default_with_oids; -extern bool escape_string_warning; extern int log_min_error_statement; extern int log_min_messages; |