1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-16 14:08:35 +08:00

cmListCommand: add a policy for failing on invalid indicies

This commit is contained in:
Ben Boeckel
2021-02-16 10:29:37 -05:00
parent 1f1fdff7fa
commit 79eaa908dc
58 changed files with 287 additions and 8 deletions

View File

@@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or to determine whether to report an error on use of deprecated macros or
functions. functions.
Policies Introduced by CMake 3.21
=================================
.. toctree::
:maxdepth: 1
CMP0121: The list command detects invalid indicies </policy/CMP0121>
Policies Introduced by CMake 3.20 Policies Introduced by CMake 3.20
================================= =================================

21
Help/policy/CMP0121.rst Normal file
View File

@@ -0,0 +1,21 @@
CMP0121
-------
.. versionadded:: 3.21
The :command:`list` command now detects invalid indicies.
Prior to CMake version 3.21, the :command:`list` command's ``GET``,
``INSERT``, ``SUBLIST``, and ``REMOVE_AT`` subcommands did not detect invalid
index arguments.
The ``OLD`` behavior of this policy is for invalid indicies to be treated as
their integer value (if any) at the start of the string. For example,
``2good4you`` is a ``2`` and ``not_an_integer`` is a ``0``. The ``NEW``
behavior is for invalid indicies to trigger an error.
This policy was introduced in CMake version 3.21. CMake version |release|
warns when the policy is not set and uses ``OLD`` behavior. Use the
:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
.. include:: DEPRECATED.txt

View File

@@ -0,0 +1,7 @@
list-index-arg-parsing
----------------------
* The :command:`list` command's ``GET``, ``INSERT``, ``SUBLIST``, and
``REMOVE_AT`` subcommands now error with invalid (i.e., non-integer) values
are given as any of their index arguments based on the setting of policy
:policy:`CMP0121`.

View File

@@ -34,11 +34,34 @@
namespace { namespace {
bool GetIndexArg(char const* arg, int* idx) bool GetIndexArg(char const* arg, int* idx, cmMakefile& mf)
{ {
long value; long value;
if (!cmStrToLong(arg, &value)) { if (!cmStrToLong(arg, &value)) {
// An error was detected. switch (mf.GetPolicyStatus(cmPolicies::CMP0121)) {
case cmPolicies::WARN: {
// Default is to warn and use old behavior OLD behavior is to allow
// compatibility, so issue a warning and use the previous behavior.
std::string warn =
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0121),
" Invalid list index \"", arg, "\".");
mf.IssueMessage(MessageType::AUTHOR_WARNING, warn);
break;
}
case cmPolicies::OLD:
// OLD behavior is to allow compatibility, so just ignore the
// situation.
break;
case cmPolicies::NEW:
return false;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
std::string msg =
cmStrCat(cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0121),
" Invalid list index \"", arg, "\".");
mf.IssueMessage(MessageType::FATAL_ERROR, msg);
break;
}
} }
// Truncation is happening here, but it had always been happening here. // Truncation is happening here, but it had always been happening here.
@@ -166,7 +189,7 @@ bool HandleGetCommand(std::vector<std::string> const& args,
size_t nitem = varArgsExpanded.size(); size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size() - 1; cc++) { for (cc = 2; cc < args.size() - 1; cc++) {
int item; int item;
if (!GetIndexArg(args[cc].c_str(), &item)) { if (!GetIndexArg(args[cc].c_str(), &item, status.GetMakefile())) {
status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
return false; return false;
} }
@@ -378,7 +401,7 @@ bool HandleInsertCommand(std::vector<std::string> const& args,
// expand the variable // expand the variable
int item; int item;
if (!GetIndexArg(args[2].c_str(), &item)) { if (!GetIndexArg(args[2].c_str(), &item, status.GetMakefile())) {
status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
return false; return false;
} }
@@ -1303,11 +1326,11 @@ bool HandleSublistCommand(std::vector<std::string> const& args,
int start; int start;
int length; int length;
if (!GetIndexArg(args[2].c_str(), &start)) { if (!GetIndexArg(args[2].c_str(), &start, status.GetMakefile())) {
status.SetError(cmStrCat("index: ", args[2], " is not a valid index")); status.SetError(cmStrCat("index: ", args[2], " is not a valid index"));
return false; return false;
} }
if (!GetIndexArg(args[3].c_str(), &length)) { if (!GetIndexArg(args[3].c_str(), &length, status.GetMakefile())) {
status.SetError(cmStrCat("index: ", args[3], " is not a valid index")); status.SetError(cmStrCat("index: ", args[3], " is not a valid index"));
return false; return false;
} }
@@ -1366,7 +1389,7 @@ bool HandleRemoveAtCommand(std::vector<std::string> const& args,
size_t nitem = varArgsExpanded.size(); size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size(); ++cc) { for (cc = 2; cc < args.size(); ++cc) {
int item; int item;
if (!GetIndexArg(args[cc].c_str(), &item)) { if (!GetIndexArg(args[cc].c_str(), &item, status.GetMakefile())) {
status.SetError(cmStrCat("index: ", args[cc], " is not a valid index")); status.SetError(cmStrCat("index: ", args[cc], " is not a valid index"));
return false; return false;
} }

View File

@@ -359,7 +359,10 @@ class cmMakefile;
3, 20, 0, cmPolicies::WARN) \ 3, 20, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0120, \ SELECT(POLICY, CMP0120, \
"The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \ "The WriteCompilerDetectionHeader module is removed.", 3, 20, 0, \
cmPolicies::WARN) cmPolicies::WARN) \
SELECT(POLICY, CMP0121, \
"The list() command now validates parsing of index arguments.", 3, \
21, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \ #define CM_FOR_EACH_POLICY_ID(POLICY) \

View File

@@ -0,0 +1,8 @@
set(listvar a b c d e)
list(GET listvar
18446744073709551616 # 2^64
2147483648 # 2^31
4294967296 # 2^32; errors out-of-range as -2147483643 due to underflow
out)
message("ERANGE: -->${out}<--")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\):
list index: 18446744073709551616 is not a valid index
Call Stack \(most recent call first\):
CMP0121-ERANGE-NEW.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
ERANGE: --><--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 NEW)
include(CMP0121-ERANGE-Common.cmake)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\):
list index: (-2147483643|2147483647) out of range \(-5, 4\)
Call Stack \(most recent call first\):
CMP0121-ERANGE-OLD.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
ERANGE: --><--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 OLD)
include(CMP0121-ERANGE-Common.cmake)

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,18 @@
CMake Warning \(dev\) at CMP0121-ERANGE-Common.cmake:3 \(list\):
Policy CMP0121 is not set: The list\(\) command now validates parsing of
index arguments. Run "cmake --help-policy CMP0121" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Invalid list index "18446744073709551616".
Call Stack \(most recent call first\):
CMP0121-ERANGE-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Error at CMP0121-ERANGE-Common.cmake:3 \(list\):
list index: (-2147483643|2147483647) out of range \(-5, 4\)
Call Stack \(most recent call first\):
CMP0121-ERANGE-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
ERANGE: --><--

View File

@@ -0,0 +1,2 @@
include(CMP0121-ERANGE-Common.cmake)

View File

@@ -0,0 +1,4 @@
set(listvar a b c d e)
list(GET listvar 0 2junk out)
message("GET: -->${out}<--")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-GET-Common.cmake:3 \(list\):
list index: 2junk is not a valid index
Call Stack \(most recent call first\):
CMP0121-GET-NEW.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
GET: --><--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 NEW)
include(CMP0121-GET-Common.cmake)

View File

@@ -0,0 +1 @@
GET: -->a;c<--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 OLD)
include(CMP0121-GET-Common.cmake)

View File

@@ -0,0 +1,11 @@
CMake Warning \(dev\) at CMP0121-GET-Common.cmake:3 \(list\):
Policy CMP0121 is not set: The list\(\) command now validates parsing of
index arguments. Run "cmake --help-policy CMP0121" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Invalid list index "2junk".
Call Stack \(most recent call first\):
CMP0121-GET-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
GET: -->a;c<--

View File

@@ -0,0 +1,2 @@
include(CMP0121-GET-Common.cmake)

View File

@@ -0,0 +1,4 @@
set(listvar a b c d e)
list(INSERT listvar junk2 new)
message("INSERT: -->${listvar}<--")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-INSERT-Common.cmake:3 \(list\):
list index: junk2 is not a valid index
Call Stack \(most recent call first\):
CMP0121-INSERT-NEW.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
INSERT: -->a;b;c;d;e<--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 NEW)
include(CMP0121-INSERT-Common.cmake)

View File

@@ -0,0 +1 @@
INSERT: -->new;a;b;c;d;e<--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 OLD)
include(CMP0121-INSERT-Common.cmake)

View File

@@ -0,0 +1,11 @@
CMake Warning \(dev\) at CMP0121-INSERT-Common.cmake:3 \(list\):
Policy CMP0121 is not set: The list\(\) command now validates parsing of
index arguments. Run "cmake --help-policy CMP0121" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Invalid list index "junk2".
Call Stack \(most recent call first\):
CMP0121-INSERT-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
INSERT: -->new;a;b;c;d;e<--

View File

@@ -0,0 +1,2 @@
include(CMP0121-INSERT-Common.cmake)

View File

@@ -0,0 +1,4 @@
set(listvar a b c d e)
list(REMOVE_AT listvar 0 invalid)
message("REMOVE_AT: -->${listvar}<--")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-REMOVE_AT-Common.cmake:3 \(list\):
list index: invalid is not a valid index
Call Stack \(most recent call first\):
CMP0121-REMOVE_AT-NEW.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
REMOVE_AT: -->a;b;c;d;e<--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 NEW)
include(CMP0121-REMOVE_AT-Common.cmake)

View File

@@ -0,0 +1 @@
REMOVE_AT: -->b;c;d;e<--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 OLD)
include(CMP0121-REMOVE_AT-Common.cmake)

View File

@@ -0,0 +1,11 @@
CMake Warning \(dev\) at CMP0121-REMOVE_AT-Common.cmake:3 \(list\):
Policy CMP0121 is not set: The list\(\) command now validates parsing of
index arguments. Run "cmake --help-policy CMP0121" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Invalid list index "invalid".
Call Stack \(most recent call first\):
CMP0121-REMOVE_AT-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
REMOVE_AT: -->b;c;d;e<--

View File

@@ -0,0 +1,2 @@
include(CMP0121-REMOVE_AT-Common.cmake)

View File

@@ -0,0 +1,4 @@
set(listvar a b c d e)
list(SUBLIST listvar 0 invalid out)
message("SUBLIST-length: -->${out}<--")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-SUBLIST-length-Common.cmake:3 \(list\):
list index: invalid is not a valid index
Call Stack \(most recent call first\):
CMP0121-SUBLIST-length-NEW.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
SUBLIST-length: --><--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 NEW)
include(CMP0121-SUBLIST-length-Common.cmake)

View File

@@ -0,0 +1 @@
SUBLIST-length: --><--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 OLD)
include(CMP0121-SUBLIST-length-Common.cmake)

View File

@@ -0,0 +1,11 @@
CMake Warning \(dev\) at CMP0121-SUBLIST-length-Common.cmake:3 \(list\):
Policy CMP0121 is not set: The list\(\) command now validates parsing of
index arguments. Run "cmake --help-policy CMP0121" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Invalid list index "invalid".
Call Stack \(most recent call first\):
CMP0121-SUBLIST-length-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
SUBLIST-length: --><--

View File

@@ -0,0 +1,2 @@
include(CMP0121-SUBLIST-length-Common.cmake)

View File

@@ -0,0 +1,4 @@
set(listvar a b c d e)
list(SUBLIST listvar invalid 2 out)
message("SUBLIST-start: -->${out}<--")

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,8 @@
CMake Error at CMP0121-SUBLIST-start-Common.cmake:3 \(list\):
list index: invalid is not a valid index
Call Stack \(most recent call first\):
CMP0121-SUBLIST-start-NEW.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
SUBLIST-start: --><--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 NEW)
include(CMP0121-SUBLIST-start-Common.cmake)

View File

@@ -0,0 +1 @@
SUBLIST-start: -->a;b<--

View File

@@ -0,0 +1,2 @@
cmake_policy(SET CMP0121 OLD)
include(CMP0121-SUBLIST-start-Common.cmake)

View File

@@ -0,0 +1,11 @@
CMake Warning \(dev\) at CMP0121-SUBLIST-start-Common.cmake:3 \(list\):
Policy CMP0121 is not set: The list\(\) command now validates parsing of
index arguments. Run "cmake --help-policy CMP0121" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
Invalid list index "invalid".
Call Stack \(most recent call first\):
CMP0121-SUBLIST-start-WARN.cmake:2 \(include\)
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
SUBLIST-start: -->a;b<--

View File

@@ -0,0 +1,2 @@
include(CMP0121-SUBLIST-start-Common.cmake)

View File

@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.20)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@@ -0,0 +1,7 @@
include(RunCMake)
foreach (subcommand IN ITEMS ERANGE GET INSERT REMOVE_AT SUBLIST-length SUBLIST-start)
run_cmake(CMP0121-${subcommand}-WARN)
run_cmake(CMP0121-${subcommand}-OLD)
run_cmake(CMP0121-${subcommand}-NEW)
endforeach ()

View File

@@ -131,6 +131,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
endif() endif()
add_RunCMake_test(CMP0118) add_RunCMake_test(CMP0118)
add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) add_RunCMake_test(CMP0119 -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
add_RunCMake_test(CMP0121)
# The test for Policy 65 requires the use of the # The test for Policy 65 requires the use of the
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode # CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode