Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1bccb15

Browse files
committed
Fix ecpg's mishandling of B'...' and X'...' literals.
These were broken in multiple ways: * The xbstart and xhstart lexer actions neglected to set "state_before_str_start" before transitioning to the xb/xh states, thus possibly resulting in "internal error: unreachable state" later. * The test for valid string contents at the end of xb state was flat out wrong, as it accounted incorrectly for the "b" prefix that the xbstart action had injected. Meanwhile, the xh state had no such check at all. * The generated literal value failed to include any quote marks. * The grammar did the wrong thing anyway, typically ignoring the literal value and emitting something else, since BCONST and XCONST tokens were handled randomly differently from SCONST tokens. The first of these problems is evidently an oversight in commit 7f380c5, but the others seem to be very ancient. The lack of complaints shows that ECPG users aren't using these syntaxes much (although I do vaguely remember one previous complaint). As written, this patch is dependent on 7f380c5, so it can't go back further than v13. Given the shortage of complaints, I'm not excited about adapting the patch to prior branches. Report and patch by Shenhao Wang (test case adjusted by me) Discussion: https://postgr.es/m/d6402f1bacb74ecba22ef715dbba17fd@G08CNEXMBPEKD06.g08.fujitsu.local
1 parent d94d37f commit 1bccb15

File tree

8 files changed

+39
-8
lines changed

8 files changed

+39
-8
lines changed

src/interfaces/ecpg/preproc/ecpg.trailer

+2-2
Original file line numberDiff line numberDiff line change
@@ -1715,13 +1715,13 @@ cvariable: CVARIABLE
17151715

17161716
ecpg_param: PARAM { $$ = make_name(); } ;
17171717

1718-
ecpg_bconst: BCONST { $$ = make_name(); } ;
1718+
ecpg_bconst: BCONST { $$ = $1; } ;
17191719

17201720
ecpg_fconst: FCONST { $$ = make_name(); } ;
17211721

17221722
ecpg_sconst: SCONST { $$ = $1; } ;
17231723

1724-
ecpg_xconst: XCONST { $$ = make_name(); } ;
1724+
ecpg_xconst: XCONST { $$ = $1; } ;
17251725

17261726
ecpg_ident: IDENT { $$ = $1; }
17271727
| CSTRING { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); }

src/interfaces/ecpg/preproc/ecpg.type

+2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@
122122
%type <str> CSTRING
123123
%type <str> CPP_LINE
124124
%type <str> CVARIABLE
125+
%type <str> BCONST
125126
%type <str> SCONST
127+
%type <str> XCONST
126128
%type <str> IDENT
127129

128130
%type <struct_union> s_struct_union_symbol

src/interfaces/ecpg/preproc/parse.pl

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
'BCONST' => 'ecpg_bconst',
3939
'FCONST' => 'ecpg_fconst',
4040
'Sconst' => 'ecpg_sconst',
41+
'XCONST' => 'ecpg_xconst',
4142
'IDENT' => 'ecpg_ident',
4243
'PARAM' => 'ecpg_param',);
4344

src/interfaces/ecpg/preproc/pgc.l

+7-5
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
505505
<SQL>{
506506
{xbstart} {
507507
token_start = yytext;
508+
state_before_str_start = YYSTATE;
508509
BEGIN(xb);
509510
startlit();
510-
addlitchar('b');
511511
}
512512
} /* <SQL> */
513513

@@ -519,9 +519,9 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
519519

520520
<SQL>{xhstart} {
521521
token_start = yytext;
522+
state_before_str_start = YYSTATE;
522523
BEGIN(xh);
523524
startlit();
524-
addlitchar('x');
525525
}
526526
<xh><<EOF>> { mmfatal(PARSE_ERROR, "unterminated hexadecimal string literal"); }
527527

@@ -597,12 +597,14 @@ cppline {space}*#([^i][A-Za-z]*|{if}|{ifdef}|{ifndef}|{import})((\/\*[^*/]*\*+
597597
switch (state_before_str_stop)
598598
{
599599
case xb:
600-
if (literalbuf[strspn(literalbuf, "01") + 1] != '\0')
600+
if (literalbuf[strspn(literalbuf, "01")] != '\0')
601601
mmerror(PARSE_ERROR, ET_ERROR, "invalid bit string literal");
602-
base_yylval.str = mm_strdup(literalbuf);
602+
base_yylval.str = psprintf("b'%s'", literalbuf);
603603
return BCONST;
604604
case xh:
605-
base_yylval.str = mm_strdup(literalbuf);
605+
if (literalbuf[strspn(literalbuf, "0123456789abcdefABCDEF")] != '\0')
606+
mmerror(PARSE_ERROR, ET_ERROR, "invalid hex string literal");
607+
base_yylval.str = psprintf("x'%s'", literalbuf);
606608
return XCONST;
607609
case xq:
608610
/* fallthrough */

src/interfaces/ecpg/test/expected/preproc-strings.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,18 @@ int main(void)
6363

6464
printf("%s %s %s %s %s %s\n", s1, s2, s3, s4, s5, s6);
6565

66+
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select b'0010' , x'019ABcd'", ECPGt_EOIT,
67+
ECPGt_char,&(s1),(long)0,(long)1,(1)*sizeof(char),
68+
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
69+
ECPGt_char,&(s2),(long)0,(long)1,(1)*sizeof(char),
70+
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
71+
#line 26 "strings.pgc"
72+
73+
74+
printf("%s %s\n", s1, s2);
75+
6676
{ ECPGdisconnect(__LINE__, "CURRENT");}
67-
#line 25 "strings.pgc"
77+
#line 30 "strings.pgc"
6878

6979
return 0;
7080
}

src/interfaces/ecpg/test/expected/preproc-strings.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,15 @@
3838
[NO_PID]: sqlca: code: 0, state: 00000
3939
[NO_PID]: ecpg_get_data on line 15: RESULT: abc$def offset: -1; array: no
4040
[NO_PID]: sqlca: code: 0, state: 00000
41+
[NO_PID]: ecpg_execute on line 25: query: select b'0010' , x'019ABcd'; with 0 parameter(s) on connection ecpg1_regression
42+
[NO_PID]: sqlca: code: 0, state: 00000
43+
[NO_PID]: ecpg_execute on line 25: using PQexec
44+
[NO_PID]: sqlca: code: 0, state: 00000
45+
[NO_PID]: ecpg_process_output on line 25: correctly got 1 tuples with 2 fields
46+
[NO_PID]: sqlca: code: 0, state: 00000
47+
[NO_PID]: ecpg_get_data on line 25: RESULT: 0010 offset: -1; array: no
48+
[NO_PID]: sqlca: code: 0, state: 00000
49+
[NO_PID]: ecpg_get_data on line 25: RESULT: 0000000110011010101111001101 offset: -1; array: no
50+
[NO_PID]: sqlca: code: 0, state: 00000
4151
[NO_PID]: ecpg_finish: connection ecpg1_regression closed
4252
[NO_PID]: sqlca: code: 0, state: 00000
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
abcdef abcdef abcdef data data abc$def
2+
0010 0000000110011010101111001101

src/interfaces/ecpg/test/preproc/strings.pgc

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ int main(void)
2222

2323
printf("%s %s %s %s %s %s\n", s1, s2, s3, s4, s5, s6);
2424

25+
exec sql select b'0010', X'019ABcd'
26+
into :s1, :s2;
27+
28+
printf("%s %s\n", s1, s2);
29+
2530
exec sql disconnect;
2631
return 0;
2732
}

0 commit comments

Comments
 (0)