Opened 7 years ago
Last modified 7 years ago
#11935 new Bugs
boost::program_options::error_with_option_name.what() throws std::out_of_range when an empty option is used in the command input
| Reported by: | Owned by: | Vladimir Prus | |
|---|---|---|---|
| Milestone: | To Be Determined | Component: | program_options |
| Version: | Boost 1.60.0 | Severity: | Problem |
| Keywords: | program_options | Cc: |
Description
Hi,
After accidentally typing "-v . -" (without the quotes) into a Windows command line app written with boost::po, it crashed. The app's catch block (code below) calls boost::po::error_with_option_name.what() and this subsequently throws std::out_of_range().
It appears as though the empty option "-" confuses boost::program_options::strip_prefixes(const std::string& text) which is called with text value of "-", resulting in text.substr being called with a value of npos:
inline std::string strip_prefixes(const std::string& text)
{
// "--foo-bar" -> "foo-bar"[[BR]]
return text.substr(text.find_first_not_of("-/"));
}
Here's my code.
po::variables_map vm;
po::options_description desc("Options");
desc.add_options()
("folder,f", po::wvalue<wstring>()->required(), "Specify the name of the folder containing the C++ projects to check")
("list,l", "List the project file names as they're checked")
("verbose,v", "Verbose; Show the node values when finding non-SAK SCC values")
("help,?", "Show usage information")
;
po::positional_options_description pod;
pod.add("folder", -1);
try
{
po::store(po::wcommand_line_parser(argc, argv).options(desc).positional(pod).run(), vm);
po::notify(vm);
}
catch (const boost::program_options::error & e)
{
cerr << w32::fg_red << e.what() << w32::restore << endl;
return ERROR_UNHANDLED_EXCEPTION;
}
I am using Boost 1.60 on Windows 7 (64-bit) with Visual Studio 2015 Update 1.
Cheers
Mark.

I just ran into this problem too, though in my case I didn't pass in an empty option. I was testing a parameter with a length validator:
add_options() ("name", validated<string>(&m_name, length_max(64))->required(), "thing name")When passed a value longer than the limit the code threw a boost::program_options::error_with_option_name, as expected. Calling that exception's what() method crashed the program in the same way as the original reporter of this bug described, except that in this case the "original_token" value in the error's m_substitutions map was empty. When passed an empty string, strip_prefixes() throws the same out_of_range exception as above.
The following patch will fix the problem:
--- a/boost/program_options/errors.hpp 2013-12-04 00:17:17.000000000 -0500 +++ b/boost/program_options/errors.hpp 2016-01-28 20:03:12.994847938 -0500 @@ -26,7 +26,10 @@ inline std::string strip_prefixes(const std::string& text) { // "--foo-bar" -> "foo-bar" - return text.substr(text.find_first_not_of("-/")); + size_t pos = text.find_first_not_of("-/"); + if (pos == std::string::npos) + return std::string(); + return text.substr(pos); } /** Base class for all errors in the library. */I'm using boost 1.58 on Linux.