Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit93dc6a1

Browse files
committed
Fix psql to not go into infinite recursion when expanding a variable that
refers to itself (directly or indirectly). Instead, print a message whenrecursion is detected, and don't expand the repeated reference. Per bug#5448 from Francis Markham.Back-patch to 8.0. Although the issue exists in 7.4 as well, it seemsimpractical to fix there because of the lack of any state stack thatcould be used to track active expansions.
1 parent1ba23f7 commit93dc6a1

File tree

1 file changed

+74
-23
lines changed

1 file changed

+74
-23
lines changed

‎src/bin/psql/psqlscan.l

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
* Portions Copyright (c) 1994, Regents of the University of California
3434
*
3535
* IDENTIFICATION
36-
* $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.32 2010/01/29 17:44:12 rhaas Exp $
36+
* $PostgreSQL: pgsql/src/bin/psql/psqlscan.l,v 1.33 2010/05/05 22:18:56 tgl Exp $
3737
*
3838
*-------------------------------------------------------------------------
3939
*/
@@ -59,6 +59,7 @@ typedef struct StackElem
5959
YY_BUFFER_STATE buf;/* flex input control structure */
6060
char *bufstring;/* data actually being scanned by flex */
6161
char *origstring;/* copy of original data, if needed */
62+
char *varname;/* name of variable providing data, or NULL */
6263
structStackElem *next;
6364
} StackElem;
6465

@@ -113,7 +114,9 @@ static char *option_quote;
113114

114115
intyylex(void);
115116

116-
staticvoidpush_new_buffer(constchar *newstr);
117+
staticvoidpush_new_buffer(constchar *newstr,constchar *varname);
118+
staticvoidpop_buffer_stack(PsqlScanState state);
119+
staticboolvar_is_current_source(PsqlScanState state,constchar *varname);
117120
static YY_BUFFER_STATEprepare_buffer(constchar *txt,int len,
118121
char **txtcopy);
119122
staticvoidemit(constchar *txt,int len);
@@ -688,15 +691,28 @@ other.
688691

689692
:[A-Za-z0-9_]+{
690693
/* Possible psql variable substitution */
694+
constchar *varname = yytext +1;
691695
constchar *value;
692696

693-
value =GetVariable(pset.vars,yytext +1);
697+
value =GetVariable(pset.vars,varname);
694698

695699
if (value)
696700
{
697-
/* It is a variable, perform substitution */
698-
push_new_buffer(value);
699-
/* yy_scan_string already made buffer active */
701+
/* It is a variable, check for recursion */
702+
if (var_is_current_source(cur_state, varname))
703+
{
704+
/* Recursive expansion --- don't go there */
705+
psql_error("skipping recursive expansion of variable\"%s\"\n",
706+
varname);
707+
/* Instead copy the string as is */
708+
ECHO;
709+
}
710+
else
711+
{
712+
/* OK, perform substitution */
713+
push_new_buffer(value, varname);
714+
/* yy_scan_string already made buffer active */
715+
}
700716
}
701717
else
702718
{
@@ -836,12 +852,7 @@ other.
836852
* We were expanding a variable, so pop the inclusion
837853
* stack and keep lexing
838854
*/
839-
cur_state->buffer_stack = stackelem->next;
840-
yy_delete_buffer(stackelem->buf);
841-
free(stackelem->bufstring);
842-
if (stackelem->origstring)
843-
free(stackelem->origstring);
844-
free(stackelem);
855+
pop_buffer_stack(cur_state);
845856

846857
stackelem = cur_state->buffer_stack;
847858
if (stackelem !=NULL)
@@ -926,6 +937,7 @@ other.
926937
* further examination. This is consistent with the
927938
* pre-8.0 code behavior, if not with the way that
928939
* variables are handled outside backslash commands.
940+
* Note that we needn't guard against recursion here.
929941
*/
930942
if (value)
931943
appendPQExpBufferStr(output_buf, value);
@@ -1315,16 +1327,7 @@ psql_scan_finish(PsqlScanState state)
13151327
{
13161328
/* Drop any incomplete variable expansions. */
13171329
while (state->buffer_stack !=NULL)
1318-
{
1319-
StackElem *stackelem = state->buffer_stack;
1320-
1321-
state->buffer_stack = stackelem->next;
1322-
yy_delete_buffer(stackelem->buf);
1323-
free(stackelem->bufstring);
1324-
if (stackelem->origstring)
1325-
free(stackelem->origstring);
1326-
free(stackelem);
1327-
}
1330+
pop_buffer_stack(state);
13281331

13291332
/* Done with the outer scan buffer, too */
13301333
if (state->scanbufhandle)
@@ -1670,11 +1673,19 @@ psql_scan_slash_command_end(PsqlScanState state)
16701673
* NOTE SIDE EFFECT: the new buffer is made the active flex input buffer.
16711674
*/
16721675
staticvoid
1673-
push_new_buffer(constchar *newstr)
1676+
push_new_buffer(constchar *newstr,constchar *varname)
16741677
{
16751678
StackElem *stackelem;
16761679

16771680
stackelem = (StackElem *)pg_malloc(sizeof(StackElem));
1681+
1682+
/*
1683+
* In current usage, the passed varname points at the current flex
1684+
* input buffer; we must copy it before calling prepare_buffer()
1685+
* because that will change the buffer state.
1686+
*/
1687+
stackelem->varname = varname ?pg_strdup(varname) :NULL;
1688+
16781689
stackelem->buf =prepare_buffer(newstr,strlen(newstr),
16791690
&stackelem->bufstring);
16801691
cur_state->curline = stackelem->bufstring;
@@ -1692,6 +1703,46 @@ push_new_buffer(const char *newstr)
16921703
cur_state->buffer_stack = stackelem;
16931704
}
16941705

1706+
/*
1707+
* Pop the topmost buffer stack item (there must be one!)
1708+
*
1709+
* NB: after this, the flex input state is unspecified; caller must
1710+
* switch to an appropriate buffer to continue lexing.
1711+
*/
1712+
staticvoid
1713+
pop_buffer_stack(PsqlScanState state)
1714+
{
1715+
StackElem *stackelem = state->buffer_stack;
1716+
1717+
state->buffer_stack = stackelem->next;
1718+
yy_delete_buffer(stackelem->buf);
1719+
free(stackelem->bufstring);
1720+
if (stackelem->origstring)
1721+
free(stackelem->origstring);
1722+
if (stackelem->varname)
1723+
free(stackelem->varname);
1724+
free(stackelem);
1725+
}
1726+
1727+
/*
1728+
* Check if specified variable name is the source for any string
1729+
* currently being scanned
1730+
*/
1731+
staticbool
1732+
var_is_current_source(PsqlScanState state,constchar *varname)
1733+
{
1734+
StackElem *stackelem;
1735+
1736+
for (stackelem = state->buffer_stack;
1737+
stackelem !=NULL;
1738+
stackelem = stackelem->next)
1739+
{
1740+
if (stackelem->varname &&strcmp(stackelem->varname, varname) ==0)
1741+
returntrue;
1742+
}
1743+
returnfalse;
1744+
}
1745+
16951746
/*
16961747
* Set up a flex input buffer to scan the given data. We always make a
16971748
* copy of the data. If working in an unsafe encoding, the copy has

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp