Commit 79eaa908 authored by Ben Boeckel's avatar Ben Boeckel

cmListCommand: add a policy for failing on invalid indicies

parent 1f1fdff7
Pipeline #214857 waiting for manual action with stages
in 7 minutes and 41 seconds
......@@ -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
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
=================================
......
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
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`.
......@@ -34,11 +34,34 @@
namespace {
bool GetIndexArg(char const* arg, int* idx)
bool GetIndexArg(char const* arg, int* idx, cmMakefile& mf)
{
long 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.
......@@ -166,7 +189,7 @@ bool HandleGetCommand(std::vector<std::string> const& args,
size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size() - 1; cc++) {
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"));
return false;
}
......@@ -378,7 +401,7 @@ bool HandleInsertCommand(std::vector<std::string> const& args,
// expand the variable
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"));
return false;
}
......@@ -1303,11 +1326,11 @@ bool HandleSublistCommand(std::vector<std::string> const& args,
int start;
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"));
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"));
return false;
}
......@@ -1366,7 +1389,7 @@ bool HandleRemoveAtCommand(std::vector<std::string> const& args,
size_t nitem = varArgsExpanded.size();
for (cc = 2; cc < args.size(); ++cc) {
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"));
return false;
}
......
......@@ -359,7 +359,10 @@ class cmMakefile;
3, 20, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0120, \
"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_FOR_EACH_POLICY_ID(POLICY) \
......
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}<--")
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: --><--
cmake_policy(SET CMP0121 NEW)
include(CMP0121-ERANGE-Common.cmake)
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: --><--
cmake_policy(SET CMP0121 OLD)
include(CMP0121-ERANGE-Common.cmake)
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: --><--
include(CMP0121-ERANGE-Common.cmake)
set(listvar a b c d e)
list(GET listvar 0 2junk out)
message("GET: -->${out}<--")
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: --><--
cmake_policy(SET CMP0121 NEW)
include(CMP0121-GET-Common.cmake)
cmake_policy(SET CMP0121 OLD)
include(CMP0121-GET-Common.cmake)
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<--
include(CMP0121-GET-Common.cmake)
set(listvar a b c d e)
list(INSERT listvar junk2 new)
message("INSERT: -->${listvar}<--")
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<--
cmake_policy(SET CMP0121 NEW)
include(CMP0121-INSERT-Common.cmake)
cmake_policy(SET CMP0121 OLD)
include(CMP0121-INSERT-Common.cmake)
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<--
include(CMP0121-INSERT-Common.cmake)
set(listvar a b c d e)
list(REMOVE_AT listvar 0 invalid)
message("REMOVE_AT: -->${listvar}<--")
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<--
cmake_policy(SET CMP0121 NEW)
include(CMP0121-REMOVE_AT-Common.cmake)
cmake_policy(SET CMP0121 OLD)
include(CMP0121-REMOVE_AT-Common.cmake)
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<--
include(CMP0121-REMOVE_AT-Common.cmake)
set(listvar a b c d e)
list(SUBLIST listvar 0 invalid out)
message("SUBLIST-length: -->${out}<--")
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: --><--
cmake_policy(SET CMP0121 NEW)
include(CMP0121-SUBLIST-length-Common.cmake)
cmake_policy(SET CMP0121 OLD)
include(CMP0121-SUBLIST-length-Common.cmake)
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: --><--
include(CMP0121-SUBLIST-length-Common.cmake)
set(listvar a b c d e)
list(SUBLIST listvar invalid 2 out)
message("SUBLIST-start: -->${out}<--")
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: --><--
cmake_policy(SET CMP0121 NEW)
include(CMP0121-SUBLIST-start-Common.cmake)
cmake_policy(SET CMP0121 OLD)
include(CMP0121-SUBLIST-start-Common.cmake)
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<--
include(CMP0121-SUBLIST-start-Common.cmake)
cmake_minimum_required(VERSION 3.20)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
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 ()
......@@ -131,6 +131,7 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
endif()
add_RunCMake_test(CMP0118)
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
# CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS variable, which both the VS and Xcode
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment