当JSON中存在非法字符时,如何防止JSON解析器崩溃?

时间:2014-11-06 09:27:39

标签: c++ c json rapidjson

由于某些通信错误,我有时会收到带有一些非法字符的JSON字符串:     "{messageType\" : \"Test1\", \"from\" : \"F2D0B5C6-9875-46B5-8D4F\"}����1"

这些非法字符使我的JSON解析器中断。我正在使用RapidJSON JSON解析器(C / C ++)。 你能告诉我是否有一种方法可以从字符串中过滤掉这些不需要的字符,并验证json字符串的完整性。

5 个答案:

答案 0 :(得分:5)

这不是解析器中的错误。解析器在null终止符为空格之前验证尾随字符。并在发生错误时返回错误代码。但是如果没有空终止符,则可能导致分段错误,类似于strlen()

在较新版本的RapidJSON中,有一个kParseStopWhenDoneFlag。启用后,解析器将在完整的JSON值后停止读取尾随字符。 E.g。

Document d;
const char* s =
    "{messageType\" : \"Test1\", \"from\" : \"F2D0B5C6-9875-46B5-8D4F\"}����1";
d.Parse<kParseStopWhenDoneFlag>(s);
assert(!d.HasParseError());

通过使用此标志,解析器将在阅读}后停止,而不报告错误。

指南中尚未记录。请参阅https://github.com/miloyip/rapidjson/pull/83

中的讨论

答案 1 :(得分:2)

我认为您应该考虑滚动自己的预处理函数,该函数遍历JSON字符串中的每个字符,搜索不属于您的合法集的字符,并使用空格删除或替换它们。然后将新修复的字符串传递给RapidJSON。

最好先检测一下你的comms问题(因此JSON可能不完整或不正确),然后扔掉并重试整个会话,而不是将数据“修补”为你想在这里解决你的短期问题(程序崩溃),但很容易产生数据不一致和其他更微妙和难以诊断的问题。

此外,如果您在字符串末尾看到大部分错误的数据,我认为您应该仔细检查您的问题实际上是使用通信 - 您在这里给出的情况看起来更像是未正确终止的字符串缓冲区在字符串结束后还有额外的垃圾(未初始化的内存) - 也许您希望C ++清除(设置为零)分配的缓冲区?

答案 2 :(得分:2)

提交错误报告。 JSON解析器应接受您抛出的任何输入并返回相应的错误消息。如果它崩溃,这听起来像一个漏洞,可能允许您的应用程序被黑客攻击。可能最好找到一个不同的解析器。

接收方永远不应修改JSON数据以使其正常工作。它应该按原样使用,如果它不是可接受的数据,那么它应该被拒绝。如果存在&#34;通信错误&#34;这是由于您的代码中的错误,修复错误。如果它们是由于服务器错误,请向编写服务器代码的人抱怨。如果它们是真正的传输错误,您怎么知道您没有保持JSON有效的更改,例如付款金额从100美元变为900美元?

答案 3 :(得分:1)

您可以在字符串中列出允许的字符,并检查json流的每个字符是否在allowed_string中。 示例:

std::string allowed = "abcdefghijklmnopqrstuvwxyz0123456789.,{}[]\"";
std::string json = "{\"bar\":\"foo\",\"blah\":25}";
for(unsigned long int i = 0; i < json.length(); ++i)
  if(allowed.find(json[i]) == std::string::npos)
    throw IllegalJsonChar(json[i]);

答案 4 :(得分:1)

如果您的系统符合POSIX.1,则可以使用iconv

您可以进行系统调用(Linux / iOS等):

iconv -f utf-8 -t utf-8 -c file.txt

这将从utf-8转换为utf-8,跳过任何无效字符。

您可以使用iconv(3)执行相同的操作,并进行一些编程。