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;
@@ -1659,6 +1662,15 @@ static struct config_string ConfigureNamesString[] =
 		"", NULL, NULL
 	},
 
+	{
+		{"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."),
@@ -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;