You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Invalid command line containing "%canonical_option%" causes hang when what() invoked on resulting exception. #163
Tested on program_options from boost 1.91.0, built on linux with g++ 13.3.0 on Ubuntu subsystem on Windows. Tested as well with program_options 1.81.0 on windows compiled with vc17, and found to be impacted.
During fuzzing, found that providing the option -%canonical_option%
will cause a hang in any program that uses program_options and uses err.what() to print the invalid argument. My assumption is the field %canonical_option% is used in a string used in error reporting, and is repeatedly replaced with the user's invalid argument. If the user's invalid argument contains this magic string, the attempted replacements will continue forever.
Additionally, strings appended onto the end of this invalid argument will cause increasing memory usage, likely eventually running out of memory. I do not know the behavior in this case - if what() has additional error handling to catch a memory allocation failure, and the program will recover, or if this will result in a crash. The memory consumption appears to grow linearly - even providing multiple %canonical_option% flags, e.g. -%canonical_option%%canonical_option%%canonical_option%` seems to only cause linear growth in memory usage as the program runs. There may be additional substitutions that could be affected, but this is the only one that my fuzzing found.
Security implications: Generally, program_options is only used for processing command lines, so this only affects machines where a malicious actor can run a command line, or inject arguments that end up on a command line. Generally, the only program affected is the program launched, but there are cases where the command line may be passed to a service which then does the parsing, possibly logging any error codes. In such cases, long running services can be caused to have an infinitely looping thread, which continuously allocates memory.
Example program reproducing this hang:
`
#include "boost/program_options/errors.hpp"
#include
int main()
{
boost::program_options::unknown_option err("-%canonical_option%");
std::cout << err.what() << std::endl;
return 0;
}
`
Program hangs and nothing is printed.
Confirmed: this is in program_options, not the shell.
unknown_option("-%canonical_option%").what() begins with "unrecognised option '%canonical_option%'". get_canonical_option_name() returns the original token, so %canonical_option% is replaced by -%canonical_option%. replace_token() then searches from offset zero again, immediately finds the newly inserted placeholder, and repeats forever. Any suffix increases the message on each iteration.
The minimal fix is to advance the search position past the inserted replacement (pos += to.size()) rather than restarting at zero. An allocation failure inside this loop also occurs from what() (non-throwing), so it is unlikely to be recoverable.
Activity
vprus commentedon Oct 29, 2026
Thanks for the bug report!
Are you sure the hang is in program_options and not in the Windows shell?
vprus commentedon Oct 29, 2026
Confirmed: this is in program_options, not the shell.
unknown_option("-%canonical_option%").what()begins with"unrecognised option '%canonical_option%'".get_canonical_option_name()returns the original token, so%canonical_option%is replaced by-%canonical_option%.replace_token()then searches from offset zero again, immediately finds the newly inserted placeholder, and repeats forever. Any suffix increases the message on each iteration.The minimal fix is to advance the search position past the inserted replacement (
pos += to.size()) rather than restarting at zero. An allocation failure inside this loop also occurs fromwhat()(non-throwing), so it is unlikely to be recoverable.vprus commentedon Oct 29, 2026
PR #164
vprus commentedon Oct 29, 2026
Thanks for the report! It should be fixed now.
tbrightbill commentedon Oct 30, 2026
Thanks for the incredibly rapid fix! That fix looks good to me!