diff options
author | Andrew Dunstan <andrew@dunslane.net> | 2014-06-03 16:11:31 -0400 |
---|---|---|
committer | Andrew Dunstan <andrew@dunslane.net> | 2014-06-03 16:11:31 -0400 |
commit | 0ad1a816320a2b539a51628e2a0b1e83ff096b1d (patch) | |
tree | b65753b2035c2e21b60504bd014d2df106dca7ff /src/backend/utils/adt/json.c | |
parent | f30015b6d794c15d52abbb3df3a65081fbefb1ed (diff) | |
download | postgresql-0ad1a816320a2b539a51628e2a0b1e83ff096b1d.tar.gz postgresql-0ad1a816320a2b539a51628e2a0b1e83ff096b1d.zip |
Do not escape a unicode sequence when escaping JSON text.
Previously, any backslash in text being escaped for JSON was doubled so
that the result was still valid JSON. However, this led to some perverse
results in the case of Unicode sequences, These are now detected and the
initial backslash is no longer escaped. All other backslashes are
still escaped. No validity check is performed, all that is looked for is
\uXXXX where X is a hexidecimal digit.
This is a change from the 9.2 and 9.3 behaviour as noted in the Release
notes.
Per complaint from Teodor Sigaev.
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r-- | src/backend/utils/adt/json.c | 21 |
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 < ' ') |