Commit ca9a12872010732b91ab928230c488c9b3c1ba0b

Authored by Philip Top
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>
include/CLI/TypeTools.hpp
... ... @@ -816,11 +816,15 @@ inline std::string type_name() {
816 816 /// Convert to an unsigned integral
817 817 template <typename T, enable_if_t<std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
818 818 bool integral_conversion(const std::string &input, T &output) noexcept {
819   - if(input.empty()) {
  819 + if(input.empty() || input.front() == '-') {
820 820 return false;
821 821 }
822 822 char *val = nullptr;
  823 + errno = 0;
823 824 std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0);
  825 + if(errno == ERANGE) {
  826 + return false;
  827 + }
824 828 output = static_cast<T>(output_ll);
825 829 if(val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll) {
826 830 return true;
... ... @@ -841,7 +845,11 @@ bool integral_conversion(const std::string &amp;input, T &amp;output) noexcept {
841 845 return false;
842 846 }
843 847 char *val = nullptr;
  848 + errno = 0;
844 849 std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0);
  850 + if(errno == ERANGE) {
  851 + return false;
  852 + }
845 853 output = static_cast<T>(output_ll);
846 854 if(val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll) {
847 855 return true;
... ...
tests/AppTest.cpp
... ... @@ -1995,6 +1995,31 @@ TEST_CASE_METHOD(TApp, &quot;typeCheck&quot;, &quot;[app]&quot;) {
1995 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 2023 // Check to make sure programmatic access to left over is available
1999 2024 TEST_CASE_METHOD(TApp, "AllowExtras", "[app]") {
2000 2025  
... ...
tests/OptionTypeTest.cpp
... ... @@ -405,6 +405,86 @@ TEST_CASE_METHOD(TApp, &quot;VectorIndexedValidator&quot;, &quot;[optiontype]&quot;) {
405 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 488 TEST_CASE_METHOD(TApp, "VectorUnlimString", "[optiontype]") {
409 489 std::vector<std::string> strvec;
410 490 std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
... ...