From: Joe Conway Date: Sun, 30 Nov 2003 20:52:37 +0000 (+0000) Subject: Make PQescapeBytea and byteaout consistent with each other, and X-Git-Tag: REL7_3_5~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8582f21afdb0a9241b915e56fc2ddb50dcd0509c;p=postgresql 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 --- diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index e4f3f7adab..10ea9bfccb 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 e0bf6b6857..9c3faaf2a4 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 214f2929fd..ae507d30e9 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;