From 3b221dc64e1e9eb74b48a97fba4bfa18fad4bf4a Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 21 Jun 2017 22:57:23 -0400 Subject: [PATCH v2] Fix output of char node fields WRITE_CHAR_FIELD() didn't do any escaping, so that for example a zero byte would cause the whole output string to be truncated. To fix, pass the char through outToken(), so it is escaped like a string. Adjust the reading side to handle this. --- src/backend/nodes/outfuncs.c | 20 +++++++++++++++++++- src/backend/nodes/readfuncs.c | 3 ++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 3a23f0bb16..b0abe9ec10 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -32,6 +32,8 @@ #include "utils/datum.h" #include "utils/rel.h" +static void outChar(StringInfo str, char c); + /* * Macros to simplify output of different kinds of fields. Use these @@ -62,7 +64,8 @@ /* Write a char field (ie, one ascii character) */ #define WRITE_CHAR_FIELD(fldname) \ - appendStringInfo(str, " :" CppAsString(fldname) " %c", node->fldname) + (appendStringInfo(str, " :" CppAsString(fldname) " "), \ + outChar(str, node->fldname)) /* Write an enumerated-type field as an integer code */ #define WRITE_ENUM_FIELD(fldname, enumtype) \ @@ -140,6 +143,21 @@ outToken(StringInfo str, const char *s) } } +/* + * Convert one char. Goes through outToken() so that special characters are + * escaped. + */ +static void +outChar(StringInfo str, char c) +{ + char in[2]; + + in[0] = c; + in[1] = '\0'; + + outToken(str, in); +} + static void _outList(StringInfo str, const List *node) { diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 2988e8bd16..1380703cbc 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -86,7 +86,8 @@ #define READ_CHAR_FIELD(fldname) \ token = pg_strtok(&length); /* skip :fldname */ \ token = pg_strtok(&length); /* get field value */ \ - local_node->fldname = token[0] + /* avoid overhead of calling debackslash() for one char */ \ + local_node->fldname = (length == 0) ? '\0' : (token[0] == '\\' ? token[1] : token[0]) /* Read an enumerated-type field that was written as an integer code */ #define READ_ENUM_FIELD(fldname, enumtype) \ -- 2.13.1