【发布时间】:2015-01-06 02:11:45
【问题描述】:
我有一个使用 qi::double_ 数字解析器的 boost Spirit 解析器。我遇到用户数据包含 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
}
我使用 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
}
};
作为旁注,这似乎是精神实现中的一个巨大错误。您应该能够通过传入一个虚拟输入值(如1e999)轻松地使任何解析双精度的精神应用程序崩溃。
【问题讨论】:
-
指出了安全隐患。好消息是它是一个断言,但仍然如此。大额负债
标签: c++ parsing boost boost-spirit