*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
***************
*** 2923,3042 **** typedef struct {
! Escaping Strings for Inclusion in SQL Commands
- PQescapeStringConn
-
-
- PQescapeString
-
-
escaping strings
in libpq
!
! PQescapeStringConn escapes a string for use within an SQL
! command. This is useful when inserting data values as literal constants
! in SQL commands. Certain characters (such as quotes and backslashes) must
! be escaped to prevent them from being interpreted specially by the SQL parser.
! PQescapeStringConn> performs this operation.
!
!
!
! It is especially important to do proper escaping when handling strings that
! were received from an untrustworthy source. Otherwise there is a security
! risk: you are vulnerable to SQL injection> attacks wherein unwanted
! SQL commands are fed to your database.
!
!
!
! Note that it is not necessary nor correct to do escaping when a data
! value is passed as a separate parameter in PQexecParams> or
! its sibling routines.
!
!
! size_t PQescapeStringConn (PGconn *conn,
! char *to, const char *from, size_t length,
! int *error);
!
!
!
! PQescapeStringConn> writes an escaped version of the
! from> string to the to> buffer, escaping
! special characters so that they cannot cause any harm, and adding a
! terminating zero byte. The single quotes that must surround
! PostgreSQL> string literals are not included in the
! result string; they should be provided in the SQL command that the
! result is inserted into. The parameter from> points to
! the first character of the string that is to be escaped, and the
! length> parameter gives the number of bytes in this
! string. A terminating zero byte is not required, and should not be
! counted in length>. (If a terminating zero byte is found
! before length> bytes are processed,
! PQescapeStringConn> stops at the zero; the behavior is
! thus rather like strncpy>.) to> shall point
! to a buffer that is able to hold at least one more byte than twice
! the value of length>, otherwise the behavior is undefined.
! Behavior is likewise undefined if the to> and
! from> strings overlap.
!
!
! If the error> parameter is not NULL, then
! *error> is set to zero on success, nonzero on error.
! Presently the only possible error conditions involve invalid multibyte
! encoding in the source string. The output string is still generated
! on error, but it can be expected that the server will reject it as
! malformed. On error, a suitable message is stored in the
! conn> object, whether or not error> is NULL.
!
!
! PQescapeStringConn> returns the number of bytes written
! to to>, not including the terminating zero byte.
!
!
!
! size_t PQescapeString (char *to, const char *from, size_t length);
!
!
!
! PQescapeString> is an older, deprecated version of
! PQescapeStringConn>; the difference is that it does
! not take conn> or error> parameters.
! Because of this, it cannot adjust its behavior depending on the
! connection properties (such as character encoding) and therefore
! it might give the wrong results>. Also, it has no way
! to report error conditions.
!
!
! PQescapeString> can be used safely in single-threaded
! client programs that work with only one PostgreSQL>
! connection at a time (in this case it can find out what it needs to
! know behind the scenes>). In other contexts it is a security
! hazard and should be avoided in favor of
! PQescapeStringConn>.
!
!
!
! Escaping Binary Strings for Inclusion in SQL Commands
!
! bytea
! in libpq
!
-
PQescapeByteaConn
--- 2923,3117 ----
! Escaping Strings and Identifiers for Inclusion in SQL Commands
escaping strings
in libpq
!
!
!
! PQescapeStringConn
!
! PQescapeStringConn
!
!
!
!
! PQescapeStringConn escapes a string for use within an SQL
! command. This is useful when inserting data values as literal constants
! in SQL commands. Certain characters (such as quotes and backslashes) must
! be escaped to prevent them from being interpreted specially by the SQL parser.
! PQescapeStringConn> performs this operation.
!
!
!
! It is especially important to do proper escaping when handling strings that
! were received from an untrustworthy source. Otherwise there is a security
! risk: you are vulnerable to SQL injection> attacks wherein unwanted
! SQL commands are fed to your database.
!
!
!
! Note that it is not necessary nor correct to do escaping when a data
! value is passed as a separate parameter in PQexecParams> or
! its sibling routines.
!
! size_t PQescapeStringConn (PGconn *conn,
! char *to, const char *from, size_t length,
! int *error);
!
!
!
! PQescapeStringConn> writes an escaped version of the
! from> string to the to> buffer, escaping
! special characters so that they cannot cause any harm, and adding a
! terminating zero byte. The single quotes that must surround
! PostgreSQL> string literals are not included in the
! result string; they should be provided in the SQL command that the
! result is inserted into. The parameter from> points to
! the first character of the string that is to be escaped, and the
! length> parameter gives the number of bytes in this
! string. A terminating zero byte is not required, and should not be
! counted in length>. (If a terminating zero byte is found
! before length> bytes are processed,
! PQescapeStringConn> stops at the zero; the behavior is
! thus rather like strncpy>.) to> shall point
! to a buffer that is able to hold at least one more byte than twice
! the value of length>, otherwise the behavior is undefined.
! Behavior is likewise undefined if the to> and
! from> strings overlap.
!
!
! If the error> parameter is not NULL, then
! *error> is set to zero on success, nonzero on error.
! Presently the only possible error conditions involve invalid multibyte
! encoding in the source string. The output string is still generated
! on error, but it can be expected that the server will reject it as
! malformed. On error, a suitable message is stored in the
! conn> object, whether or not error> is NULL.
!
!
! PQescapeStringConn> returns the number of bytes written
! to to>, not including the terminating zero byte.
!
!
!
!
!
! PQescapeString
!
! PQescapeString
!
!
!
!
!
!
! size_t PQescapeString (char *to, const char *from, size_t length);
!
!
+
+ PQescapeString> is an older, deprecated version of
+ PQescapeStringConn>; the difference is that it does
+ not take conn> or error> parameters.
+ Because of this, it cannot adjust its behavior depending on the
+ connection properties (such as character encoding) and therefore
+ it might give the wrong results>. Also, it has no way
+ to report error conditions.
+
!
! PQescapeString> can be used safely in single-threaded
! client programs that work with only one PostgreSQL>
! connection at a time (in this case it can find out what it needs to
! know behind the scenes>). In other contexts it is a security
! hazard and should be avoided in favor of
! PQescapeStringConn>.
!
!
!
!
!
! PQescapeIdentifierConn
!
! PQescapeIdentifierConn
!
!
!
!
!
! PQescapeIdentifierConn escapes a string for use as
! as an SQL identifier, such as a table or column name. Note that the
! escaping required for identifiers is different than what is required
! for string literals, so you must be careful to use the correct function.
! Strings are surrounded by single quotes, while identifiers are
! surrounded by double quotes.
!
!
!
!
! As with strings, you must escape identifiers that were received from
! an untrustworthy source to prevent SQL injection> attacks
! wherein unwanted SQL commands are fed to your database.
!
!
!
!
!
! size_t PQescapeIdentifierConn (PGconn *conn,
! char *to, const char *from, size_t length,
! int *error);
!
!
!
!
! PQescapeIdentifierConn> writes an escaped version of the
! from> string to the to> buffer, surrounding
! the identifier with double quotes, escaping special characters so that
! they cannot cause any harm, and adding a terminating zero byte.
! The parameter from> points to the first character of the
! string that is to be escaped, and the length> parameter
! gives the number of bytes in this string. A terminating zero byte is not
! required, and should not be counted in length>. (If a
! terminating zero byte is found before length> bytes are
! processed, PQescapeIdentifierConn> stops at the zero; the
! behavior is thus rather like strncpy>.) to>
! shall point to a buffer that is able to hold at least three more bytes
! than twice the value of length>, otherwise the behavior is
! undefined. Behavior is likewise undefined if the to> and
! from> strings overlap.
!
!
!
! If the error> parameter is not NULL, then
! *error> is set to zero on success, nonzero on error.
! Presently the only possible error conditions involve invalid multibyte
! encoding in the source string. The output string is still generated
! on error, but it can be expected that the server will reject it as
! malformed. On error, a suitable message is stored in the
! conn> object, whether or not error> is NULL.
!
!
!
! PQescapeIdentifierConn> returns the number of bytes written
! to to>, not including the terminating zero byte.
!
!
!
PQescapeByteaConn
*** a/src/interfaces/libpq/exports.txt
--- b/src/interfaces/libpq/exports.txt
***************
*** 153,155 **** PQresultSetInstanceData 150
--- 153,156 ----
PQfireResultCreateEvents 151
PQconninfoParse 152
PQinitOpenSSL 153
+ PQescapeIdentifierConn 154
*** a/src/interfaces/libpq/fe-exec.c
--- b/src/interfaces/libpq/fe-exec.c
***************
*** 3058,3063 **** PQescapeString(char *to, const char *from, size_t length)
--- 3058,3168 ----
static_std_strings);
}
+ /*
+ * Escape an arbitrary string as an SQL identifier.
+ *
+ * This is similar to the backend function quote_identifier(), but we don't
+ * attempt to assess whether quoting is actually needed. To do that, we'd
+ * need the server's list of keywords, which is not available here (and might
+ * differ depending on the server version). So we just quote unconditionally.
+ *
+ * This function will up to, but not more than, 2*length+3 bytes to the output
+ * buffer. A terminating NUL character is added to the output string, whether
+ * the input is NUL-terminated or not.
+ *
+ * Returns the actual length of the output (not counting the terminating NUL).
+ */
+ size_t
+ PQescapeIdentifierConn(PGconn *conn, char *to, const char *from,
+ size_t length, int *error)
+ {
+ const char *source = from;
+ char *target = to;
+ size_t remaining = length;
+
+ if (!conn)
+ {
+ /* force empty-string result */
+ *to = '\0';
+ if (error)
+ *error = 1;
+ return 0;
+ }
+
+ if (error)
+ *error = 0;
+
+ /* Write opening double-quote. */
+ *target++ = '"';
+
+ while (remaining > 0 && *source != '\0')
+ {
+ char c = *source;
+ int len;
+ int i;
+
+ /* Fast path for plain ASCII */
+ if (!IS_HIGHBIT_SET(c))
+ {
+ /* Apply quoting if needed */
+ if (c == '"')
+ *target++ = c;
+ /* Copy the character */
+ *target++ = c;
+ source++;
+ remaining--;
+ continue;
+ }
+
+ /* Slow path for possible multibyte characters */
+ len = pg_encoding_mblen(conn->client_encoding, source);
+
+ /* Copy the character */
+ for (i = 0; i < len; i++)
+ {
+ if (remaining == 0 || *source == '\0')
+ break;
+ *target++ = *source++;
+ remaining--;
+ }
+
+ /*
+ * If we hit premature end of string (ie, incomplete multibyte
+ * character), try to pad out to the correct length with spaces. We
+ * may not be able to pad completely, but we will always be able to
+ * insert at least one pad space (since we'd not have quoted a
+ * multibyte character). This should be enough to make a string that
+ * the server will error out on.
+ */
+ if (i < len)
+ {
+ if (error)
+ *error = 1;
+ if (conn)
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("incomplete multibyte character\n"));
+ for (; i < len; i++)
+ {
+ /*
+ * The output buffer must be 2n+3 bytes, but the extra 3 are
+ * reserved for leading and trailing quotes and terminating;
+ * NUL, so we have room for exactly 2 output bytes per input
+ * character.
+ */
+ if (((size_t) (target - (to + 1))) / 2 >= length)
+ break;
+ *target++ = ' ';
+ }
+ break;
+ }
+ }
+
+ /* Write closing double quote and terminating NUL. */
+ *target++ = '"';
+ *target = '\0';
+
+ return target - to;
+ }
/* HEX encoding support for bytea */
static const char hextbl[] = "0123456789abcdef";
*** a/src/interfaces/libpq/libpq-fe.h
--- b/src/interfaces/libpq/libpq-fe.h
***************
*** 471,476 **** extern int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, in
--- 471,478 ----
extern size_t PQescapeStringConn(PGconn *conn,
char *to, const char *from, size_t length,
int *error);
+ extern size_t PQescapeIdentifierConn(PGconn *conn, char *to, const char *from,
+ size_t length, int *error);
extern unsigned char *PQescapeByteaConn(PGconn *conn,
const unsigned char *from, size_t from_length,
size_t *to_length);