From e628f82d1c64d9ff56b7dee93726f92903caadca Mon Sep 17 00:00:00 2001 From: Kevin DeJong Date: Thu, 31 Oct 2024 11:24:29 -0700 Subject: [PATCH] Fix validating min/maxLength with array types --- .../rules/resources/properties/StringLength.py | 15 ++++++++------- .../resources/properties/test_string_length.py | 12 ++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/cfnlint/rules/resources/properties/StringLength.py b/src/cfnlint/rules/resources/properties/StringLength.py index 819ac11890..4f2f78d013 100644 --- a/src/cfnlint/rules/resources/properties/StringLength.py +++ b/src/cfnlint/rules/resources/properties/StringLength.py @@ -9,7 +9,7 @@ import regex as re -from cfnlint.helpers import FUNCTIONS +from cfnlint.helpers import FUNCTIONS, ensure_list, is_function from cfnlint.jsonschema import ValidationError from cfnlint.rules import CloudFormationLintRule @@ -80,8 +80,8 @@ def maxLength(self, validator, mL, instance, schema): return # there are scenarios where Fn::Sub may not predictable so use # best judgement - if validator.is_type(instance, "object") and len(instance) == 1: - key = list(instance.keys())[0] + key, value = is_function(instance) + if key is not None: if key == "Fn::Sub": value = instance[key] if isinstance(value, str): @@ -93,7 +93,7 @@ def maxLength(self, validator, mL, instance, schema): validator, mL, self._fix_sub_string(value[0]), schema ) return - if schema.get("type") == "object": + if "object" in ensure_list(schema.get("type")): yield from self._non_string_max_length(instance, mL) # pylint: disable=unused-argument, arguments-renamed @@ -105,8 +105,8 @@ def minLength(self, validator, mL, instance, schema): # there are scenarios where Fn::Sub may not predictable so use # best judgement - if validator.is_type(instance, "object") and len(instance) == 1: - key = list(instance.keys())[0] + key, value = is_function(instance) + if key is not None: if key == "Fn::Sub": value = instance[key] if isinstance(value, str): @@ -118,5 +118,6 @@ def minLength(self, validator, mL, instance, schema): validator, mL, self._fix_sub_string(value[0]), schema ) return - if schema.get("type") == "object": + + if "object" in ensure_list(schema.get("type")): yield from self._non_string_min_length(instance, mL) diff --git a/test/unit/rules/resources/properties/test_string_length.py b/test/unit/rules/resources/properties/test_string_length.py index ebd161542f..77a3e55aab 100644 --- a/test/unit/rules/resources/properties/test_string_length.py +++ b/test/unit/rules/resources/properties/test_string_length.py @@ -37,6 +37,12 @@ def rule(): ({"foo": 1, "bar": {"Fn::Sub": "2"}}, 20, {"type": "object"}, 1), ({"foo": 1, "bar": {"Fn::Sub": ["2", {}]}}, 10, {"type": "object"}, 0), ({"foo": 1, "bar": {"Fn::Sub": ["2", {}]}}, 20, {"type": "object"}, 1), + ( + {"foo": 1, "bar": {"Fn::Sub": ["2", {}]}}, + 20, + {"type": ["string", "object"]}, + 1, + ), ], ) def test_min_length(instance, mL, expected, rule, schema, validator): @@ -65,6 +71,12 @@ def test_min_length(instance, mL, expected, rule, schema, validator): ({"foo": 1, "bar": {"Fn::Sub": "2"}}, 4, {"type": "object"}, 1), ({"foo": 1, "bar": {"Fn::Sub": ["2", {}]}}, 20, {"type": "object"}, 0), ({"foo": 1, "bar": {"Fn::Sub": ["2", {}]}}, 4, {"type": "object"}, 1), + ( + {"foo": 1, "bar": {"Fn::Sub": ["2", {}]}}, + 4, + {"type": ["string", "object"]}, + 1, + ), ], ) def test_max_length(instance, mL, expected, rule, schema, validator):