【发布时间】:2016-08-17 03:39:01
【问题描述】:
我们直接从boost's documentation举个例子:
#include <iostream>
#include <string>
#include <boost/program_options.hpp>
int main(int const ac, char** const av){
// Declare the supported options.
namespace po = boost::program_options;
using namespace std;
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("compression", po::value<int>(), "set compression level")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
if (vm.count("help")) {
cout << desc << "\n";
return 1;
}
if (vm.count("compression")) {
cout << "Compression level was set to "
<< vm["compression"].as<int>() << ".\n";
} else {
cout << "Compression level was not set.\n";
}
}
程序运行正常。
但是,当使用 gcc 的 sanitizer(或 clang 的)编译时:
g++ -std=c++1z -o main main.cpp -fsanitize=undefined -lboost_program_options
它会产生以下运行时错误:
./main --compression="1" 134
/usr/include/boost/any.hpp:243:16: runtime error: downcast of address 0x000001153fb0 which does not point to an object of type 'holder'
0x000001153fb0: note: object is of type 'boost::any::holder<int>'
00 00 00 00 20 bc 42 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 31 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'boost::any::holder<int>'
Compression level was set to 1.
我已将问题提炼为更小的问题:
#include <iostream>
#include <string>
#include <boost/program_options.hpp>
int main(int const argc, char** const argv){
using namespace boost::program_options;
//create description
options_description desc("");
//add entry
desc.add_options()
("foo",value<std::string>(),"desc");
//create variable map
variables_map vm;
//store variables in map
positional_options_description pod;
store(command_line_parser(argc, argv).options(desc).positional(pod).run(), vm);
notify(vm);
//get variable out of map
std::string foo;
if (vm.count("foo")){
foo = vm["foo"].as<std::string>(); //UNDEFINED BEHAVIOUR
}
}
编译:
g++ -std=c++1z -o main main.cpp -fsanitize=undefined -lboost_program_options
执行时:
./main --foo="hello"
/usr/include/boost/any.hpp:243:16: runtime error: downcast of address 0x000000d85fd0 which does not point to an object of type 'holder'
0x000000d85fd0: note: object is of type 'boost::any::holder<std::string>'
00 00 00 00 b0 c5 5e 90 f8 7f 00 00 98 5f d8 00 00 00 00 00 00 00 00 00 00 00 00 00 31 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'boost::any::holder<std::string>'
很明显,导致 UB 的变量映射的强制转换:
vm["foo"].as<std::string>()
这正是在线文档显示的方式。
这是误报吗?我的 boost 发行版中是否存在错误?
如果确实安全,我如何避免消毒剂标记它?
【问题讨论】:
-
Boost 的哪个版本? svn.boost.org/trac/boost/ticket/8958
-
@T.C.I 在 1.54.0 上。我更新到1.55.0,问题依旧。我想我会自己应用补丁......
-
我自己打了补丁,还是没有解决问题。第 257 行已更改为
? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held,但 sanitizer 仍然在第 257 行崩溃。 -
在 Ubuntu 上,我的包管理器没有显示任何高于 1.55.0 的内容。我想我会尝试从源代码构建。
标签: c++ boost runtime-error boost-program-options any