Skip to content

Commit

Permalink
test for out of bounds long long (#807)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
phlptp and pre-commit-ci[bot] authored Nov 30, 2022
1 parent 8f8344b commit ca9a128
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
10 changes: 9 additions & 1 deletion include/CLI/TypeTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -816,11 +816,15 @@ inline std::string type_name() {
/// Convert to an unsigned integral
template <typename T, enable_if_t<std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
bool integral_conversion(const std::string &input, T &output) noexcept {
if(input.empty()) {
if(input.empty() || input.front() == '-') {
return false;
}
char *val = nullptr;
errno = 0;
std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0);
if(errno == ERANGE) {
return false;
}
output = static_cast<T>(output_ll);
if(val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll) {
return true;
Expand All @@ -841,7 +845,11 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
return false;
}
char *val = nullptr;
errno = 0;
std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0);
if(errno == ERANGE) {
return false;
}
output = static_cast<T>(output_ll);
if(val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll) {
return true;
Expand Down
25 changes: 25 additions & 0 deletions tests/AppTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1995,6 +1995,31 @@ TEST_CASE_METHOD(TApp, "typeCheck", "[app]") {
CHECK_THROWS_AS(run(), CLI::ValidationError);
}

TEST_CASE_METHOD(TApp, "NeedsTrue", "[app]") {
std::string str;
app.add_option("-s,--string", str);
app.add_flag("--opt1")->check([&](const std::string &) {
return (str != "val_with_opt1") ? std::string("--opt1 requires --string val_with_opt1") : std::string{};
});

run();

args = {"--opt1"};
CHECK_THROWS_AS(run(), CLI::ValidationError);

args = {"--string", "val"};
run();

args = {"--string", "val", "--opt1"};
CHECK_THROWS_AS(run(), CLI::ValidationError);

args = {"--string", "val_with_opt1", "--opt1"};
run();

args = {"--opt1", "--string", "val_with_opt1"}; // order is not revelant
run();
}

// Check to make sure programmatic access to left over is available
TEST_CASE_METHOD(TApp, "AllowExtras", "[app]") {

Expand Down
80 changes: 80 additions & 0 deletions tests/OptionTypeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,86 @@ TEST_CASE_METHOD(TApp, "VectorIndexedValidator", "[optiontype]") {
CHECK_THROWS_AS(run(), CLI::ValidationError);
}

TEST_CASE_METHOD(TApp, "IntegerOverFlowShort", "[optiontype]") {
std::int16_t A{0};
std::uint16_t B{0};

app.add_option("-a", A);
app.add_option("-b", B);

args = {"-a", "2626254242"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "2626254242"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-26262"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-262624262525"};
CHECK_THROWS_AS(run(), CLI::ConversionError);
}

TEST_CASE_METHOD(TApp, "IntegerOverFlowInt", "[optiontype]") {
int A{0};
unsigned int B{0};

app.add_option("-a", A);
app.add_option("-b", B);

args = {"-a", "262625424225252"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "262625424225252"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-2626225252"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-26262426252525252"};
CHECK_THROWS_AS(run(), CLI::ConversionError);
}

TEST_CASE_METHOD(TApp, "IntegerOverFlowLong", "[optiontype]") {
std::int32_t A{0};
std::uint32_t B{0};

app.add_option("-a", A);
app.add_option("-b", B);

args = {"-a", "1111111111111111111111111111"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "1111111111111111111111111111"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-2626225252"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-111111111111111111111111"};
CHECK_THROWS_AS(run(), CLI::ConversionError);
}

TEST_CASE_METHOD(TApp, "IntegerOverFlowLongLong", "[optiontype]") {
std::int64_t A{0};
std::uint64_t B{0};

app.add_option("-a", A);
app.add_option("-b", B);

args = {"-a", "1111111111111111111111111111111111111111111111111111111111"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "1111111111111111111111111111111111111111111111111111111111"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-2626225252"};
CHECK_THROWS_AS(run(), CLI::ConversionError);

args = {"-b", "-111111111111111111111111111111111111111111111111111111111"};
CHECK_THROWS_AS(run(), CLI::ConversionError);
}

TEST_CASE_METHOD(TApp, "VectorUnlimString", "[optiontype]") {
std::vector<std::string> strvec;
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
Expand Down

0 comments on commit ca9a128

Please sign in to comment.