We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
E0002: Unknown exception while processing rule E1024: 'list' object has no attribute 'path'
### CloudFormation Lint Version

cfn-lint 0.77.10

### What operating system are you using?

Mac

### Describe the bug

When validation checks run on a the Cidr function `!Cidr [ ipBlock, count, cidrBits ]`, the count and cidrBits doesn't validate more complex functions like the `!If` in the example.

### Expected behavior

Doesn't throw unknown exception

### Reproduction template

```yaml
PublicSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs ""]
      CidrBlock: !If
        - defineYourOwnSubnetCIDR
        - !Ref FirstTierSubnet1CIDR
        - !Select
          - 0
          - !Cidr
            - 10.0.0.0/24
            - !If [3AZ, 16, 8]
            - 4
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/cfnlint/rules/functions/Cidr.py`
Content:
```
1 """
2 Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 SPDX-License-Identifier: MIT-0
4 """
5 import regex as re
6 
7 from cfnlint.helpers import REGEX_CIDR
8 from cfnlint.rules import CloudFormationLintRule, RuleMatch
9 
10 
11 class Cidr(CloudFormationLintRule):
12     """Check if Cidr values are correct"""
13 
14     id = "E1024"
15     shortdesc = "Cidr validation of parameters"
16     description = "Making sure the function CIDR is a list with valid values"
17     source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-cidr.html"
18     tags = ["functions", "cidr"]
19 
20     supported_functions = [
21         "Fn::FindInMap",
22         "Fn::Select",
23         "Ref",
24         "Fn::GetAtt",
25         "Fn::Sub",
26         "Fn::ImportValue",
27     ]
28 
29     def check_ip_block(self, value, path):
30         matches = []
31         if isinstance(value, dict):
32             if len(value) == 1:
33                 for index_key, _ in value.items():
34                     if index_key not in self.supported_functions:
35                         if index_key == "Fn::If":
36                             if len(value.get("Fn::If")) == 3 and isinstance(
37                                 value.get("Fn::If"), list
38                             ):
39                                 matches.extend(
40                                     self.check_ip_block(
41                                         value.get("Fn::If")[1],
42                                         path=path[:] + [index_key, 1],
43                                     )
44                                 )
45                                 matches.extend(
46                                     self.check_ip_block(
47                                         value.get("Fn::If")[2],
48                                         path=path[:] + [index_key, 2],
49                                     )
50                                 )
51                         else:
52                             message = "Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or Select for {0}"
53                             matches.append(
54                                 RuleMatch(
55                                     path, message.format("/".join(map(str, value)))
56                                 )
57                             )
58         elif isinstance(value, (str)):
59             if not re.match(REGEX_CIDR, value):
60                 message = "Cidr ipBlock should be a Cidr Range based string for {0}"
61                 matches.append(
62                     RuleMatch(path, message.format("/".join(map(str, path))))
63                 )
64         else:
65             message = "Cidr ipBlock should be a string for {0}"
66             matches.append(RuleMatch(path, message.format("/".join(map(str, path)))))
67 
68         return matches
69 
70     def check_count(self, value, path):
71         matches = []
72         count_parameters = []
73         if isinstance(value, dict):
74             if len(value) == 1:
75                 for index_key, index_value in value.items():
76                     if index_key not in self.supported_functions:
77                         if index_key == "Fn::If":
78                             if len(value.get("Fn::If")) == 3 and isinstance(
79                                 value.get("Fn::If"), list
80                             ):
81                                 matches.extend(
82                                     self.check_count(
83                                         value.get("Fn::If")[1],
84                                         path=path[:] + [index_key, 1],
85                                     )
86                                 )
87                                 matches.extend(
88                                     self.check_count(
89                                         value.get("Fn::If")[2],
90                                         path=path[:] + [index_key, 2],
91                                     )
92                                 )
93                         else:
94                             message = "Cidr count should be Int, Ref, or Select for {0}"
95                             matches.append(
96                                 RuleMatch(
97                                     path, message.format("/".join(map(str, path)))
98                                 )
99                             )
100                     if index_key == "Ref":
101                         count_parameters.append(index_value)
102         elif not isinstance(value, int):
103             message = "Cidr count should be a int for {0}"
104             extra_args = {
105                 "actual_type": type(value).__name__,
106                 "expected_type": int.__name__,
107             }
108             matches.append(
109                 RuleMatch(path, message.format("/".join(map(str, path))), **extra_args)
110             )
111 
112         return count_parameters, matches
113 
114     def check_size_mask(self, value, path):
115         matches = []
116         size_mask_parameters = []
117         if isinstance(value, dict):
118             if len(value) == 1:
119                 for index_key, index_value in value.items():
120                     if index_key not in self.supported_functions:
121                         if index_key == "Fn::If":
122                             if len(value.get("Fn::If")) == 3 and isinstance(
123                                 value.get("Fn::If"), list
124                             ):
125                                 matches.extend(
126                                     self.check_size_mask(
127                                         value.get("Fn::If")[1],
128                                         path=path[:] + [index_key, 1],
129                                     )
130                                 )
131                                 matches.extend(
132                                     self.check_size_mask(
133                                         value.get("Fn::If")[2],
134                                         path=path[:] + [index_key, 2],
135                                     )
136                                 )
137                         else:
138                             message = (
139                                 "Cidr sizeMask should be Int, Ref, or Select for {0}"
140                             )
141                             matches.append(
142                                 RuleMatch(
143                                     path, message.format("/".join(map(str, path)))
144                                 )
145                             )
146                     if index_key == "Ref":
147                         size_mask_parameters.append(index_value)
148         elif not isinstance(value, int):
149             message = "Cidr sizeMask should be a int for {0}"
150             extra_args = {
151                 "actual_type": type(value).__name__,
152                 "expected_type": int.__name__,
153             }
154             matches.append(
155                 RuleMatch(path, message.format("/".join(map(str, path))), **extra_args)
156             )
157 
158         return size_mask_parameters, matches
159 
160     def check_parameter_count(self, cfn, parameter_name):
161         """Check Count Parameter if used"""
162         matches = []
163         parameter_obj = cfn.get_parameters().get(parameter_name, {})
164         if parameter_obj:
165             tree = ["Parameters", parameter_name]
166             parameter_type = parameter_obj.get("Type")
167             if parameter_type == "Number":
168                 max_value = parameter_obj.get("MaxValue")
169                 min_value = parameter_obj.get("MinValue")
170                 if (not min_value) or min_value < 1 or min_value > 256:
171                     message = "Parameter for Cidr count have MinValue between 1 and 256 at {0}"
172                     matches.append(
173                         RuleMatch(
174                             tree + ["MinValue"],
175                             message.format("/".join(map(str, tree + ["MinValue"]))),
176                         )
177                     )
178                 if (not max_value) or max_value < 1 or max_value > 256:
179                     message = "Parameter for Cidr count have MaxValue between 1 and 256 at {0}"
180                     matches.append(
181                         RuleMatch(
182                             tree + ["MaxValue"],
183                             message.format("/".join(map(str, tree + ["MaxValue"]))),
184                         )
185                     )
186             else:
187                 message = "Parameter for Cidr count have be of Type Number at {0}"
188                 matches.append(
189                     RuleMatch(tree, message.format("/".join(map(str, tree))))
190                 )
191 
192         return matches
193 
194     def check_parameter_size_mask(self, cfn, parameter_name):
195         """Check SizeMask Parameter if used"""
196         matches = []
197         parameter_obj = cfn.get_parameters().get(parameter_name, {})
198         if parameter_obj:
199             tree = ["Parameters", parameter_name]
200             parameter_type = parameter_obj.get("Type")
201             if parameter_type == "Number":
202                 max_value = parameter_obj.get("MaxValue")
203                 min_value = parameter_obj.get("MinValue")
204                 if (not min_value) or min_value < 1 or min_value > 256:
205                     message = (
206                         "Parameter for Cidr sizeMask have MinValue between 1 and "
207                         "128 (for ipv6) and 32 (for ipv4) at {0}"
208                     )
209                     matches.append(
210                         RuleMatch(
211                             tree + ["MinValue"],
212                             message.format("/".join(map(str, tree + ["MinValue"]))),
213                         )
214                     )
215                 if (not max_value) or max_value < 1 or max_value > 256:
216                     message = (
217                         "Parameter for Cidr count have MaxValue between 1 and "
218                         "128 (for ipv6) and 32 (for ipv4) at {0}"
219                     )
220                     matches.append(
221                         RuleMatch(
222                             tree + ["MaxValue"],
223                             message.format("/".join(map(str, tree + ["MaxValue"]))),
224                         )
225                     )
226             else:
227                 message = "Parameter for Cidr count have be of Type Number at {0}"
228                 matches.append(
229                     RuleMatch(tree, message.format("/".join(map(str, tree))))
230                 )
231 
232         return matches
233 
234     def match(self, cfn):
235         matches = []
236 
237         cidr_objs = cfn.search_deep_keys("Fn::Cidr")
238 
239         count_parameters = []
240         size_mask_parameters = []
241 
242         for cidr_obj in cidr_objs:
243             cidr_value_obj = cidr_obj[-1]
244             tree = cidr_obj[:-1]
245             if isinstance(cidr_value_obj, list):
246                 if len(cidr_value_obj) in [2, 3]:
247                     ip_block_obj = cidr_value_obj[0]
248                     count_obj = cidr_value_obj[1]
249                     if len(cidr_value_obj) == 3:
250                         size_mask_obj = cidr_value_obj[2]
251                     else:
252                         size_mask_obj = None
253 
254                     matches.extend(self.check_ip_block(ip_block_obj, tree[:] + [0]))
255 
256                     new_count_parameters, new_matches = self.check_count(
257                         count_obj, tree[:] + [1]
258                     )
259                     count_parameters.extend(new_count_parameters)
260                     matches.extend(new_matches)
261 
262                     new_size_mask_parameters, new_matches = self.check_size_mask(
263                         size_mask_obj, tree[:] + [2]
264                     )
265                     size_mask_parameters.extend(new_size_mask_parameters)
266                     matches.extend(new_matches)
267 
268                 else:
269                     message = "Cidr should be a list of 2 or 3 elements for {0}"
270                     matches.append(
271                         RuleMatch(tree, message.format("/".join(map(str, tree))))
272                     )
273             else:
274                 message = "Cidr should be a list of 2 or 3 elements for {0}"
275                 matches.append(
276                     RuleMatch(tree, message.format("/".join(map(str, tree))))
277                 )
278 
279         for count_parameter in set(count_parameters):
280             matches.extend(self.check_parameter_count(cfn, count_parameter))
281         for size_mask_parameter in set(size_mask_parameters):
282             matches.extend(self.check_parameter_size_mask(cfn, size_mask_parameter))
283 
284         return matches
285
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/cfnlint/rules/functions/Cidr.py b/src/cfnlint/rules/functions/Cidr.py
--- a/src/cfnlint/rules/functions/Cidr.py
+++ b/src/cfnlint/rules/functions/Cidr.py
@@ -49,7 +49,10 @@
                                     )
                                 )
                         else:
-                            message = "Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or Select for {0}"
+                            message = (
+                                "Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or"
+                                " Select for {0}"
+                            )
                             matches.append(
                                 RuleMatch(
                                     path, message.format("/".join(map(str, value)))
@@ -78,18 +81,16 @@
                             if len(value.get("Fn::If")) == 3 and isinstance(
                                 value.get("Fn::If"), list
                             ):
-                                matches.extend(
-                                    self.check_count(
-                                        value.get("Fn::If")[1],
-                                        path=path[:] + [index_key, 1],
-                                    )
-                                )
-                                matches.extend(
-                                    self.check_count(
-                                        value.get("Fn::If")[2],
-                                        path=path[:] + [index_key, 2],
+                                for i in [1, 2]:
+                                    (
+                                        new_count_parameters,
+                                        new_matches,
+                                    ) = self.check_count(
+                                        value.get("Fn::If")[i],
+                                        path=path[:] + [index_key, i],
                                     )
-                                )
+                                    count_parameters.extend(new_count_parameters)
+                                    matches.extend(new_matches)
                         else:
                             message = "Cidr count should be Int, Ref, or Select for {0}"
                             matches.append(
@@ -168,7 +169,10 @@
                 max_value = parameter_obj.get("MaxValue")
                 min_value = parameter_obj.get("MinValue")
                 if (not min_value) or min_value < 1 or min_value > 256:
-                    message = "Parameter for Cidr count have MinValue between 1 and 256 at {0}"
+                    message = (
+                        "Parameter for Cidr count have MinValue between 1 and 256"
+                        " at {0}"
+                    )
                     matches.append(
                         RuleMatch(
                             tree + ["MinValue"],
@@ -176,7 +180,10 @@
                         )
                     )
                 if (not max_value) or max_value < 1 or max_value > 256:
-                    message = "Parameter for Cidr count have MaxValue between 1 and 256 at {0}"
+                    message = (
+                        "Parameter for Cidr count have MaxValue between 1 and 256"
+                        " at {0}"
+                    )
                     matches.append(
                         RuleMatch(
                             tree + ["MaxValue"],
@@ -258,7 +265,6 @@
                     )
                     count_parameters.extend(new_count_parameters)
                     matches.extend(new_matches)
-
                     new_size_mask_parameters, new_matches = self.check_size_mask(
                         size_mask_obj, tree[:] + [2]
                     )

{"golden_diff": "diff --git a/src/cfnlint/rules/functions/Cidr.py b/src/cfnlint/rules/functions/Cidr.py\n--- a/src/cfnlint/rules/functions/Cidr.py\n+++ b/src/cfnlint/rules/functions/Cidr.py\n@@ -49,7 +49,10 @@\n                                     )\n                                 )\n                         else:\n-                            message = \"Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or Select for {0}\"\n+                            message = (\n+                                \"Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or\"\n+                                \" Select for {0}\"\n+                            )\n                             matches.append(\n                                 RuleMatch(\n                                     path, message.format(\"/\".join(map(str, value)))\n@@ -78,18 +81,16 @@\n                             if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                 value.get(\"Fn::If\"), list\n                             ):\n-                                matches.extend(\n-                                    self.check_count(\n-                                        value.get(\"Fn::If\")[1],\n-                                        path=path[:] + [index_key, 1],\n-                                    )\n-                                )\n-                                matches.extend(\n-                                    self.check_count(\n-                                        value.get(\"Fn::If\")[2],\n-                                        path=path[:] + [index_key, 2],\n+                                for i in [1, 2]:\n+                                    (\n+                                        new_count_parameters,\n+                                        new_matches,\n+                                    ) = self.check_count(\n+                                        value.get(\"Fn::If\")[i],\n+                                        path=path[:] + [index_key, i],\n                                     )\n-                                )\n+                                    count_parameters.extend(new_count_parameters)\n+                                    matches.extend(new_matches)\n                         else:\n                             message = \"Cidr count should be Int, Ref, or Select for {0}\"\n                             matches.append(\n@@ -168,7 +169,10 @@\n                 max_value = parameter_obj.get(\"MaxValue\")\n                 min_value = parameter_obj.get(\"MinValue\")\n                 if (not min_value) or min_value < 1 or min_value > 256:\n-                    message = \"Parameter for Cidr count have MinValue between 1 and 256 at {0}\"\n+                    message = (\n+                        \"Parameter for Cidr count have MinValue between 1 and 256\"\n+                        \" at {0}\"\n+                    )\n                     matches.append(\n                         RuleMatch(\n                             tree + [\"MinValue\"],\n@@ -176,7 +180,10 @@\n                         )\n                     )\n                 if (not max_value) or max_value < 1 or max_value > 256:\n-                    message = \"Parameter for Cidr count have MaxValue between 1 and 256 at {0}\"\n+                    message = (\n+                        \"Parameter for Cidr count have MaxValue between 1 and 256\"\n+                        \" at {0}\"\n+                    )\n                     matches.append(\n                         RuleMatch(\n                             tree + [\"MaxValue\"],\n@@ -258,7 +265,6 @@\n                     )\n                     count_parameters.extend(new_count_parameters)\n                     matches.extend(new_matches)\n-\n                     new_size_mask_parameters, new_matches = self.check_size_mask(\n                         size_mask_obj, tree[:] + [2]\n                     )\n", "issue": "E0002: Unknown exception while processing rule E1024: 'list' object has no attribute 'path'\n### CloudFormation Lint Version\n\ncfn-lint 0.77.10\n\n### What operating system are you using?\n\nMac\n\n### Describe the bug\n\nWhen validation checks run on a the Cidr function `!Cidr [ ipBlock, count, cidrBits ]`, the count and cidrBits doesn't validate more complex functions like the `!If` in the example.\n\n### Expected behavior\n\nDoesn't throw unknown exception\n\n### Reproduction template\n\n```yaml\r\nPublicSubnet1:\r\n    Type: AWS::EC2::Subnet\r\n    Properties:\r\n      VpcId: !Ref VPC\r\n      AvailabilityZone: !Select [0, !GetAZs \"\"]\r\n      CidrBlock: !If\r\n        - defineYourOwnSubnetCIDR\r\n        - !Ref FirstTierSubnet1CIDR\r\n        - !Select\r\n          - 0\r\n          - !Cidr\r\n            - 10.0.0.0/24\r\n            - !If [3AZ, 16, 8]\r\n            - 4\r\n```\n", "before_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport regex as re\n\nfrom cfnlint.helpers import REGEX_CIDR\nfrom cfnlint.rules import CloudFormationLintRule, RuleMatch\n\n\nclass Cidr(CloudFormationLintRule):\n    \"\"\"Check if Cidr values are correct\"\"\"\n\n    id = \"E1024\"\n    shortdesc = \"Cidr validation of parameters\"\n    description = \"Making sure the function CIDR is a list with valid values\"\n    source_url = \"https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-cidr.html\"\n    tags = [\"functions\", \"cidr\"]\n\n    supported_functions = [\n        \"Fn::FindInMap\",\n        \"Fn::Select\",\n        \"Ref\",\n        \"Fn::GetAtt\",\n        \"Fn::Sub\",\n        \"Fn::ImportValue\",\n    ]\n\n    def check_ip_block(self, value, path):\n        matches = []\n        if isinstance(value, dict):\n            if len(value) == 1:\n                for index_key, _ in value.items():\n                    if index_key not in self.supported_functions:\n                        if index_key == \"Fn::If\":\n                            if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                value.get(\"Fn::If\"), list\n                            ):\n                                matches.extend(\n                                    self.check_ip_block(\n                                        value.get(\"Fn::If\")[1],\n                                        path=path[:] + [index_key, 1],\n                                    )\n                                )\n                                matches.extend(\n                                    self.check_ip_block(\n                                        value.get(\"Fn::If\")[2],\n                                        path=path[:] + [index_key, 2],\n                                    )\n                                )\n                        else:\n                            message = \"Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or Select for {0}\"\n                            matches.append(\n                                RuleMatch(\n                                    path, message.format(\"/\".join(map(str, value)))\n                                )\n                            )\n        elif isinstance(value, (str)):\n            if not re.match(REGEX_CIDR, value):\n                message = \"Cidr ipBlock should be a Cidr Range based string for {0}\"\n                matches.append(\n                    RuleMatch(path, message.format(\"/\".join(map(str, path))))\n                )\n        else:\n            message = \"Cidr ipBlock should be a string for {0}\"\n            matches.append(RuleMatch(path, message.format(\"/\".join(map(str, path)))))\n\n        return matches\n\n    def check_count(self, value, path):\n        matches = []\n        count_parameters = []\n        if isinstance(value, dict):\n            if len(value) == 1:\n                for index_key, index_value in value.items():\n                    if index_key not in self.supported_functions:\n                        if index_key == \"Fn::If\":\n                            if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                value.get(\"Fn::If\"), list\n                            ):\n                                matches.extend(\n                                    self.check_count(\n                                        value.get(\"Fn::If\")[1],\n                                        path=path[:] + [index_key, 1],\n                                    )\n                                )\n                                matches.extend(\n                                    self.check_count(\n                                        value.get(\"Fn::If\")[2],\n                                        path=path[:] + [index_key, 2],\n                                    )\n                                )\n                        else:\n                            message = \"Cidr count should be Int, Ref, or Select for {0}\"\n                            matches.append(\n                                RuleMatch(\n                                    path, message.format(\"/\".join(map(str, path)))\n                                )\n                            )\n                    if index_key == \"Ref\":\n                        count_parameters.append(index_value)\n        elif not isinstance(value, int):\n            message = \"Cidr count should be a int for {0}\"\n            extra_args = {\n                \"actual_type\": type(value).__name__,\n                \"expected_type\": int.__name__,\n            }\n            matches.append(\n                RuleMatch(path, message.format(\"/\".join(map(str, path))), **extra_args)\n            )\n\n        return count_parameters, matches\n\n    def check_size_mask(self, value, path):\n        matches = []\n        size_mask_parameters = []\n        if isinstance(value, dict):\n            if len(value) == 1:\n                for index_key, index_value in value.items():\n                    if index_key not in self.supported_functions:\n                        if index_key == \"Fn::If\":\n                            if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                value.get(\"Fn::If\"), list\n                            ):\n                                matches.extend(\n                                    self.check_size_mask(\n                                        value.get(\"Fn::If\")[1],\n                                        path=path[:] + [index_key, 1],\n                                    )\n                                )\n                                matches.extend(\n                                    self.check_size_mask(\n                                        value.get(\"Fn::If\")[2],\n                                        path=path[:] + [index_key, 2],\n                                    )\n                                )\n                        else:\n                            message = (\n                                \"Cidr sizeMask should be Int, Ref, or Select for {0}\"\n                            )\n                            matches.append(\n                                RuleMatch(\n                                    path, message.format(\"/\".join(map(str, path)))\n                                )\n                            )\n                    if index_key == \"Ref\":\n                        size_mask_parameters.append(index_value)\n        elif not isinstance(value, int):\n            message = \"Cidr sizeMask should be a int for {0}\"\n            extra_args = {\n                \"actual_type\": type(value).__name__,\n                \"expected_type\": int.__name__,\n            }\n            matches.append(\n                RuleMatch(path, message.format(\"/\".join(map(str, path))), **extra_args)\n            )\n\n        return size_mask_parameters, matches\n\n    def check_parameter_count(self, cfn, parameter_name):\n        \"\"\"Check Count Parameter if used\"\"\"\n        matches = []\n        parameter_obj = cfn.get_parameters().get(parameter_name, {})\n        if parameter_obj:\n            tree = [\"Parameters\", parameter_name]\n            parameter_type = parameter_obj.get(\"Type\")\n            if parameter_type == \"Number\":\n                max_value = parameter_obj.get(\"MaxValue\")\n                min_value = parameter_obj.get(\"MinValue\")\n                if (not min_value) or min_value < 1 or min_value > 256:\n                    message = \"Parameter for Cidr count have MinValue between 1 and 256 at {0}\"\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MinValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MinValue\"]))),\n                        )\n                    )\n                if (not max_value) or max_value < 1 or max_value > 256:\n                    message = \"Parameter for Cidr count have MaxValue between 1 and 256 at {0}\"\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MaxValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MaxValue\"]))),\n                        )\n                    )\n            else:\n                message = \"Parameter for Cidr count have be of Type Number at {0}\"\n                matches.append(\n                    RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                )\n\n        return matches\n\n    def check_parameter_size_mask(self, cfn, parameter_name):\n        \"\"\"Check SizeMask Parameter if used\"\"\"\n        matches = []\n        parameter_obj = cfn.get_parameters().get(parameter_name, {})\n        if parameter_obj:\n            tree = [\"Parameters\", parameter_name]\n            parameter_type = parameter_obj.get(\"Type\")\n            if parameter_type == \"Number\":\n                max_value = parameter_obj.get(\"MaxValue\")\n                min_value = parameter_obj.get(\"MinValue\")\n                if (not min_value) or min_value < 1 or min_value > 256:\n                    message = (\n                        \"Parameter for Cidr sizeMask have MinValue between 1 and \"\n                        \"128 (for ipv6) and 32 (for ipv4) at {0}\"\n                    )\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MinValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MinValue\"]))),\n                        )\n                    )\n                if (not max_value) or max_value < 1 or max_value > 256:\n                    message = (\n                        \"Parameter for Cidr count have MaxValue between 1 and \"\n                        \"128 (for ipv6) and 32 (for ipv4) at {0}\"\n                    )\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MaxValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MaxValue\"]))),\n                        )\n                    )\n            else:\n                message = \"Parameter for Cidr count have be of Type Number at {0}\"\n                matches.append(\n                    RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                )\n\n        return matches\n\n    def match(self, cfn):\n        matches = []\n\n        cidr_objs = cfn.search_deep_keys(\"Fn::Cidr\")\n\n        count_parameters = []\n        size_mask_parameters = []\n\n        for cidr_obj in cidr_objs:\n            cidr_value_obj = cidr_obj[-1]\n            tree = cidr_obj[:-1]\n            if isinstance(cidr_value_obj, list):\n                if len(cidr_value_obj) in [2, 3]:\n                    ip_block_obj = cidr_value_obj[0]\n                    count_obj = cidr_value_obj[1]\n                    if len(cidr_value_obj) == 3:\n                        size_mask_obj = cidr_value_obj[2]\n                    else:\n                        size_mask_obj = None\n\n                    matches.extend(self.check_ip_block(ip_block_obj, tree[:] + [0]))\n\n                    new_count_parameters, new_matches = self.check_count(\n                        count_obj, tree[:] + [1]\n                    )\n                    count_parameters.extend(new_count_parameters)\n                    matches.extend(new_matches)\n\n                    new_size_mask_parameters, new_matches = self.check_size_mask(\n                        size_mask_obj, tree[:] + [2]\n                    )\n                    size_mask_parameters.extend(new_size_mask_parameters)\n                    matches.extend(new_matches)\n\n                else:\n                    message = \"Cidr should be a list of 2 or 3 elements for {0}\"\n                    matches.append(\n                        RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                    )\n            else:\n                message = \"Cidr should be a list of 2 or 3 elements for {0}\"\n                matches.append(\n                    RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                )\n\n        for count_parameter in set(count_parameters):\n            matches.extend(self.check_parameter_count(cfn, count_parameter))\n        for size_mask_parameter in set(size_mask_parameters):\n            matches.extend(self.check_parameter_size_mask(cfn, size_mask_parameter))\n\n        return matches\n", "path": "src/cfnlint/rules/functions/Cidr.py"}], "after_files": [{"content": "\"\"\"\nCopyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport regex as re\n\nfrom cfnlint.helpers import REGEX_CIDR\nfrom cfnlint.rules import CloudFormationLintRule, RuleMatch\n\n\nclass Cidr(CloudFormationLintRule):\n    \"\"\"Check if Cidr values are correct\"\"\"\n\n    id = \"E1024\"\n    shortdesc = \"Cidr validation of parameters\"\n    description = \"Making sure the function CIDR is a list with valid values\"\n    source_url = \"https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-cidr.html\"\n    tags = [\"functions\", \"cidr\"]\n\n    supported_functions = [\n        \"Fn::FindInMap\",\n        \"Fn::Select\",\n        \"Ref\",\n        \"Fn::GetAtt\",\n        \"Fn::Sub\",\n        \"Fn::ImportValue\",\n    ]\n\n    def check_ip_block(self, value, path):\n        matches = []\n        if isinstance(value, dict):\n            if len(value) == 1:\n                for index_key, _ in value.items():\n                    if index_key not in self.supported_functions:\n                        if index_key == \"Fn::If\":\n                            if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                value.get(\"Fn::If\"), list\n                            ):\n                                matches.extend(\n                                    self.check_ip_block(\n                                        value.get(\"Fn::If\")[1],\n                                        path=path[:] + [index_key, 1],\n                                    )\n                                )\n                                matches.extend(\n                                    self.check_ip_block(\n                                        value.get(\"Fn::If\")[2],\n                                        path=path[:] + [index_key, 2],\n                                    )\n                                )\n                        else:\n                            message = (\n                                \"Cidr ipBlock should be Cidr Range, Ref, GetAtt, Sub or\"\n                                \" Select for {0}\"\n                            )\n                            matches.append(\n                                RuleMatch(\n                                    path, message.format(\"/\".join(map(str, value)))\n                                )\n                            )\n        elif isinstance(value, (str)):\n            if not re.match(REGEX_CIDR, value):\n                message = \"Cidr ipBlock should be a Cidr Range based string for {0}\"\n                matches.append(\n                    RuleMatch(path, message.format(\"/\".join(map(str, path))))\n                )\n        else:\n            message = \"Cidr ipBlock should be a string for {0}\"\n            matches.append(RuleMatch(path, message.format(\"/\".join(map(str, path)))))\n\n        return matches\n\n    def check_count(self, value, path):\n        matches = []\n        count_parameters = []\n        if isinstance(value, dict):\n            if len(value) == 1:\n                for index_key, index_value in value.items():\n                    if index_key not in self.supported_functions:\n                        if index_key == \"Fn::If\":\n                            if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                value.get(\"Fn::If\"), list\n                            ):\n                                for i in [1, 2]:\n                                    (\n                                        new_count_parameters,\n                                        new_matches,\n                                    ) = self.check_count(\n                                        value.get(\"Fn::If\")[i],\n                                        path=path[:] + [index_key, i],\n                                    )\n                                    count_parameters.extend(new_count_parameters)\n                                    matches.extend(new_matches)\n                        else:\n                            message = \"Cidr count should be Int, Ref, or Select for {0}\"\n                            matches.append(\n                                RuleMatch(\n                                    path, message.format(\"/\".join(map(str, path)))\n                                )\n                            )\n                    if index_key == \"Ref\":\n                        count_parameters.append(index_value)\n        elif not isinstance(value, int):\n            message = \"Cidr count should be a int for {0}\"\n            extra_args = {\n                \"actual_type\": type(value).__name__,\n                \"expected_type\": int.__name__,\n            }\n            matches.append(\n                RuleMatch(path, message.format(\"/\".join(map(str, path))), **extra_args)\n            )\n\n        return count_parameters, matches\n\n    def check_size_mask(self, value, path):\n        matches = []\n        size_mask_parameters = []\n        if isinstance(value, dict):\n            if len(value) == 1:\n                for index_key, index_value in value.items():\n                    if index_key not in self.supported_functions:\n                        if index_key == \"Fn::If\":\n                            if len(value.get(\"Fn::If\")) == 3 and isinstance(\n                                value.get(\"Fn::If\"), list\n                            ):\n                                matches.extend(\n                                    self.check_size_mask(\n                                        value.get(\"Fn::If\")[1],\n                                        path=path[:] + [index_key, 1],\n                                    )\n                                )\n                                matches.extend(\n                                    self.check_size_mask(\n                                        value.get(\"Fn::If\")[2],\n                                        path=path[:] + [index_key, 2],\n                                    )\n                                )\n                        else:\n                            message = (\n                                \"Cidr sizeMask should be Int, Ref, or Select for {0}\"\n                            )\n                            matches.append(\n                                RuleMatch(\n                                    path, message.format(\"/\".join(map(str, path)))\n                                )\n                            )\n                    if index_key == \"Ref\":\n                        size_mask_parameters.append(index_value)\n        elif not isinstance(value, int):\n            message = \"Cidr sizeMask should be a int for {0}\"\n            extra_args = {\n                \"actual_type\": type(value).__name__,\n                \"expected_type\": int.__name__,\n            }\n            matches.append(\n                RuleMatch(path, message.format(\"/\".join(map(str, path))), **extra_args)\n            )\n\n        return size_mask_parameters, matches\n\n    def check_parameter_count(self, cfn, parameter_name):\n        \"\"\"Check Count Parameter if used\"\"\"\n        matches = []\n        parameter_obj = cfn.get_parameters().get(parameter_name, {})\n        if parameter_obj:\n            tree = [\"Parameters\", parameter_name]\n            parameter_type = parameter_obj.get(\"Type\")\n            if parameter_type == \"Number\":\n                max_value = parameter_obj.get(\"MaxValue\")\n                min_value = parameter_obj.get(\"MinValue\")\n                if (not min_value) or min_value < 1 or min_value > 256:\n                    message = (\n                        \"Parameter for Cidr count have MinValue between 1 and 256\"\n                        \" at {0}\"\n                    )\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MinValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MinValue\"]))),\n                        )\n                    )\n                if (not max_value) or max_value < 1 or max_value > 256:\n                    message = (\n                        \"Parameter for Cidr count have MaxValue between 1 and 256\"\n                        \" at {0}\"\n                    )\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MaxValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MaxValue\"]))),\n                        )\n                    )\n            else:\n                message = \"Parameter for Cidr count have be of Type Number at {0}\"\n                matches.append(\n                    RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                )\n\n        return matches\n\n    def check_parameter_size_mask(self, cfn, parameter_name):\n        \"\"\"Check SizeMask Parameter if used\"\"\"\n        matches = []\n        parameter_obj = cfn.get_parameters().get(parameter_name, {})\n        if parameter_obj:\n            tree = [\"Parameters\", parameter_name]\n            parameter_type = parameter_obj.get(\"Type\")\n            if parameter_type == \"Number\":\n                max_value = parameter_obj.get(\"MaxValue\")\n                min_value = parameter_obj.get(\"MinValue\")\n                if (not min_value) or min_value < 1 or min_value > 256:\n                    message = (\n                        \"Parameter for Cidr sizeMask have MinValue between 1 and \"\n                        \"128 (for ipv6) and 32 (for ipv4) at {0}\"\n                    )\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MinValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MinValue\"]))),\n                        )\n                    )\n                if (not max_value) or max_value < 1 or max_value > 256:\n                    message = (\n                        \"Parameter for Cidr count have MaxValue between 1 and \"\n                        \"128 (for ipv6) and 32 (for ipv4) at {0}\"\n                    )\n                    matches.append(\n                        RuleMatch(\n                            tree + [\"MaxValue\"],\n                            message.format(\"/\".join(map(str, tree + [\"MaxValue\"]))),\n                        )\n                    )\n            else:\n                message = \"Parameter for Cidr count have be of Type Number at {0}\"\n                matches.append(\n                    RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                )\n\n        return matches\n\n    def match(self, cfn):\n        matches = []\n\n        cidr_objs = cfn.search_deep_keys(\"Fn::Cidr\")\n\n        count_parameters = []\n        size_mask_parameters = []\n\n        for cidr_obj in cidr_objs:\n            cidr_value_obj = cidr_obj[-1]\n            tree = cidr_obj[:-1]\n            if isinstance(cidr_value_obj, list):\n                if len(cidr_value_obj) in [2, 3]:\n                    ip_block_obj = cidr_value_obj[0]\n                    count_obj = cidr_value_obj[1]\n                    if len(cidr_value_obj) == 3:\n                        size_mask_obj = cidr_value_obj[2]\n                    else:\n                        size_mask_obj = None\n\n                    matches.extend(self.check_ip_block(ip_block_obj, tree[:] + [0]))\n\n                    new_count_parameters, new_matches = self.check_count(\n                        count_obj, tree[:] + [1]\n                    )\n                    count_parameters.extend(new_count_parameters)\n                    matches.extend(new_matches)\n                    new_size_mask_parameters, new_matches = self.check_size_mask(\n                        size_mask_obj, tree[:] + [2]\n                    )\n                    size_mask_parameters.extend(new_size_mask_parameters)\n                    matches.extend(new_matches)\n\n                else:\n                    message = \"Cidr should be a list of 2 or 3 elements for {0}\"\n                    matches.append(\n                        RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                    )\n            else:\n                message = \"Cidr should be a list of 2 or 3 elements for {0}\"\n                matches.append(\n                    RuleMatch(tree, message.format(\"/\".join(map(str, tree))))\n                )\n\n        for count_parameter in set(count_parameters):\n            matches.extend(self.check_parameter_count(cfn, count_parameter))\n        for size_mask_parameter in set(size_mask_parameters):\n            matches.extend(self.check_parameter_size_mask(cfn, size_mask_parameter))\n\n        return matches\n", "path": "src/cfnlint/rules/functions/Cidr.py"}]}