From ca1c171817c5518932ce549d138f028f5d4d9398 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 13 Feb 2014 14:24:45 -0500
Subject: [PATCH] Fix length checking for Unicode identifiers containing
 escapes (U&"...").

We used the length of the input string, not the de-escaped string, as
the trigger for NAMEDATALEN truncation.  AFAICS this would only result
in sometimes printing a phony truncation warning; but it's just luck
that there was no worse problem, since we were violating the API spec
for truncate_identifier().  Per bug #9204 from Joshua Yanovski.

This has been wrong since the Unicode-identifier support was added,
so back-patch to all supported branches.
---
 src/backend/parser/scan.l | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index b65ee3e667a..772fd4c6a53 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -737,7 +737,8 @@ other			.
 <xuiend>{xustop1} |
 <xuiend><<EOF>>	{
 					/* no UESCAPE after the quote, throw back everything */
-					char		   *ident;
+					char	   *ident;
+					int			identlen;
 
 					yyless(0);
 
@@ -745,14 +746,16 @@ other			.
 					if (yyextra->literallen == 0)
 						yyerror("zero-length delimited identifier");
 					ident = litbuf_udeescape('\\', yyscanner);
-					if (yyextra->literallen >= NAMEDATALEN)
-						truncate_identifier(ident, yyextra->literallen, true);
+					identlen = strlen(ident);
+					if (identlen >= NAMEDATALEN)
+						truncate_identifier(ident, identlen, true);
 					yylval->str = ident;
 					return IDENT;
 				}
 <xuiend>{xustop2}	{
 					/* found UESCAPE after the end quote */
-					char		   *ident;
+					char	   *ident;
+					int			identlen;
 
 					BEGIN(INITIAL);
 					if (yyextra->literallen == 0)
@@ -764,8 +767,9 @@ other			.
 						yyerror("invalid Unicode escape character");
 					}
 					ident = litbuf_udeescape(yytext[yyleng - 2], yyscanner);
-					if (yyextra->literallen >= NAMEDATALEN)
-						truncate_identifier(ident, yyextra->literallen, true);
+					identlen = strlen(ident);
+					if (identlen >= NAMEDATALEN)
+						truncate_identifier(ident, identlen, true);
 					yylval->str = ident;
 					return IDENT;
 				}