From 8582f21afdb0a9241b915e56fc2ddb50dcd0509c Mon Sep 17 00:00:00 2001 From: Joe Conway Date: Sun, 30 Nov 2003 20:52:37 +0000 Subject: [PATCH] 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 --- doc/src/sgml/datatype.sgml | 20 ++++++++++++++++---- src/backend/utils/adt/varlena.c | 14 +++++++------- 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 @@ @@ -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 non-printable - 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. @@ -1089,12 +1090,23 @@ SELECT b, char_length(b) FROM test2; \\ + + 0 to 31 and 127 to 255 + non-printable octets + '\\xxx' (octal value) + SELECT '\\001'::bytea; + \001 + + - Note that the result in each of the examples in was exactly one + The requirement to escape non-printable 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 was exactly one octet in length, even though the output representation of the zero octet and backslash are more than one character. Bytea output octets are also escaped. In general, each @@ -1140,7 +1152,7 @@ SELECT b, char_length(b) FROM test2; 32 to 126 printable octets - ASCII representation + client character set representation SELECT '\\176'::bytea; ~ 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; -- 2.39.5