? src/interfaces/libpq/.deps ? src/interfaces/libpq/libpq.so.4 Index: src/include/c.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/c.h,v retrieving revision 1.190 diff -c -r1.190 c.h *** src/include/c.h 15 Oct 2005 02:49:41 -0000 1.190 --- src/include/c.h 26 Oct 2005 05:42:58 -0000 *************** *** 478,483 **** --- 478,484 ---- #define NameStr(name) ((name).data) #define SQL_STR_DOUBLE(ch) ((ch) == '\'' || (ch) == '\\') + #define SQL_IDENT_DOUBLE(ch) ((ch) == '"') #define ESCAPE_STRING_SYNTAX 'E' /* ---------------------------------------------------------------- Index: src/interfaces/libpq/exports.txt =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/exports.txt,v retrieving revision 1.5 diff -c -r1.5 exports.txt *** src/interfaces/libpq/exports.txt 21 Oct 2005 15:21:21 -0000 1.5 --- src/interfaces/libpq/exports.txt 26 Oct 2005 05:42:58 -0000 *************** *** 125,127 **** --- 125,128 ---- lo_create 123 PQinitSSL 124 PQregisterThreadLock 125 + PQescapeIdentifier 126 Index: src/interfaces/libpq/fe-exec.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v retrieving revision 1.176 diff -c -r1.176 fe-exec.c *** src/interfaces/libpq/fe-exec.c 15 Oct 2005 02:49:48 -0000 1.176 --- src/interfaces/libpq/fe-exec.c 26 Oct 2005 05:43:00 -0000 *************** *** 2373,2378 **** --- 2373,2414 ---- } /* + * Escaping arbitrary strings to get valid SQL identifier strings. + * + * Replaces " with "". + * + * length is the length of the source string. (Note: if a terminating NUL + * is encountered sooner, PQescapeIdentifier stops short of "length"; the behavior + * is thus rather like strncpy.) + * + * For safety the buffer at "to" must be at least 2*length + 1 bytes long. + * 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 + PQescapeIdentifier(char *to, const char *from, size_t length) + { + const char *source = from; + char *target = to; + size_t remaining = length; + + while (remaining > 0 && *source != '\0') + { + if (SQL_IDENT_DOUBLE(*source)) + *target++ = *source; + *target++ = *source++; + remaining--; + } + + /* Write the terminating NUL character. */ + *target = '\0'; + + return target - to; + } + + /* * PQescapeBytea - converts from binary string to the * minimal encoding necessary to include the string in an SQL * INSERT statement with a bytea type column as the target. Index: src/interfaces/libpq/libpq-fe.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/interfaces/libpq/libpq-fe.h,v retrieving revision 1.120 diff -c -r1.120 libpq-fe.h *** src/interfaces/libpq/libpq-fe.h 15 Oct 2005 02:49:48 -0000 1.120 --- src/interfaces/libpq/libpq-fe.h 26 Oct 2005 05:43:00 -0000 *************** *** 436,441 **** --- 436,442 ---- /* Quoting strings before inclusion in queries. */ extern size_t PQescapeString(char *to, const char *from, size_t length); + extern size_t PQescapeIdentifier(char *to, const char *from, size_t length); extern unsigned char *PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen); extern unsigned char *PQunescapeBytea(const unsigned char *strtext, Index: doc/src/sgml/libpq.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/libpq.sgml,v retrieving revision 1.197 diff -c -r1.197 libpq.sgml *** doc/src/sgml/libpq.sgml 24 Oct 2005 15:38:36 -0000 1.197 --- doc/src/sgml/libpq.sgml 26 Oct 2005 05:43:02 -0000 *************** *** 2253,2258 **** --- 2253,2321 ---- + + Escaping Identifier for Inclusion in SQL Commands + + PQescapeIdentifier + escaping strings + + + PQescapeIdentifier escapes a string for use + as an identifier name within an SQL command. For example; table names, + column names, view names and user names are all identifiers. + Double quotes (") must be escaped to prevent them from being interpreted + specially by the SQL parser. PQescapeIdentifier 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 still necessary to do escaping of identifiers when + using functions that support parameterized queries such as PQexecParams or + its sibling routines. Only literal values are automatically escaped + using these functions, not identifiers. + + + size_t PQescapeIdentifier (char *to, const char *from, size_t length); + + + + + The parameter from points to the first character of the string + that is to be escaped, and the length parameter gives the + number of characters 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, PQescapeIdentifier 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 character than twice + the value of length, otherwise the behavior is + undefined. A call to PQescapeIdentifier writes an escaped + version of the from string to the to + buffer, replacing special characters so that they cannot cause any + harm, and adding a terminating zero byte. The double quotes that + may surround PostgreSQL identifiers are not + included in the result string; they should be provided in the SQL + command that the result is inserted into. + + + PQescapeIdentifier returns the number of characters written + to to, not including the terminating zero byte. + + + Behavior is undefined if the to and from + strings overlap. + + Escaping Binary Strings for Inclusion in SQL Commands