1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-04-29 12:13:52 +00:00

Overflow (#84)

* Overflowing an integer conversion now results in a conversion failure

* CMake improvements for VERSION and inital packing support

* Fix for recent addition of overflow check

* Conan file now gets version from Version.hpp file too
This commit is contained in:
Henry Schreiner 2018-03-10 09:50:25 +01:00 committed by GitHub
parent 316363061b
commit 79a1847605
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 9 deletions

View File

@ -1,9 +1,19 @@
cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
project(CLI11 LANGUAGES CXX)
set(VERSION_REGEX "#define CLI11_VERSION[ \t]+\"(.+)\"")
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
# Read in the line containing the version
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/CLI/Version.hpp"
VERSION_STRING REGEX ${VERSION_REGEX})
# Pick out just the version
string(REGEX REPLACE ${VERSION_REGEX} "\\1" VERSION_STRING "${VERSION_STRING}")
project(CLI11 LANGUAGES CXX VERSION ${VERSION_STRING})
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
# User settable
set(CLI_CXX_STD "11" CACHE STRING "The CMake standard to require")
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
@ -70,6 +80,18 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/CLI DESTINATION include)
# to Config.cmake (otherwise we'd have a custom config and would
# import Targets.cmake
# Add the version in a CMake readable way
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
CLI11ConfigVersion.cmake
VERSION ${CLI11_VERSION}
COMPATIBILITY AnyNewerVersion
)
# Make version available in the install
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/CLI11ConfigVersion.cmake"
DESTINATION lib/cmake/CLI11)
# Make an export target
install(TARGETS CLI11
EXPORT CLI11Targets)
@ -129,3 +151,24 @@ if(CLI_EXAMPLES)
add_subdirectory(examples)
endif()
# Packaging support
set(CPACK_PACKAGE_VENDOR "github.com/CLIUtils/CLI11")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Command line interface")
set(CPACK_PACKAGE_VERSION_MAJOR ${CLI11_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${CLI11_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${CLI11_VERSION_PATCH})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
# CPack collects *everything* except what's listed here.
set(CPACK_SOURCE_IGNORE_FILES
/.git
/dist
/.*build.*
/\\\\.DS_Store
/.*\\\\.egg-info
/var
/Pipfile.*$
)
include(CPack)

View File

@ -15,7 +15,11 @@ download_project(PROJ googletest
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# CMake warning suppression will not be needed in version 1.9
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE BOOL "")
add_subdirectory(${googletest_SOURCE_DIR} ${googletest_SOURCE_DIR} EXCLUDE_FROM_ALL)
unset(CMAKE_SUPPRESS_DEVELOPER_WARNINGS)
if (CMAKE_CONFIGURATION_TYPES)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}

View File

@ -1,14 +1,24 @@
from conans import ConanFile, CMake
from conans.tools import load
import re
def get_version():
try:
content = load("include/CLI/Version.hpp")
version = re.search(r'#define CLI11_VERSION "(.*)"', content).group(1)
return version
except Exception:
return None
class HelloConan(ConanFile):
name = "CLI11"
version = "1.3.0"
version = get_version()
url = "https://github.com/CLIUtils/CLI11"
settings = "os", "compiler", "arch", "build_type"
license = "BSD 3 clause"
description = "Command Line Interface toolkit for C++11"
exports_sources = "LICENCE", "include/*", "cmake/*", "CMakeLists.txt", "tests/*"
exports_sources = "LICENSE", "README.md", "include/*", "cmake/*", "CMakeLists.txt", "tests/*"
def build(self): # this is not building a library, just tests
cmake = CMake(self)

View File

@ -79,8 +79,9 @@ template <typename T,
bool lexical_cast(std::string input, T &output) {
try {
size_t n = 0;
output = static_cast<T>(std::stoll(input, &n, 0));
return n == input.size();
long long output_ll = std::stoll(input, &n, 0);
output = static_cast<T>(output_ll);
return n == input.size() && static_cast<long long>(output) == output_ll;
} catch(const std::invalid_argument &) {
return false;
} catch(const std::out_of_range &) {
@ -97,8 +98,9 @@ bool lexical_cast(std::string input, T &output) {
try {
size_t n = 0;
output = static_cast<T>(std::stoull(input, &n, 0));
return n == input.size();
unsigned long long output_ll = std::stoull(input, &n, 0);
output = static_cast<T>(output_ll);
return n == input.size() && static_cast<unsigned long long>(output) == output_ll;
} catch(const std::invalid_argument &) {
return false;
} catch(const std::out_of_range &) {

View File

@ -348,6 +348,16 @@ TEST(Types, TypeName) {
EXPECT_EQ("TEXT", text2_name);
}
TEST(Types, OverflowSmall) {
char x;
auto strmax = std::to_string(INT8_MAX + 1);
EXPECT_FALSE(CLI::detail::lexical_cast(strmax, x));
unsigned char y;
strmax = std::to_string(UINT8_MAX + 1);
EXPECT_FALSE(CLI::detail::lexical_cast(strmax, y));
}
TEST(Types, LexicalCastInt) {
std::string signed_input = "-912";
int x_signed;
@ -357,7 +367,7 @@ TEST(Types, LexicalCastInt) {
std::string unsigned_input = "912";
unsigned int x_unsigned;
EXPECT_TRUE(CLI::detail::lexical_cast(unsigned_input, x_unsigned));
EXPECT_EQ(912, x_unsigned);
EXPECT_EQ((unsigned int)912, x_unsigned);
EXPECT_FALSE(CLI::detail::lexical_cast(signed_input, x_unsigned));