Commit ca9a12872010732b91ab928230c488c9b3c1ba0b
Committed by
GitHub
1 parent
8f8344bf
test for out of bounds long long (#807)
* test for out of bounds long long * style: pre-commit.ci fixes * change to use std types * style: pre-commit.ci fixes Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Showing
3 changed files
with
114 additions
and
1 deletions
include/CLI/TypeTools.hpp
| @@ -816,11 +816,15 @@ inline std::string type_name() { | @@ -816,11 +816,15 @@ inline std::string type_name() { | ||
| 816 | /// Convert to an unsigned integral | 816 | /// Convert to an unsigned integral |
| 817 | template <typename T, enable_if_t<std::is_unsigned<T>::value, detail::enabler> = detail::dummy> | 817 | template <typename T, enable_if_t<std::is_unsigned<T>::value, detail::enabler> = detail::dummy> |
| 818 | bool integral_conversion(const std::string &input, T &output) noexcept { | 818 | bool integral_conversion(const std::string &input, T &output) noexcept { |
| 819 | - if(input.empty()) { | 819 | + if(input.empty() || input.front() == '-') { |
| 820 | return false; | 820 | return false; |
| 821 | } | 821 | } |
| 822 | char *val = nullptr; | 822 | char *val = nullptr; |
| 823 | + errno = 0; | ||
| 823 | std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); | 824 | std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); |
| 825 | + if(errno == ERANGE) { | ||
| 826 | + return false; | ||
| 827 | + } | ||
| 824 | output = static_cast<T>(output_ll); | 828 | output = static_cast<T>(output_ll); |
| 825 | if(val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll) { | 829 | if(val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll) { |
| 826 | return true; | 830 | return true; |
| @@ -841,7 +845,11 @@ bool integral_conversion(const std::string &input, T &output) noexcept { | @@ -841,7 +845,11 @@ bool integral_conversion(const std::string &input, T &output) noexcept { | ||
| 841 | return false; | 845 | return false; |
| 842 | } | 846 | } |
| 843 | char *val = nullptr; | 847 | char *val = nullptr; |
| 848 | + errno = 0; | ||
| 844 | std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); | 849 | std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); |
| 850 | + if(errno == ERANGE) { | ||
| 851 | + return false; | ||
| 852 | + } | ||
| 845 | output = static_cast<T>(output_ll); | 853 | output = static_cast<T>(output_ll); |
| 846 | if(val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll) { | 854 | if(val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll) { |
| 847 | return true; | 855 | return true; |
tests/AppTest.cpp
| @@ -1995,6 +1995,31 @@ TEST_CASE_METHOD(TApp, "typeCheck", "[app]") { | @@ -1995,6 +1995,31 @@ TEST_CASE_METHOD(TApp, "typeCheck", "[app]") { | ||
| 1995 | CHECK_THROWS_AS(run(), CLI::ValidationError); | 1995 | CHECK_THROWS_AS(run(), CLI::ValidationError); |
| 1996 | } | 1996 | } |
| 1997 | 1997 | ||
| 1998 | +TEST_CASE_METHOD(TApp, "NeedsTrue", "[app]") { | ||
| 1999 | + std::string str; | ||
| 2000 | + app.add_option("-s,--string", str); | ||
| 2001 | + app.add_flag("--opt1")->check([&](const std::string &) { | ||
| 2002 | + return (str != "val_with_opt1") ? std::string("--opt1 requires --string val_with_opt1") : std::string{}; | ||
| 2003 | + }); | ||
| 2004 | + | ||
| 2005 | + run(); | ||
| 2006 | + | ||
| 2007 | + args = {"--opt1"}; | ||
| 2008 | + CHECK_THROWS_AS(run(), CLI::ValidationError); | ||
| 2009 | + | ||
| 2010 | + args = {"--string", "val"}; | ||
| 2011 | + run(); | ||
| 2012 | + | ||
| 2013 | + args = {"--string", "val", "--opt1"}; | ||
| 2014 | + CHECK_THROWS_AS(run(), CLI::ValidationError); | ||
| 2015 | + | ||
| 2016 | + args = {"--string", "val_with_opt1", "--opt1"}; | ||
| 2017 | + run(); | ||
| 2018 | + | ||
| 2019 | + args = {"--opt1", "--string", "val_with_opt1"}; // order is not revelant | ||
| 2020 | + run(); | ||
| 2021 | +} | ||
| 2022 | + | ||
| 1998 | // Check to make sure programmatic access to left over is available | 2023 | // Check to make sure programmatic access to left over is available |
| 1999 | TEST_CASE_METHOD(TApp, "AllowExtras", "[app]") { | 2024 | TEST_CASE_METHOD(TApp, "AllowExtras", "[app]") { |
| 2000 | 2025 |
tests/OptionTypeTest.cpp
| @@ -405,6 +405,86 @@ TEST_CASE_METHOD(TApp, "VectorIndexedValidator", "[optiontype]") { | @@ -405,6 +405,86 @@ TEST_CASE_METHOD(TApp, "VectorIndexedValidator", "[optiontype]") { | ||
| 405 | CHECK_THROWS_AS(run(), CLI::ValidationError); | 405 | CHECK_THROWS_AS(run(), CLI::ValidationError); |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | +TEST_CASE_METHOD(TApp, "IntegerOverFlowShort", "[optiontype]") { | ||
| 409 | + std::int16_t A{0}; | ||
| 410 | + std::uint16_t B{0}; | ||
| 411 | + | ||
| 412 | + app.add_option("-a", A); | ||
| 413 | + app.add_option("-b", B); | ||
| 414 | + | ||
| 415 | + args = {"-a", "2626254242"}; | ||
| 416 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 417 | + | ||
| 418 | + args = {"-b", "2626254242"}; | ||
| 419 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 420 | + | ||
| 421 | + args = {"-b", "-26262"}; | ||
| 422 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 423 | + | ||
| 424 | + args = {"-b", "-262624262525"}; | ||
| 425 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 426 | +} | ||
| 427 | + | ||
| 428 | +TEST_CASE_METHOD(TApp, "IntegerOverFlowInt", "[optiontype]") { | ||
| 429 | + int A{0}; | ||
| 430 | + unsigned int B{0}; | ||
| 431 | + | ||
| 432 | + app.add_option("-a", A); | ||
| 433 | + app.add_option("-b", B); | ||
| 434 | + | ||
| 435 | + args = {"-a", "262625424225252"}; | ||
| 436 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 437 | + | ||
| 438 | + args = {"-b", "262625424225252"}; | ||
| 439 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 440 | + | ||
| 441 | + args = {"-b", "-2626225252"}; | ||
| 442 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 443 | + | ||
| 444 | + args = {"-b", "-26262426252525252"}; | ||
| 445 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 446 | +} | ||
| 447 | + | ||
| 448 | +TEST_CASE_METHOD(TApp, "IntegerOverFlowLong", "[optiontype]") { | ||
| 449 | + std::int32_t A{0}; | ||
| 450 | + std::uint32_t B{0}; | ||
| 451 | + | ||
| 452 | + app.add_option("-a", A); | ||
| 453 | + app.add_option("-b", B); | ||
| 454 | + | ||
| 455 | + args = {"-a", "1111111111111111111111111111"}; | ||
| 456 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 457 | + | ||
| 458 | + args = {"-b", "1111111111111111111111111111"}; | ||
| 459 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 460 | + | ||
| 461 | + args = {"-b", "-2626225252"}; | ||
| 462 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 463 | + | ||
| 464 | + args = {"-b", "-111111111111111111111111"}; | ||
| 465 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 466 | +} | ||
| 467 | + | ||
| 468 | +TEST_CASE_METHOD(TApp, "IntegerOverFlowLongLong", "[optiontype]") { | ||
| 469 | + std::int64_t A{0}; | ||
| 470 | + std::uint64_t B{0}; | ||
| 471 | + | ||
| 472 | + app.add_option("-a", A); | ||
| 473 | + app.add_option("-b", B); | ||
| 474 | + | ||
| 475 | + args = {"-a", "1111111111111111111111111111111111111111111111111111111111"}; | ||
| 476 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 477 | + | ||
| 478 | + args = {"-b", "1111111111111111111111111111111111111111111111111111111111"}; | ||
| 479 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 480 | + | ||
| 481 | + args = {"-b", "-2626225252"}; | ||
| 482 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 483 | + | ||
| 484 | + args = {"-b", "-111111111111111111111111111111111111111111111111111111111"}; | ||
| 485 | + CHECK_THROWS_AS(run(), CLI::ConversionError); | ||
| 486 | +} | ||
| 487 | + | ||
| 408 | TEST_CASE_METHOD(TApp, "VectorUnlimString", "[optiontype]") { | 488 | TEST_CASE_METHOD(TApp, "VectorUnlimString", "[optiontype]") { |
| 409 | std::vector<std::string> strvec; | 489 | std::vector<std::string> strvec; |
| 410 | std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; | 490 | std::vector<std::string> answer{"mystring", "mystring2", "mystring3"}; |