yaml-0.2.7 GetNextDocument() 命中断言在 Scanner::peek 中失败

yaml-0.2.7 GetNextDocument() hit assertion fail in Scanner::peek

yaml-cpp 团队和大家,

我们的产品从云服务提供商处收到大小不固定的 json 响应。我们目前使用一个初始大小为 16KB 的缓冲区来接收它,然后将它传递给 yaml 解析器(我们使用的是 yaml-0.2.7)。如果 json 文档在解析过程中不完整,我们希望 yaml 解析器抛出异常,我们会将缓冲区的大小加倍。

今天,我们在执行 parser.GetNextDocument(doc) 时遇到了一个显示 "Assertion failed: (!m_tokens.empty()), function peek, file .../yaml-cpp-0.2.7/src/scanner.cpp, line 41." 的断言。由于接收缓冲区较小,json 文档不完整。

在检查缓冲区并做了一些实验后,我发现如果某些字符按照某种模式丢失,扫描器中的断言将在 GetNextDocument 期间命中。例如对于'{"access": "abc"}',如果最后一个'}'丢失,那么断言将被命中。如果它是“{"access":”或“{"access"”,同样的事情也会发生。如果它是 '"{"access":"abc'(注意 abc 没有尾随双引号),它不会命中断言。

升级到最新的0.5.3版本会有帮助吗?我查看了源代码,发现 Scanner::peek 函数中的相同断言仍然存在。

这是命中断言的函数的源代码:

Token& Scanner::peek() {
{
    EnsureTokensInQueue();
    /** THIS ONE GOT HIT **/
    assert(!m_tokens.empty());  // should we be asserting here? I mean, we really just be checking
                                // if it's empty before peeking.
#if 0
    static Token *pLast = 0;
    if(pLast != &m_tokens.front())
        std::cerr << "peek: " << m_tokens.front() << "\n";
    pLast = &m_tokens.front();
#endif

    return m_tokens.front();
}

非常感谢您的帮助! :)

这是在 0.5.3 中修复的,虽然我不确定它是什么时候修复的。我添加了 tests for your examples,它们按预期通过(通过抛出异常)。