From caf92856098ecfc9594deb597c4bef11f9277e96 Mon Sep 17 00:00:00 2001 From: Tobias Taschner Date: Sun, 19 Jan 2020 21:32:11 +0100 Subject: [PATCH] Improved JSON string parsing --- include/wx/private/json.h | 62 +++++++++++++++++++-------------------- src/msw/webview_edge.cpp | 5 +++- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/include/wx/private/json.h b/include/wx/private/json.h index 2e7bbaf7f8..f9ddff7fca 100644 --- a/include/wx/private/json.h +++ b/include/wx/private/json.h @@ -14,74 +14,72 @@ namespace wxJSON { // Decode a string literal including escape sequences -// If the input is not quoted string it will be returned as the input -wxString DecodeString(const wxString& str) +// Returns false if the input string is not a valid JSON string +bool DecodeString(const wxString& in, wxString* out) { - if (!str.starts_with('"') || !str.ends_with('"')) - return str; - - wxString result; - const wxWCharBuffer buf = str.wc_str(); + const wxWCharBuffer buf = in.wc_str(); + const wchar_t* ch = buf.data(); + // String has to chart with a quote + if (*(ch++) != '"') + return false; + out->reserve(buf.length()); const wchar_t* end = buf.data() + buf.length() - 1; - for (const wchar_t* ch = buf.data() + 1; ch < end; ++ch) + for (; ch < end; ++ch) { if (*ch == '\\') { switch (*(++ch)) { case 'b': - result.append('\b'); + out->append('\b'); break; case 'n': - result.append('\n'); + out->append('\n'); break; case 'r': - result.append('\r'); + out->append('\r'); break; case 't': - result.append('\t'); + out->append('\t'); break; - case 'v': - result.append('\v'); + case 'f': + out->append('\f'); break; - case '\'': - result.append('\''); + case '/': + out->append('/'); break; case '"': - result.append('"'); + out->append('"'); break; case '\\': - result.append('\\'); + out->append('\\'); break; case 'u': +#if SIZEOF_WCHAR_T == 2 + // In this case, we handle surrogates without doing anything special was wchar_t strings use UTF-17 encoding. if (wxIsxdigit(ch[1]) && wxIsxdigit(ch[2]) && wxIsxdigit(ch[3]) && wxIsxdigit(ch[4])) { - wxUChar uchar = wxHexToDec(wxString(&ch[3], 2)) | + wchar_t uchar = wxHexToDec(wxString(&ch[3], 2)) | wxHexToDec(wxString(&ch[1], 2)) >> 8; - result.append(uchar); + out->append(uchar); ch += 4; } +#else + #error Implement correct surrogate handling. +#endif break; - case 'x': - if (wxIsxdigit(ch[1]) && wxIsxdigit(ch[2])) - { - wxChar hchar = wxHexToDec(wxString(&ch[1], 2)); - result.append(hchar); - ch += 2; - } - break; - default: - result.append(*ch); + return false; break; } } else - result.append(*ch); + out->append(*ch); } - return result; + // String has to end with a quote + return (*ch) == '"'; } } // namespace JSON diff --git a/src/msw/webview_edge.cpp b/src/msw/webview_edge.cpp index 10f71b50e9..df38961a3f 100644 --- a/src/msw/webview_edge.cpp +++ b/src/msw/webview_edge.cpp @@ -811,7 +811,10 @@ bool wxWebViewEdge::RunScript(const wxString& javascript, wxString* output) if (RunScriptSync(wrapJS.GetUnwrappedOutputCode() + ";", &result)) { if (output) - *output = wxJSON::DecodeString(result); + // Try to decode JSON string or return original + // result if it's not a valid JSON string + if (!wxJSON::DecodeString(result, output)) + *output = result; result.clear(); }