aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/json.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r--src/backend/utils/adt/json.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 2462111ecb3..8ca1ede83fb 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -2315,7 +2315,26 @@ escape_json(StringInfo buf, const char *str)
appendStringInfoString(buf, "\\\"");
break;
case '\\':
- appendStringInfoString(buf, "\\\\");
+ /*
+ * Unicode escapes are passed through as is. There is no
+ * requirement that they denote a valid character in the
+ * server encoding - indeed that is a big part of their
+ * usefulness.
+ *
+ * All we require is that they consist of \uXXXX where
+ * the Xs are hexadecimal digits. It is the responsibility
+ * of the caller of, say, to_json() to make sure that the
+ * unicode escape is valid.
+ *
+ * In the case of a jsonb string value being escaped, the
+ * only unicode escape that should be present is \u0000,
+ * all the other unicode escapes will have been resolved.
+ */
+ if (p[1] == 'u' && isxdigit(p[2]) && isxdigit(p[3])
+ && isxdigit(p[4]) && isxdigit(p[5]))
+ appendStringInfoCharMacro(buf, *p);
+ else
+ appendStringInfoString(buf, "\\\\");
break;
default:
if ((unsigned char) *p < ' ')