diff options
author | Joe Conway <mail@joeconway.com> | 2003-11-30 20:52:37 +0000 |
---|---|---|
committer | Joe Conway <mail@joeconway.com> | 2003-11-30 20:52:37 +0000 |
commit | 8582f21afdb0a9241b915e56fc2ddb50dcd0509c (patch) | |
tree | c424d69f32e09ae56d0188c2616756955323e9b6 | |
parent | 005887d1c07c1ee2264bbc5334a0fc78cd148b78 (diff) | |
download | postgresql-8582f21afdb0a9241b915e56fc2ddb50dcd0509c.tar.gz postgresql-8582f21afdb0a9241b915e56fc2ddb50dcd0509c.zip |
Make PQescapeBytea and byteaout consistent with each other, and
octal escape all octets outside the range 0x20 to 0x7e. This fixes
the problem pointed out by Sergey Yatskevich here:
http://archives.postgresql.org/pgsql-bugs/2003-11/msg00140.php
-rw-r--r-- | doc/src/sgml/datatype.sgml | 20 | ||||
-rw-r--r-- | src/backend/utils/adt/varlena.c | 14 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-exec.c | 9 |
3 files changed, 28 insertions, 15 deletions
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index e4f3f7adabd..10ea9bfccb8 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.106.2.3 2003/01/29 01:09:03 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.106.2.4 2003/11/30 20:52:37 joe Exp $ --> <chapter id="datatype"> @@ -1035,7 +1035,8 @@ SELECT b, char_length(b) FROM test2; strings are distinguished from characters strings by two characteristics: First, binary strings specifically allow storing octets of zero value and other <quote>non-printable</quote> - octets. Second, operations on binary strings process the actual + octets (defined as octets outside the range 32 to 126). + Second, operations on binary strings process the actual bytes, whereas the encoding and processing of character strings depends on locale settings. </para> @@ -1089,12 +1090,23 @@ SELECT b, char_length(b) FROM test2; <entry><literal>\\</literal></entry> </row> + <row> + <entry>0 to 31 and 127 to 255</entry> + <entry><quote>non-printable</quote> octets</entry> + <entry><literal>'\\<replaceable>xxx'</></literal> (octal value)</entry> + <entry><literal>SELECT '\\001'::bytea;</literal></entry> + <entry><literal>\001</literal></entry> + </row> + </tbody> </tgroup> </table> <para> - Note that the result in each of the examples in <xref linkend="datatype-binary-sqlesc"> was exactly one + The requirement to escape <quote>non-printable</quote> octets actually + varies depending on locale settings. In some instances you can get away + with leaving them unescaped. Note that the result in each of the + examples in <xref linkend="datatype-binary-sqlesc"> was exactly one octet in length, even though the output representation of the zero octet and backslash are more than one character. <type>Bytea</type> output octets are also escaped. In general, each @@ -1140,7 +1152,7 @@ SELECT b, char_length(b) FROM test2; <row> <entry>32 to 126</entry> <entry><quote>printable</quote> octets</entry> - <entry>ASCII representation</entry> + <entry>client character set representation</entry> <entry><literal>SELECT '\\176'::bytea;</literal></entry> <entry><literal>~</literal></entry> </row> diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index e0bf6b68576..9c3faaf2a4c 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.92.2.1 2003/04/23 18:19:23 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.92.2.2 2003/11/30 20:52:37 joe Exp $ * *------------------------------------------------------------------------- */ @@ -174,10 +174,10 @@ byteaout(PG_FUNCTION_ARGS) { if (*vp == '\\') len += 2; - else if (isprint((unsigned char) *vp)) - len++; - else + else if ((unsigned char) *vp < 0x20 || (unsigned char) *vp > 0x7e) len += 4; + else + len++; } rp = result = (char *) palloc(len); vp = vlena->vl_dat; @@ -188,9 +188,7 @@ byteaout(PG_FUNCTION_ARGS) *rp++ = '\\'; *rp++ = '\\'; } - else if (isprint((unsigned char) *vp)) - *rp++ = *vp; - else + else if ((unsigned char) *vp < 0x20 || (unsigned char) *vp > 0x7e) { val = *vp; rp[0] = '\\'; @@ -201,6 +199,8 @@ byteaout(PG_FUNCTION_ARGS) rp[1] = DIG(val & 03); rp += 4; } + else + *rp++ = *vp; } *rp = '\0'; PG_RETURN_CSTRING(result); diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 214f2929fd1..ae507d30e96 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.122 2002/09/04 20:31:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.122.2.1 2003/11/30 20:52:37 joe Exp $ * *------------------------------------------------------------------------- */ @@ -115,7 +115,8 @@ PQescapeString(char *to, const char *from, size_t length) * '\0' == ASCII 0 == \\000 * '\'' == ASCII 39 == \' * '\\' == ASCII 92 == \\\\ - * anything >= 0x80 ---> \\ooo (where ooo is an octal expression) + * anything < 0x20, or > 0x7e ---> \\ooo + * (where ooo is an octal expression) */ unsigned char * PQescapeBytea(unsigned char *bintext, size_t binlen, size_t *bytealen) @@ -134,7 +135,7 @@ PQescapeBytea(unsigned char *bintext, size_t binlen, size_t *bytealen) vp = bintext; for (i = binlen; i > 0; i--, vp++) { - if (*vp == 0 || *vp >= 0x80) + if (*vp < 0x20 || *vp > 0x7e) len += 5; /* '5' is for '\\ooo' */ else if (*vp == '\'') len += 2; @@ -153,7 +154,7 @@ PQescapeBytea(unsigned char *bintext, size_t binlen, size_t *bytealen) for (i = binlen; i > 0; i--, vp++) { - if (*vp == 0 || *vp >= 0x80) + if (*vp < 0x20 || *vp > 0x7e) { (void) sprintf(rp, "\\\\%03o", *vp); rp += 5; |