Boost Spirit 解析器在输入时崩溃

Boost Spirit parser crashes on input

我有一个使用 qi::double_ 数字解析器的 boost spirit 解析器。我遇到用户数据包含 uuid 字符串的情况:

"00573e443ef1ec10b5a1f23ac8a69c43c415cedf"

我在下面的 spirit pow10_helper() 函数中遇到了崩溃。测试更多它似乎发生在任何以数字开头,后跟 e 和另一个数字的字符串。例如 1e999 也会崩溃。要重现崩溃,请尝试:

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main()
{
    double x;
    std::string s = "1e999";
    auto a = s.begin();
    auto b = s.end();
    qi::parse(a, b, qi::double_, x); // <--- crash/assert in debug mode
}

我使用 spirit 是因为它的原始性能(qi::double_ 大约比 strtod() 快 2 倍)。我的问题是,有没有办法解决这个限制?切换到较慢的解析器会很痛苦,但如果您有特别的建议,请告诉我。

相关boost代码崩溃(boost/spirit/home/support/detail/pow10.hpp)供参考:

template <>
struct pow10_helper<double>
{
    static double call(unsigned dim)
    {
        static double const exponents[] =
        {
            1e0,   1e1,   1e2,   1e3,   1e4,   1e5,   1e6,   1e7,   1e8,    1e9,
            ...
            1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308,
        };
        BOOST_ASSERT(dim < sizeof(exponents)/sizeof(double));
        return exponents[dim]; // <--- crash here, dim is 999 which is >308
    }
};

附带说明一下,这似乎是 in spirit 实现中的 巨大 错误。您应该能够通过传入一个虚拟输入值(如 1e999.

来轻松地使任何解析双打的精神应用程序崩溃。

这是一个已知问题,已在 1_57_0 AFAIR

中修复

这是关于它的邮件列表讨论:

11 月 7 日,Joel de Guzman 写道:

This is now fixed in the develop branch along with a whole slew of improvements in floating point precision parsing (the corner cases). There are some backward incompatible changes, but it should only affect those who are using the real parser policies, in patrticular, those who specialize parse_frac_n. The changes will be documented in due time.