Make PQescapeBytea and byteaout consistent with each other, and
authorJoe Conway
Sun, 30 Nov 2003 20:55:09 +0000 (20:55 +0000)
committerJoe Conway
Sun, 30 Nov 2003 20:55:09 +0000 (20:55 +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 d47cee96338957c08f231cdd4b16262eaf523080..7707aed2a47189d197582f5f23527f8516eabac1 100644 (file)
@@ -1,5 +1,5 @@
 
 
  
@@ -1076,9 +1076,10 @@ SELECT b, char_length(b) FROM test2;
     strings are distinguished from characters strings by two
     characteristics: First, binary strings specifically allow storing
     octets of value zero and other non-printable
-    octets.  Second, operations on binary strings process the actual
-    bytes, whereas the encoding and processing of character strings
-    depends on locale settings.
+    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.
    
 
    
@@ -1131,14 +1132,25 @@ 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
-    octet in length, even though the output representation of the zero
-    octet and backslash are more than one character.
+    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.
    
 
    
@@ -1206,7 +1218,7 @@ SELECT b, char_length(b) FROM test2;
       
        32 to 126
        printable octets
-       ASCII representation
+       client character set representation
        SELECT '\\176'::bytea;
        ~
       
index 244e2fbc698ea2f18c5bfda5e99fd5b98f8beddd..8e01f9f539ef237cace2a8652127196d1e918406 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.107 2003/11/29 19:51:59 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.108 2003/11/30 20:55:09 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -186,10 +186,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 = VARDATA(vlena);
@@ -200,9 +200,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] = '\\';
@@ -213,6 +211,8 @@ byteaout(PG_FUNCTION_ARGS)
            rp[1] = DIG(val & 03);
            rp += 4;
        }
+       else
+           *rp++ = *vp;
    }
    *rp = '\0';
    PG_RETURN_CSTRING(result);
index 19cb840af714472b5c146c368ef7f2813d286372..84b7d2e1c19f8bf98a67ada4d4fc4adf1266a672 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.154 2003/11/29 19:52:11 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.155 2003/11/30 20:55:09 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2261,7 +2261,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(const unsigned char *bintext, size_t binlen, size_t *bytealen)
@@ -2280,7 +2281,7 @@ PQescapeBytea(const 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;
@@ -2299,7 +2300,7 @@ PQescapeBytea(const 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;