Commit 35d89401 authored by Tom Lane's avatar Tom Lane

Fix up some oversights in psql's Unicode-escape support.

Original patch failed to include new exclusive states in a switch that
needed to include them; and also was guilty of very fuzzy thinking
about how to handle error cases.  Per bug #5729 from Alan Choi.
parent 5a12c808
...@@ -120,7 +120,6 @@ static bool var_is_current_source(PsqlScanState state, const char *varname); ...@@ -120,7 +120,6 @@ static bool var_is_current_source(PsqlScanState state, const char *varname);
static YY_BUFFER_STATE prepare_buffer(const char *txt, int len, static YY_BUFFER_STATE prepare_buffer(const char *txt, int len,
char **txtcopy); char **txtcopy);
static void emit(const char *txt, int len); static void emit(const char *txt, int len);
static bool is_utf16_surrogate_first(uint32 c);
static void escape_variable(bool as_ident); static void escape_variable(bool as_ident);
#define ECHO emit(yytext, yyleng) #define ECHO emit(yytext, yyleng)
...@@ -163,7 +162,11 @@ static void escape_variable(bool as_ident); ...@@ -163,7 +162,11 @@ static void escape_variable(bool as_ident);
* <xdolq> $foo$ quoted strings * <xdolq> $foo$ quoted strings
* <xui> quoted identifier with Unicode escapes * <xui> quoted identifier with Unicode escapes
* <xus> quoted string with Unicode escapes * <xus> quoted string with Unicode escapes
* <xeu> Unicode surrogate pair in extended quoted string *
* Note: we intentionally don't mimic the backend's <xeu> state; we have
* no need to distinguish it from <xe> state, and no good way to get out
* of it in error cases. The backend just throws yyerror() in those
* cases, but that's not an option here.
*/ */
%x xb %x xb
...@@ -175,7 +178,6 @@ static void escape_variable(bool as_ident); ...@@ -175,7 +178,6 @@ static void escape_variable(bool as_ident);
%x xdolq %x xdolq
%x xui %x xui
%x xus %x xus
%x xeu
/* Additional exclusive states for psql only: lex backslash commands */ /* Additional exclusive states for psql only: lex backslash commands */
%x xslashcmd %x xslashcmd
%x xslasharg %x xslasharg
...@@ -529,19 +531,9 @@ other . ...@@ -529,19 +531,9 @@ other .
ECHO; ECHO;
} }
<xe>{xeunicode} { <xe>{xeunicode} {
uint32 c = strtoul(yytext+2, NULL, 16);
if (is_utf16_surrogate_first(c))
BEGIN(xeu);
ECHO;
}
<xeu>{xeunicode} {
BEGIN(xe);
ECHO; ECHO;
} }
<xeu>. { ECHO; } <xe>{xeunicodefail} {
<xeu>\n { ECHO; }
<xe,xeu>{xeunicodefail} {
ECHO; ECHO;
} }
<xe>{xeescape} { <xe>{xeescape} {
...@@ -1242,6 +1234,7 @@ psql_scan(PsqlScanState state, ...@@ -1242,6 +1234,7 @@ psql_scan(PsqlScanState state,
case LEXRES_EOL: /* end of input */ case LEXRES_EOL: /* end of input */
switch (state->start_state) switch (state->start_state)
{ {
/* This switch must cover all non-slash-command states. */
case INITIAL: case INITIAL:
if (state->paren_depth > 0) if (state->paren_depth > 0)
{ {
...@@ -1276,11 +1269,11 @@ psql_scan(PsqlScanState state, ...@@ -1276,11 +1269,11 @@ psql_scan(PsqlScanState state,
result = PSCAN_INCOMPLETE; result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE; *prompt = PROMPT_SINGLEQUOTE;
break; break;
case xq: case xe:
result = PSCAN_INCOMPLETE; result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE; *prompt = PROMPT_SINGLEQUOTE;
break; break;
case xe: case xq:
result = PSCAN_INCOMPLETE; result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE; *prompt = PROMPT_SINGLEQUOTE;
break; break;
...@@ -1288,6 +1281,14 @@ psql_scan(PsqlScanState state, ...@@ -1288,6 +1281,14 @@ psql_scan(PsqlScanState state,
result = PSCAN_INCOMPLETE; result = PSCAN_INCOMPLETE;
*prompt = PROMPT_DOLLARQUOTE; *prompt = PROMPT_DOLLARQUOTE;
break; break;
case xui:
result = PSCAN_INCOMPLETE;
*prompt = PROMPT_DOUBLEQUOTE;
break;
case xus:
result = PSCAN_INCOMPLETE;
*prompt = PROMPT_SINGLEQUOTE;
break;
default: default:
/* can't get here */ /* can't get here */
fprintf(stderr, "invalid YY_START\n"); fprintf(stderr, "invalid YY_START\n");
...@@ -1814,12 +1815,6 @@ emit(const char *txt, int len) ...@@ -1814,12 +1815,6 @@ emit(const char *txt, int len)
} }
} }
static bool
is_utf16_surrogate_first(uint32 c)
{
return (c >= 0xD800 && c <= 0xDBFF);
}
static void static void
escape_variable(bool as_ident) escape_variable(bool as_ident)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment