Make PQescapeBytea and byteaout consistent with each other, and
authorJoe Conway <[email protected]>
Sun, 30 Nov 2003 20:52:37 +0000 (20:52 +0000)
committerJoe Conway <[email protected]>
Sun, 30 Nov 2003 20:52:37 +0000 (20:52 +0000)
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
src/backend/utils/adt/varlena.c
src/interfaces/libpq/fe-exec.c

index e4f3f7adabd83047dcd6701dc131b51528d36c13..10ea9bfccb848b9fea09548a21019bbee01530f9 100644 (file)
@@ -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>
index e0bf6b68576562325d68107c538f19aafcd5aaa0..9c3faaf2a4c889d03e252a337565a8061a46b99f 100644 (file)
@@ -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);
index 214f2929fd1d83f2651071e714666fa52b0cf4e9..ae507d30e96defd53026c948827b78c4a8b980ed 100644 (file)
@@ -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;