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

Commit77c1791

Browse files
committed
Use PQescapeString to ensure that tab-completion queries are not messed
up by quotes or backslashes in words that are being matched to databasenames (per gripe from Ian Barwick, though I didn't use his patch).Also fix possible memory leakage if _complete_with_query isn't run tocompletion (not clear if that can happen or not, but be safe).
1 parent2a0f1c0 commit77c1791

File tree

1 file changed

+85
-28
lines changed

1 file changed

+85
-28
lines changed

‎src/bin/psql/tab-complete.c

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
55
*
6-
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.85 2003/09/07 15:26:54 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.86 2003/10/14 22:47:12 tgl Exp $
77
*/
88

99
/*----------------------------------------------------------------------
@@ -85,17 +85,20 @@ static char *complete_from_const(const char *text, int state);
8585
staticchar*complete_from_list(constchar*text,intstate);
8686

8787
staticPGresult*exec_query(char*query);
88-
char*quote_file_name(char*text,intmatch_type,char*quote_pointer);
8988

90-
/*static char * dequote_file_name(char *text, char quote_char);*/
9189
staticchar*previous_word(intpoint,intskip);
9290

91+
#if0
92+
staticchar*quote_file_name(char*text,intmatch_type,char*quote_pointer);
93+
staticchar*dequote_file_name(char*text,charquote_char);
94+
#endif
95+
9396
/* These variables are used to pass information into the completion functions.
9497
Realizing that this is the cardinal sin of programming, I don't see a better
9598
way. */
96-
char*completion_charp;/* if you need to pass a string */
97-
char**completion_charpp;/* if you need to pass a list of strings */
98-
char*completion_info_charp;/* if you need to pass another
99+
staticchar*completion_charp;/* if you need to pass a string */
100+
staticchar**completion_charpp;/* if you need to pass a list of strings */
101+
staticchar*completion_info_charp;/* if you need to pass another
99102
* string */
100103

101104
/* Store how many records from a database query we want to return at most
@@ -124,7 +127,10 @@ initialize_readline(void)
124127
/*
125128
* Queries to get lists of names of various kinds of things, possibly
126129
* restricted to names matching a partially entered name. In these queries,
127-
* the %s will be replaced by the text entered so far, the %d by its length.
130+
* %s will be replaced by the text entered so far (suitably escaped to
131+
* become a SQL literal string). %d will be replaced by the length of the
132+
* string (in unescaped form). Beware that the allowed sequences of %s and
133+
* %d are determined by _complete_from_query().
128134
*/
129135

130136
#defineQuery_for_list_of_aggregates \
@@ -401,6 +407,15 @@ initialize_readline(void)
401407
" FROM pg_catalog.pg_user "\
402408
" WHERE substr(usename,1,%d)='%s'"
403409

410+
/* the silly-looking length condition is just to eat up the current word */
411+
#defineQuery_for_table_owning_index \
412+
"SELECT c1.relname "\
413+
" FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
414+
" WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
415+
" and (%d = length('%s'))"\
416+
" and c2.relname='%s'"\
417+
" and pg_catalog.pg_table_is_visible(c2.oid)"
418+
404419
/* This is a list of all "things" in Pgsql, which can show up after CREATE or
405420
DROP; and there is also a query to get a list of them.
406421
*/
@@ -754,15 +769,8 @@ psql_completion(char *text, int start, int end)
754769
elseif (strcasecmp(prev3_wd,"CLUSTER")==0&&
755770
strcasecmp(prev_wd,"ON")==0)
756771
{
757-
charquery_buffer[BUF_SIZE];/* Some room to build
758-
* queries. */
759-
760-
if (snprintf(query_buffer,BUF_SIZE,
761-
"SELECT c1.relname FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid and c2.relname='%s' and pg_catalog.pg_table_is_visible(c2.oid)",
762-
prev2_wd)==-1)
763-
ERROR_QUERY_TOO_LONG;
764-
else
765-
COMPLETE_WITH_QUERY(query_buffer);
772+
completion_info_charp=prev2_wd;
773+
COMPLETE_WITH_QUERY(Query_for_table_owning_index);
766774
}
767775

768776
/* COMMENT */
@@ -1425,6 +1433,9 @@ complete_from_schema_query(const char *text, int state)
14251433
%d %s %d %s %d %s %s %d %s
14261434
where %d is the string length of the text and %s the text itself.
14271435
1436+
It is assumed that strings should be escaped to become SQL literals
1437+
(that is, what is in the query is actually ... '%s' ...)
1438+
14281439
See top of file for examples of both kinds of query.
14291440
*/
14301441

@@ -1434,48 +1445,93 @@ _complete_from_query(int is_schema_query, const char *text, int state)
14341445
staticintlist_index,
14351446
string_length;
14361447
staticPGresult*result=NULL;
1437-
charquery_buffer[BUF_SIZE];
1438-
constchar*item;
14391448

14401449
/*
14411450
* If this is the first time for this completion, we fetch a list of
14421451
* our "things" from the backend.
14431452
*/
14441453
if (state==0)
14451454
{
1455+
charquery_buffer[BUF_SIZE];
1456+
char*e_text;
1457+
char*e_info_charp;
1458+
14461459
list_index=0;
14471460
string_length=strlen(text);
14481461

1462+
/* Free any prior result */
1463+
PQclear(result);
1464+
result=NULL;
1465+
14491466
/* Need to have a query */
14501467
if (completion_charp==NULL)
14511468
returnNULL;
14521469

1453-
if (is_schema_query)
1470+
/* Set up suitably-escaped copies of textual inputs */
1471+
if (text)
14541472
{
1455-
if (snprintf(query_buffer,BUF_SIZE,completion_charp,string_length,text,string_length,text,string_length,text,text,string_length,text,string_length,text)==-1)
1456-
{
1457-
ERROR_QUERY_TOO_LONG;
1473+
e_text= (char*)malloc(strlen(text)*2+1);
1474+
if (!e_text)
14581475
returnNULL;
1459-
}
1476+
PQescapeString(e_text,text,strlen(text));
14601477
}
14611478
else
1479+
e_text=NULL;
1480+
1481+
if (completion_info_charp)
14621482
{
1463-
if (snprintf(query_buffer,BUF_SIZE,completion_charp,string_length,text,completion_info_charp)==-1)
1483+
e_info_charp= (char*)
1484+
malloc(strlen(completion_info_charp)*2+1);
1485+
if (!e_info_charp)
14641486
{
1465-
ERROR_QUERY_TOO_LONG;
1487+
if (e_text)
1488+
free(e_text);
14661489
returnNULL;
14671490
}
1491+
PQescapeString(e_info_charp,completion_info_charp,
1492+
strlen(completion_info_charp));
1493+
}
1494+
else
1495+
e_info_charp=NULL;
1496+
1497+
if (is_schema_query)
1498+
{
1499+
if (snprintf(query_buffer,BUF_SIZE,completion_charp,
1500+
string_length,e_text,
1501+
string_length,e_text,
1502+
string_length,e_text,
1503+
e_text,
1504+
string_length,e_text,
1505+
string_length,e_text)==-1)
1506+
ERROR_QUERY_TOO_LONG;
1507+
else
1508+
result=exec_query(query_buffer);
1509+
}
1510+
else
1511+
{
1512+
if (snprintf(query_buffer,BUF_SIZE,completion_charp,
1513+
string_length,e_text,e_info_charp)==-1)
1514+
ERROR_QUERY_TOO_LONG;
1515+
else
1516+
result=exec_query(query_buffer);
14681517
}
14691518

1470-
result=exec_query(query_buffer);
1519+
if (e_text)
1520+
free(e_text);
1521+
if (e_info_charp)
1522+
free(e_info_charp);
14711523
}
14721524

14731525
/* Find something that matches */
14741526
if (result&&PQresultStatus(result)==PGRES_TUPLES_OK)
1527+
{
1528+
constchar*item;
1529+
14751530
while (list_index<PQntuples(result)&&
14761531
(item=PQgetvalue(result,list_index++,0)))
14771532
if (strncasecmp(text,item,string_length)==0)
14781533
returnxstrdup(item);
1534+
}
14791535

14801536
/* If nothing matches, free the db structure and return null */
14811537
PQclear(result);
@@ -1585,7 +1641,8 @@ exec_query(char *query)
15851641
assert(query[strlen(query)-1]!=';');
15861642
#endif
15871643

1588-
if (snprintf(query_buffer,BUF_SIZE,"%s LIMIT %d;",query,completion_max_records)==-1)
1644+
if (snprintf(query_buffer,BUF_SIZE,"%s LIMIT %d;",
1645+
query,completion_max_records)==-1)
15891646
{
15901647
ERROR_QUERY_TOO_LONG;
15911648
returnNULL;
@@ -1684,7 +1741,7 @@ previous_word(int point, int skip)
16841741
* psql internal. Currently disable because it is reported not to
16851742
* cooperate with certain versions of readline.
16861743
*/
1687-
char*
1744+
staticchar*
16881745
quote_file_name(char*text,intmatch_type,char*quote_pointer)
16891746
{
16901747
char*s;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp