Skip to content

Commit 1834987

Browse files
committed
I've attached the fixed version of the patch below. After the
discussion on pgsql-hackers (especially the frightening memory dump in <12273.999562219@sss.pgh.pa.us>), we decided that it is best not to use identifiers from an untrusted source at all. Therefore, all claims of the suitability of PQescapeString() for identifiers have been removed. Florian Weimer
1 parent bd9b328 commit 1834987

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.68 2001/09/04 00:18:18 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.69 2001/09/07 22:02:32 momjian Exp $
33
-->
44

55
<chapter id="libpq">
@@ -827,6 +827,42 @@ as with a PGresult returned by libpq itself.
827827
</itemizedlist>
828828
</sect2>
829829

830+
<sect2 id="libpq-exec-escape-string">
831+
<title>Escaping strings for inclusion in SQL queries</title>
832+
<para>
833+
<function>PQescapeString</function>
834+
Escapes a string for use within an SQL query.
835+
<synopsis>
836+
size_t PQescapeString (char *to, const char *from, size_t length);
837+
</synopsis>
838+
If you want to include strings which have been received
839+
from a source which is not trustworthy (for example, because they were
840+
transmitted across a network), you cannot directly include them in SQL
841+
queries for security reasons. Instead, you have to quote special
842+
characters which are otherwise interpreted by the SQL parser.
843+
</para>
844+
<para>
845+
<function>PQescapeString</> performs this operation. The
846+
<parameter>from</> points to the first character of the string which
847+
is to be escaped, and the <parameter>length</> parameter counts the
848+
number of characters in this string (a terminating NUL character is
849+
neither necessary nor counted). <parameter>to</> shall point to a
850+
buffer which is able to hold at least one more character than twice
851+
the value of <parameter>length</>, otherwise the behavior is
852+
undefined. A call to <function>PQescapeString</> writes an escaped
853+
version of the <parameter>from</> string to the <parameter>to</>
854+
buffer, replacing special characters so that they cannot cause any
855+
harm, and adding a terminating NUL character. The single quotes which
856+
must surround PostgreSQL string literals are not part of the result
857+
string.
858+
</para>
859+
<para>
860+
<function>PQescapeString</> returns the number of characters written
861+
to <parameter>to</>, not including the terminating NUL character.
862+
Behavior is undefined when the <parameter>to</> and <parameter>from</>
863+
strings overlap.
864+
</para>
865+
830866
<sect2 id="libpq-exec-select-info">
831867
<title>Retrieving SELECT Result Information</title>
832868

src/interfaces/libpq/fe-exec.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.109 2001/09/06 02:54:56 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.110 2001/09/07 22:02:32 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -56,6 +56,62 @@ static int getAnotherTuple(PGconn *conn, int binary);
5656
static int getNotify(PGconn *conn);
5757
static int getNotice(PGconn *conn);
5858

59+
/* ---------------
60+
* Escaping arbitrary strings to get valid SQL strings/identifiers.
61+
*
62+
* Replaces "\\" with "\\\\", "\0" with "\\0", and "'" with "''".
63+
* length is the length of the buffer pointed to by
64+
* from. The buffer at to must be at least 2*length + 1 characters
65+
* long. A terminating NUL character is written.
66+
* ---------------
67+
*/
68+
69+
size_t
70+
PQescapeString (char *to, const char *from, size_t length)
71+
{
72+
const char *source = from;
73+
char *target = to;
74+
unsigned int remaining = length;
75+
76+
while (remaining > 0) {
77+
switch (*source) {
78+
case '\0':
79+
*target = '\\';
80+
target++;
81+
*target = '0';
82+
/* target and remaining are updated below. */
83+
break;
84+
85+
case '\\':
86+
*target = '\\';
87+
target++;
88+
*target = '\\';
89+
/* target and remaining are updated below. */
90+
break;
91+
92+
case '\'':
93+
*target = '\'';
94+
target++;
95+
*target = '\'';
96+
/* target and remaining are updated below. */
97+
break;
98+
99+
default:
100+
*target = *source;
101+
/* target and remaining are updated below. */
102+
}
103+
source++;
104+
target++;
105+
remaining--;
106+
}
107+
108+
/* Write the terminating NUL character. */
109+
*target = '\0';
110+
111+
return target - to;
112+
}
113+
114+
59115

60116
/* ----------------
61117
* Space management for PGresult.

src/interfaces/libpq/libpq-fe.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: libpq-fe.h,v 1.73 2001/09/06 02:54:56 momjian Exp $
10+
* $Id: libpq-fe.h,v 1.74 2001/09/07 22:02:32 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -251,6 +251,9 @@ extern "C"
251251

252252
/* === in fe-exec.c === */
253253

254+
/* Quoting strings before inclusion in queries. */
255+
extern size_t PQescapeString (char *to, const char *from, size_t length);
256+
254257
/* Simple synchronous query */
255258
extern PGresult *PQexec(PGconn *conn, const char *query);
256259
extern PGnotify *PQnotifies(PGconn *conn);

0 commit comments

Comments
 (0)