Skip to content

Commit 9fcc601

Browse files
committed
Fixing json parser issue when using streams with escaped characters.
1 parent 6839a46 commit 9fcc601

File tree

2 files changed

+21
-40
lines changed

2 files changed

+21
-40
lines changed

Release/src/json/json_parsing.cpp

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,8 @@ void convert_append_unicode_code_unit(JSON_Parser<char>::Token &token, utf16char
716716
template <typename CharType>
717717
inline bool JSON_Parser<CharType>::handle_unescape_char(Token &token)
718718
{
719+
token.has_unescape_symbol = true;
720+
719721
// This function converts unescaped character pairs (e.g. "\t") into their ASCII or Unicode representations (e.g. tab sign)
720722
// Also it handles \u + 4 hexadecimal digits
721723
auto ch = NextCharacter();
@@ -784,6 +786,7 @@ inline bool JSON_Parser<CharType>::handle_unescape_char(Token &token)
784786
template <typename CharType>
785787
bool JSON_Parser<CharType>::CompleteStringLiteral(Token &token)
786788
{
789+
token.has_unescape_symbol = false;
787790
auto ch = NextCharacter();
788791
while ( ch != '"' )
789792
{
@@ -836,13 +839,18 @@ bool JSON_StringParser<CharType>::CompleteStringLiteral(typename JSON_Parser<Cha
836839

837840
if (ch == '\\')
838841
{
839-
token.string_val.resize(m_position - start - 1);
840-
if (token.string_val.size() > 0)
841-
memcpy(&token.string_val[0], start, (m_position - start - 1)*sizeof(CharType));
842+
const size_t numChars = m_position - start - 1;
843+
const size_t prevSize = token.string_val.size();
844+
token.string_val.resize(prevSize + numChars);
845+
memcpy(const_cast<CharType *>(token.string_val.c_str() + prevSize), start, numChars * sizeof(CharType));
842846

843-
token.has_unescape_symbol = true;
847+
if (!JSON_StringParser<CharType>::handle_unescape_char(token))
848+
{
849+
return false;
850+
}
844851

845-
return finish_parsing_string_with_unescape_char(token);
852+
// Reset start position and continue.
853+
start = m_position;
846854
}
847855
else if (ch >= CharType(0x0) && ch < CharType(0x20))
848856
{
@@ -852,47 +860,16 @@ bool JSON_StringParser<CharType>::CompleteStringLiteral(typename JSON_Parser<Cha
852860
ch = JSON_StringParser<CharType>::NextCharacter();
853861
}
854862

855-
token.string_val.resize(m_position - start - 1);
856-
if (token.string_val.size() > 0)
857-
memcpy(&token.string_val[0], start, (m_position - start - 1)*sizeof(CharType));
863+
const size_t numChars = m_position - start - 1;
864+
const size_t prevSize = token.string_val.size();
865+
token.string_val.resize(prevSize + numChars);
866+
memcpy(const_cast<CharType *>(token.string_val.c_str() + prevSize), start, numChars * sizeof(CharType));
858867

859868
token.kind = JSON_Parser<CharType>::Token::TKN_StringLiteral;
860869

861870
return true;
862871
}
863872

864-
template <typename CharType>
865-
bool JSON_StringParser<CharType>::finish_parsing_string_with_unescape_char(typename JSON_Parser<CharType>::Token &token)
866-
{
867-
// This function handles parsing the string when an unescape character is encountered.
868-
// It is called once the part before the unescape char is copied to the token.string_val string
869-
870-
typename JSON_Parser<CharType>::int_type ch;
871-
872-
if (!JSON_StringParser<CharType>::handle_unescape_char(token))
873-
return false;
874-
875-
while ((ch = JSON_StringParser<CharType>::NextCharacter()) != '"')
876-
{
877-
if (ch == '\\')
878-
{
879-
if (!JSON_StringParser<CharType>::handle_unescape_char(token))
880-
return false;
881-
}
882-
else
883-
{
884-
if (ch == eof<CharType>())
885-
return false;
886-
887-
token.string_val.push_back(static_cast<CharType>(ch));
888-
}
889-
}
890-
891-
token.kind = JSON_StringParser<CharType>::Token::TKN_StringLiteral;
892-
893-
return true;
894-
}
895-
896873
template <typename CharType>
897874
void JSON_Parser<CharType>::GetNextToken(typename JSON_Parser<CharType>::Token& result)
898875
{

Release/tests/functional/json/parsing_tests.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ TEST(escaping_control_characters)
278278
const auto &v = json::value::parse(str);
279279
VERIFY_IS_TRUE(v.is_string());
280280
VERIFY_ARE_EQUAL(expectedStr, v.serialize());
281+
282+
// Try parsing a stringstream.
283+
const auto &ssv = json::value::parse(ss);
284+
VERIFY_ARE_EQUAL(expectedStr, ssv.serialize());
281285
}
282286
}
283287

0 commit comments

Comments
 (0)