summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/command/math.rst3
-rw-r--r--Source/cmProjectCommand.cxx3
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/project/VersionMax.cmake32
4 files changed, 37 insertions, 2 deletions
diff --git a/Help/command/math.rst b/Help/command/math.rst
index 3cbe719e56..ddb1ec63cf 100644
--- a/Help/command/math.rst
+++ b/Help/command/math.rst
@@ -8,7 +8,8 @@ Evaluate a mathematical expression.
math(EXPR <variable> "<expression>" [OUTPUT_FORMAT <format>])
Evaluates a mathematical ``<expression>`` and sets ``<variable>`` to the
-resulting value.
+resulting value. The result of the expression must be representable as a
+64-bit signed integer.
The mathematical expression must be given as a string (i.e. enclosed in
double quotation marks). An example is ``"5 * (10 + 13)"``.
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 1ce6c70f62..a25fd42d10 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -229,7 +229,8 @@ bool cmProjectCommand(std::vector<std::string> const& args,
std::array<std::string, MAX_VERSION_COMPONENTS> version_components;
if (cmp0096 == cmPolicies::OLD || cmp0096 == cmPolicies::WARN) {
- char vb[MAX_VERSION_COMPONENTS][std::numeric_limits<unsigned>::digits10];
+ char vb[MAX_VERSION_COMPONENTS]
+ [std::numeric_limits<unsigned>::digits10 + 2];
unsigned v[MAX_VERSION_COMPONENTS] = { 0, 0, 0, 0 };
const int vc = std::sscanf(version.c_str(), "%u.%u.%u.%u", &v[0], &v[1],
&v[2], &v[3]);
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 8f43a51803..69146993bd 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -22,6 +22,7 @@ run_cmake(VersionInvalid)
run_cmake(VersionMissingLanguages)
run_cmake(VersionMissingValueOkay)
run_cmake(VersionTwice)
+run_cmake(VersionMax)
run_cmake(CMP0048-OLD)
run_cmake(CMP0048-OLD-VERSION)
diff --git a/Tests/RunCMake/project/VersionMax.cmake b/Tests/RunCMake/project/VersionMax.cmake
new file mode 100644
index 0000000000..e955364384
--- /dev/null
+++ b/Tests/RunCMake/project/VersionMax.cmake
@@ -0,0 +1,32 @@
+cmake_policy(SET CMP0048 NEW)
+cmake_policy(SET CMP0096 OLD)
+
+enable_language(C)
+include(CheckTypeSize)
+check_type_size(unsigned __sizeOfUnsigned BUILTIN_TYPES_ONLY LANGUAGE C)
+
+# We can't use math() to compute this because it only supports up to
+# 64-bit signed integers, so hard-code the types we expect to encounter
+if(__sizeOfUnsigned EQUAL 0)
+ message(STATUS "Multi-architecture build, skipping project version check")
+ return()
+elseif(__sizeOfUnsigned EQUAL 4)
+ set(maxVal 4294967295)
+elseif(__sizeOfUnsigned EQUAL 8)
+ set(maxVal 18446744073709551615)
+else()
+ message(FATAL_ERROR
+ "Test needs to be updated for unsigned integer size ${__sizeOfUnsigned}")
+endif()
+
+# The real value of this test is when an address sanitizer is enabled.
+# It catches situations where the size of the buffer used to compute or
+# hold the version components as strings is too small.
+project(ProjectA VERSION ${maxVal}.${maxVal}.${maxVal}.${maxVal} LANGUAGES NONE)
+
+if(NOT ${PROJECT_VERSION_MAJOR} EQUAL ${maxVal})
+ message(FATAL_ERROR "Project version number parsing failed round trip.\n"
+ "Expected: ${maxVal}\n"
+ "Computed: ${PROJECT_VERSION_MAJOR}"
+ )
+endif()