diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index f77ee8e035a..718e90d8f85 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,5 +1,5 @@ @@ -1318,6 +1318,35 @@ env PGOPTIONS='-c geqo=off' psql + + BACKSLASH_QUOTE (string) + stringsbackslash quotes + + backslash_quote configuration parameter + + + + This controls whether a quote mark can be represented by + \' in a string literal. The preferred, SQL-standard way + to represent a quote mark is by doubling it ('') but + PostgreSQL has historically also accepted + \'. However, use of \' creates security risks + because in some client character set encodings, there are multibyte + characters in which the last byte is numerically equivalent to ASCII + \. 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 backslash_quote are + on (allow \' always), + off (reject always), and + safe_encoding (allow only if client encoding does not + allow ASCII \ within a multibyte character). + safe_encoding is the default setting. + + + + CLIENT_ENCODING (string) character set encoding diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l index a902e2828d8..d8fda9a2ca5 100644 --- a/src/backend/parser/scan.l +++ b/src/backend/parser/scan.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.102.2.2 2005/08/16 00:48:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.102.2.3 2006/05/21 20:12:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -39,6 +39,15 @@ extern YYSTYPE yylval; static int xcdepth = 0; /* depth of nesting in slash-star comments */ +/* + * 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 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. + */ +BackslashQuoteType backslash_quote = BACKSLASH_QUOTE_SAFE_ENCODING; + /* * literalbuf is used to accumulate literal values when multiple rules * are needed to parse a single literal. Call startlit to reset buffer @@ -376,6 +385,13 @@ other . addlit(yytext, yyleng); } {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()))) + elog(ERROR, "unsafe use of \\' in a string literal"); + } addlitchar(unescape_single_char(yytext[1])); } {xqoctesc} { diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index af64f0ad34f..4f723c42dbb 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -5,7 +5,7 @@ * command, configuration file, and command line options. * See src/backend/utils/misc/README for more information. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.99.2.6 2006/02/12 22:33:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.99.2.7 2006/05/21 20:12:20 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -38,6 +38,7 @@ #include "optimizer/geqo.h" #include "optimizer/paths.h" #include "optimizer/planmain.h" +#include "parser/gramparse.h" #include "parser/parse_expr.h" #include "storage/fd.h" #include "storage/freespace.h" @@ -72,6 +73,8 @@ static const char *assign_facility(const char *facility, static const char *assign_msglvl(int *var, const char *newval, bool doit, bool interactive); +static const char *assign_backslash_quote(const char *newval, bool doit, + bool interactive); /* * Debugging options @@ -124,6 +127,7 @@ const char client_min_messages_str_default[] = "notice"; * and is kept in sync by assign_hooks. */ 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; @@ -736,6 +740,11 @@ static struct config_real static struct config_string ConfigureNamesString[] = { + { + {"backslash_quote", PGC_USERSET}, &backslash_quote_string, + "safe_encoding", assign_backslash_quote, NULL + }, + { {"client_encoding", PGC_USERSET, GUC_IS_NAME}, &client_encoding_string, "SQL_ASCII", assign_client_encoding, NULL @@ -3060,4 +3069,30 @@ assign_msglvl(int *var, const char *newval, bool doit, bool interactive) return newval; /* OK */ } +static const char * +assign_backslash_quote(const char *newval, bool doit, bool interactive) +{ + 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 (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; +} + #include "guc-file.c" diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index d34a22939e6..e974a811167 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -206,4 +206,5 @@ #transform_null_equals = false #statement_timeout = 0 # 0 is disabled, in milliseconds #db_user_namespace = false - +#backslash_quote = safe_encoding # on, off, or safe_encoding + diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index ce4a2b5a809..b7f3c33a00a 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright 2000-2002 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.64 2002/09/04 20:31:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.64.2.1 2006/05/21 20:12:20 tgl Exp $ */ /*---------------------------------------------------------------------- @@ -269,6 +269,7 @@ psql_completion(char *text, int start, int end) "cpu_operator_cost", "geqo_selection_bias", + "backslash_quote", "default_transaction_isolation", "search_path", "statement_timeout", diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h index 97a91093e23..dd08e95c404 100644 --- a/src/include/parser/gramparse.h +++ b/src/include/parser/gramparse.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: gramparse.h,v 1.25 2002/09/04 20:31:45 momjian Exp $ + * $Id: gramparse.h,v 1.25.2.1 2006/05/21 20:12:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,17 @@ #include "lib/stringinfo.h" #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; + + /* from parser.c */ extern void parser_param_set(Oid *typev, int nargs); extern Oid param_type(int t);