我有一个boost精神解析器,它使用qi::double_数值解析器。在用户数据包含uuid字符串的情况下:
"00573e443ef1ec10b5a1f23ac8a69c43c415cedf"
我在下面的精神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
}由于它的原始性能(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
}
};顺便提一句,这似乎是精神实现中的一个巨大缺陷。您应该能够很容易地崩溃任何精神应用程序,通过传入一个虚拟输入值(如1e999 )来解析双倍。
发布于 2015-01-06 02:22:59
这是一个已知的问题,已经在1_57_0 AFAIR中解决了。
下面是邮件列表中有关它的讨论:
11月7日,乔尔·德古兹曼写道:
随着浮点精度解析(角落案例)的一系列改进,现在开发分支中已经解决了这一问题。有一些向后不兼容的更改,但它应该只影响那些使用真正的解析器策略的人,在模式上,那些专门处理parse_frac_n的人。这些更改将在适当的时候被记录下来。
https://stackoverflow.com/questions/27791080
复制相似问题