We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Parsing error scanning terraform plan output
**Describe the bug**
Receiving a parsing error when scanning terraform plan output. parsing error is in the cloudformation scan results. the file being scanned contains no cloudformation code. the terraform_plan scan results are reporting well

**To Reproduce**
Steps to reproduce the behavior:
1. Go to a folder which contains the output of a terraform plan piped into a tf.json file
2. Run cli command  checkov -f .\tf.json
3. See error in attached scanlog.txt

**Expected behavior**
Expect to be able to scan terraform plan output without encountering a parsing error

**Screenshots**
scanlog.txt
[scanlog.txt](https://github.com/bridgecrewio/checkov/files/7464351/scanlog.txt)

ts.json - terraform plan output being scanned
[tf.json.txt](https://github.com/bridgecrewio/checkov/files/7464354/tf.json.txt)


**Desktop (please complete the following information):**
 - OS: Windows 10
 - Checkov Version 2.0.536

**Additional context**
Add any other context about the problem here (e.g. code snippets).


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `checkov/cloudformation/parser/cfn_yaml.py`
Content:
```
1 """
2 Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 SPDX-License-Identifier: MIT-0
4 """
5 import logging
6 from yaml import MappingNode
7 from yaml import ScalarNode
8 from yaml import SequenceNode
9 from yaml.composer import Composer
10 from yaml.constructor import ConstructorError
11 from yaml.constructor import SafeConstructor
12 from yaml.reader import Reader
13 from yaml.resolver import Resolver
14 from yaml.scanner import Scanner
15 
16 from checkov.common.parsers.node import StrNode, DictNode, ListNode
17 
18 try:
19     from yaml.cyaml import CParser as Parser  # pylint: disable=ungrouped-imports
20 
21     cyaml = True
22 except ImportError:
23     from yaml.parser import Parser  # pylint: disable=ungrouped-imports
24 
25     cyaml = False
26 
27 UNCONVERTED_SUFFIXES = ['Ref', 'Condition']
28 FN_PREFIX = 'Fn::'
29 
30 LOGGER = logging.getLogger(__name__)
31 
32 
33 class CfnParseError(ConstructorError):
34     """
35     Error thrown when the template contains Cfn Error
36     """
37 
38     def __init__(self, filename, message, line_number, column_number, key=' '):
39         # Call the base class constructor with the parameters it needs
40         super(CfnParseError, self).__init__(message)
41 
42         # Now for your custom code...
43         self.filename = filename
44         self.line_number = line_number
45         self.column_number = column_number
46         self.message = message
47 
48 
49 class NodeConstructor(SafeConstructor):
50     """
51     Node Constructors for loading different types in Yaml
52     """
53 
54     def __init__(self, filename):
55         # Call the base class constructor
56         super(NodeConstructor, self).__init__()
57 
58         self.filename = filename
59 
60     # To support lazy loading, the original constructors first yield
61     # an empty object, then fill them in when iterated. Due to
62     # laziness we omit this behaviour (and will only do "deep
63     # construction") by first exhausting iterators, then yielding
64     # copies.
65     def construct_yaml_map(self, node):
66 
67         # Check for duplicate keys on the current level, this is not desirable
68         # because a dict does not support this. It overwrites it with the last
69         # occurance, which can give unexpected results
70         mapping = {}
71         self.flatten_mapping(node)
72         for key_node, value_node in node.value:
73             key = self.construct_object(key_node, False)
74             value = self.construct_object(value_node, False)
75 
76             if key in mapping:
77                 raise CfnParseError(
78                     self.filename,
79                     'Duplicate resource found "{}" (line {})'.format(
80                         key, key_node.start_mark.line + 1),
81                     key_node.start_mark.line, key_node.start_mark.column, key)
82             mapping[key] = value
83 
84         obj, = SafeConstructor.construct_yaml_map(self, node)
85         return DictNode(obj, node.start_mark, node.end_mark)
86 
87     def construct_yaml_str(self, node):
88         obj = SafeConstructor.construct_yaml_str(self, node)
89         assert isinstance(obj, str)  # nosec
90         return StrNode(obj, node.start_mark, node.end_mark)
91 
92     def construct_yaml_seq(self, node):
93         obj, = SafeConstructor.construct_yaml_seq(self, node)
94         assert isinstance(obj, list) # nosec
95         return ListNode(obj, node.start_mark, node.end_mark) # nosec
96 
97     def construct_yaml_null_error(self, node):
98         """Throw a null error"""
99         raise CfnParseError(
100             self.filename,
101             'Null value at line {0} column {1}'.format(
102                 node.start_mark.line + 1, node.start_mark.column + 1),
103             node.start_mark.line, node.start_mark.column, ' ')
104 
105 
106 NodeConstructor.add_constructor(
107     u'tag:yaml.org,2002:map',
108     NodeConstructor.construct_yaml_map)
109 
110 NodeConstructor.add_constructor(
111     u'tag:yaml.org,2002:str',
112     NodeConstructor.construct_yaml_str)
113 
114 NodeConstructor.add_constructor(
115     u'tag:yaml.org,2002:seq',
116     NodeConstructor.construct_yaml_seq)
117 
118 NodeConstructor.add_constructor(
119     u'tag:yaml.org,2002:null',
120     NodeConstructor.construct_yaml_null_error)
121 
122 
123 class MarkedLoader(Reader, Scanner, Parser, Composer, NodeConstructor, Resolver):
124     """
125     Class for marked loading YAML
126     """
127 
128     # pylint: disable=non-parent-init-called,super-init-not-called
129 
130     def __init__(self, stream, filename):
131         Reader.__init__(self, stream)
132         Scanner.__init__(self)
133         if cyaml:
134             Parser.__init__(self, stream)
135         else:
136             Parser.__init__(self)
137         Composer.__init__(self)
138         SafeConstructor.__init__(self)
139         Resolver.__init__(self)
140         NodeConstructor.__init__(self, filename)
141 
142     def construct_mapping(self, node, deep=False):
143         mapping = super(MarkedLoader, self).construct_mapping(node, deep=deep)
144         # Add 1 so line numbering starts at 1
145         # mapping['__line__'] = node.start_mark.line + 1
146         mapping['__startline__'] = node.start_mark.line + 1
147         mapping['__endline__'] = node.end_mark.line + 1
148         return mapping
149 
150 
151 def multi_constructor(loader, tag_suffix, node):
152     """
153     Deal with !Ref style function format
154     """
155 
156     if tag_suffix not in UNCONVERTED_SUFFIXES:
157         tag_suffix = '{}{}'.format(FN_PREFIX, tag_suffix)
158 
159     constructor = None
160     if tag_suffix == 'Fn::GetAtt':
161         constructor = construct_getatt
162     elif isinstance(node, ScalarNode):
163         constructor = loader.construct_scalar
164     elif isinstance(node, SequenceNode):
165         constructor = loader.construct_sequence
166     elif isinstance(node, MappingNode):
167         constructor = loader.construct_mapping
168     else:
169         raise 'Bad tag: !{}'.format(tag_suffix)
170 
171     return DictNode({tag_suffix: constructor(node)}, node.start_mark, node.end_mark)
172 
173 
174 def construct_getatt(node):
175     """
176     Reconstruct !GetAtt into a list
177     """
178 
179     if isinstance(node.value, str):
180         return ListNode(node.value.split('.'), node.start_mark, node.end_mark)
181     if isinstance(node.value, list):
182         return ListNode([s.value for s in node.value], node.start_mark, node.end_mark)
183 
184     raise ValueError('Unexpected node type: {}'.format(type(node.value)))
185 
186 
187 def loads(yaml_string, fname=None):
188     """
189     Load the given YAML string
190     """
191     loader = MarkedLoader(yaml_string, fname)
192     loader.add_multi_constructor('!', multi_constructor)
193 
194     template = loader.get_single_data()
195     # Convert an empty file to an empty dict
196     if template is None:
197         template = {}
198 
199     return template
200 
201 
202 def load(filename):
203     """
204     Load the given YAML file
205     """
206 
207     content = ''
208 
209     with open(filename) as fp:
210         content = fp.read()
211         fp.seek(0)
212         file_lines = [(ind + 1, line) for (ind, line) in
213                       list(enumerate(fp.readlines()))]
214 
215     return (loads(content, filename), file_lines)
216
```

Path: `checkov/cloudformation/parser/__init__.py`
Content:
```
1 import logging
2 from typing import Tuple, List, Union, Dict
3 
4 from checkov.cloudformation.parser import cfn_yaml
5 from checkov.common.parsers.json import parse as json_parse
6 from checkov.common.parsers.node import DictNode
7 from checkov.cloudformation.parser.cfn_keywords import TemplateSections
8 from yaml.parser import ScannerError
9 from yaml import YAMLError
10 
11 LOGGER = logging.getLogger(__name__)
12 
13 
14 def parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:
15     """
16         Decode filename into an object
17     """
18     template = None
19     template_lines = None
20     error = None
21     try:
22         (template, template_lines) = cfn_yaml.load(filename)
23     except IOError as err:
24         if err.errno == 2:
25             error = f"Template file not found: {filename} - {err}"
26             LOGGER.error(error)
27         elif err.errno == 21:
28             error = f"Template references a directory, not a file: {filename} - {err}"
29             LOGGER.error(error)
30         elif err.errno == 13:
31             error = f"Permission denied when accessing template file: {filename} - {err}"
32             LOGGER.error(error)
33     except UnicodeDecodeError as err:
34         error = f"Cannot read file contents: {filename} - {err}"
35         LOGGER.error(error)
36     except cfn_yaml.CfnParseError as err:
37         error = f"Parsing error in file: {filename} - {err}"
38         LOGGER.info(error)
39     except ValueError as err:
40         error = f"Parsing error in file: {filename} - {err}"
41         LOGGER.info(error)
42     except ScannerError as err:
43         if err.problem in ["found character '\\t' that cannot start any token", "found unknown escape character"]:
44             try:
45                 (template, template_lines) = json_parse(filename, allow_nulls=False)
46             except Exception as json_err:  # pylint: disable=W0703
47                 error = f"Template {filename} is malformed: {err.problem}. Tried to parse {filename} as JSON but got error: {json_err}"
48                 LOGGER.info(error)
49     except YAMLError as err:
50         error = f"Parsing error in file: {filename} - {err}"
51         LOGGER.info(error)
52 
53     if error:
54         out_parsing_errors[filename] = error
55 
56     if isinstance(template, dict):
57         resources = template.get(TemplateSections.RESOURCES.value, None)
58         if resources:
59             if '__startline__' in resources:
60                 del resources['__startline__']
61             if '__endline__' in resources:
62                 del resources['__endline__']
63     return template, template_lines
64
```
--- 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/checkov/cloudformation/parser/__init__.py b/checkov/cloudformation/parser/__init__.py
--- a/checkov/cloudformation/parser/__init__.py
+++ b/checkov/cloudformation/parser/__init__.py
@@ -1,5 +1,5 @@
 import logging
-from typing import Tuple, List, Union, Dict
+from typing import Tuple, List, Union, Dict, Optional
 
 from checkov.cloudformation.parser import cfn_yaml
 from checkov.common.parsers.json import parse as json_parse
@@ -11,13 +11,19 @@
 LOGGER = logging.getLogger(__name__)
 
 
-def parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:
+def parse(
+    filename: str, out_parsing_errors: Optional[Dict[str, str]] = None
+) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:
     """
-        Decode filename into an object
+    Decode filename into an object
     """
     template = None
     template_lines = None
     error = None
+
+    if out_parsing_errors is None:
+        out_parsing_errors = {}
+
     try:
         (template, template_lines) = cfn_yaml.load(filename)
     except IOError as err:
@@ -34,6 +40,10 @@
         error = f"Cannot read file contents: {filename} - {err}"
         LOGGER.error(error)
     except cfn_yaml.CfnParseError as err:
+        if "Null value at" in err.message:
+            LOGGER.info(f"Null values do not exist in CFN templates: {filename} - {err}")
+            return None, None
+
         error = f"Parsing error in file: {filename} - {err}"
         LOGGER.info(error)
     except ValueError as err:
@@ -56,8 +66,8 @@
     if isinstance(template, dict):
         resources = template.get(TemplateSections.RESOURCES.value, None)
         if resources:
-            if '__startline__' in resources:
-                del resources['__startline__']
-            if '__endline__' in resources:
-                del resources['__endline__']
+            if "__startline__" in resources:
+                del resources["__startline__"]
+            if "__endline__" in resources:
+                del resources["__endline__"]
     return template, template_lines
diff --git a/checkov/cloudformation/parser/cfn_yaml.py b/checkov/cloudformation/parser/cfn_yaml.py
--- a/checkov/cloudformation/parser/cfn_yaml.py
+++ b/checkov/cloudformation/parser/cfn_yaml.py
@@ -3,6 +3,9 @@
 SPDX-License-Identifier: MIT-0
 """
 import logging
+from pathlib import Path
+from typing import List, Tuple
+
 from yaml import MappingNode
 from yaml import ScalarNode
 from yaml import SequenceNode
@@ -199,17 +202,13 @@
     return template
 
 
-def load(filename):
+def load(filename: str) -> Tuple[DictNode, List[Tuple[int, str]]]:
     """
     Load the given YAML file
     """
 
-    content = ''
-
-    with open(filename) as fp:
-        content = fp.read()
-        fp.seek(0)
-        file_lines = [(ind + 1, line) for (ind, line) in
-                      list(enumerate(fp.readlines()))]
+    file_path = Path(filename)
+    content = file_path.read_text()
+    file_lines = [(idx + 1, line) for idx, line in enumerate(content.splitlines(keepends=True))]
 
     return (loads(content, filename), file_lines)

{"golden_diff": "diff --git a/checkov/cloudformation/parser/__init__.py b/checkov/cloudformation/parser/__init__.py\n--- a/checkov/cloudformation/parser/__init__.py\n+++ b/checkov/cloudformation/parser/__init__.py\n@@ -1,5 +1,5 @@\n import logging\n-from typing import Tuple, List, Union, Dict\n+from typing import Tuple, List, Union, Dict, Optional\n \n from checkov.cloudformation.parser import cfn_yaml\n from checkov.common.parsers.json import parse as json_parse\n@@ -11,13 +11,19 @@\n LOGGER = logging.getLogger(__name__)\n \n \n-def parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:\n+def parse(\n+    filename: str, out_parsing_errors: Optional[Dict[str, str]] = None\n+) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:\n     \"\"\"\n-        Decode filename into an object\n+    Decode filename into an object\n     \"\"\"\n     template = None\n     template_lines = None\n     error = None\n+\n+    if out_parsing_errors is None:\n+        out_parsing_errors = {}\n+\n     try:\n         (template, template_lines) = cfn_yaml.load(filename)\n     except IOError as err:\n@@ -34,6 +40,10 @@\n         error = f\"Cannot read file contents: {filename} - {err}\"\n         LOGGER.error(error)\n     except cfn_yaml.CfnParseError as err:\n+        if \"Null value at\" in err.message:\n+            LOGGER.info(f\"Null values do not exist in CFN templates: {filename} - {err}\")\n+            return None, None\n+\n         error = f\"Parsing error in file: {filename} - {err}\"\n         LOGGER.info(error)\n     except ValueError as err:\n@@ -56,8 +66,8 @@\n     if isinstance(template, dict):\n         resources = template.get(TemplateSections.RESOURCES.value, None)\n         if resources:\n-            if '__startline__' in resources:\n-                del resources['__startline__']\n-            if '__endline__' in resources:\n-                del resources['__endline__']\n+            if \"__startline__\" in resources:\n+                del resources[\"__startline__\"]\n+            if \"__endline__\" in resources:\n+                del resources[\"__endline__\"]\n     return template, template_lines\ndiff --git a/checkov/cloudformation/parser/cfn_yaml.py b/checkov/cloudformation/parser/cfn_yaml.py\n--- a/checkov/cloudformation/parser/cfn_yaml.py\n+++ b/checkov/cloudformation/parser/cfn_yaml.py\n@@ -3,6 +3,9 @@\n SPDX-License-Identifier: MIT-0\n \"\"\"\n import logging\n+from pathlib import Path\n+from typing import List, Tuple\n+\n from yaml import MappingNode\n from yaml import ScalarNode\n from yaml import SequenceNode\n@@ -199,17 +202,13 @@\n     return template\n \n \n-def load(filename):\n+def load(filename: str) -> Tuple[DictNode, List[Tuple[int, str]]]:\n     \"\"\"\n     Load the given YAML file\n     \"\"\"\n \n-    content = ''\n-\n-    with open(filename) as fp:\n-        content = fp.read()\n-        fp.seek(0)\n-        file_lines = [(ind + 1, line) for (ind, line) in\n-                      list(enumerate(fp.readlines()))]\n+    file_path = Path(filename)\n+    content = file_path.read_text()\n+    file_lines = [(idx + 1, line) for idx, line in enumerate(content.splitlines(keepends=True))]\n \n     return (loads(content, filename), file_lines)\n", "issue": "Parsing error scanning terraform plan output\n**Describe the bug**\r\nReceiving a parsing error when scanning terraform plan output. parsing error is in the cloudformation scan results. the file being scanned contains no cloudformation code. the terraform_plan scan results are reporting well\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n1. Go to a folder which contains the output of a terraform plan piped into a tf.json file\r\n2. Run cli command  checkov -f .\\tf.json\r\n3. See error in attached scanlog.txt\r\n\r\n**Expected behavior**\r\nExpect to be able to scan terraform plan output without encountering a parsing error\r\n\r\n**Screenshots**\r\nscanlog.txt\r\n[scanlog.txt](https://github.com/bridgecrewio/checkov/files/7464351/scanlog.txt)\r\n\r\nts.json - terraform plan output being scanned\r\n[tf.json.txt](https://github.com/bridgecrewio/checkov/files/7464354/tf.json.txt)\r\n\r\n\r\n**Desktop (please complete the following information):**\r\n - OS: Windows 10\r\n - Checkov Version 2.0.536\r\n\r\n**Additional context**\r\nAdd any other context about the problem here (e.g. code snippets).\r\n\n", "before_files": [{"content": "\"\"\"\nCopyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport logging\nfrom yaml import MappingNode\nfrom yaml import ScalarNode\nfrom yaml import SequenceNode\nfrom yaml.composer import Composer\nfrom yaml.constructor import ConstructorError\nfrom yaml.constructor import SafeConstructor\nfrom yaml.reader import Reader\nfrom yaml.resolver import Resolver\nfrom yaml.scanner import Scanner\n\nfrom checkov.common.parsers.node import StrNode, DictNode, ListNode\n\ntry:\n    from yaml.cyaml import CParser as Parser  # pylint: disable=ungrouped-imports\n\n    cyaml = True\nexcept ImportError:\n    from yaml.parser import Parser  # pylint: disable=ungrouped-imports\n\n    cyaml = False\n\nUNCONVERTED_SUFFIXES = ['Ref', 'Condition']\nFN_PREFIX = 'Fn::'\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass CfnParseError(ConstructorError):\n    \"\"\"\n    Error thrown when the template contains Cfn Error\n    \"\"\"\n\n    def __init__(self, filename, message, line_number, column_number, key=' '):\n        # Call the base class constructor with the parameters it needs\n        super(CfnParseError, self).__init__(message)\n\n        # Now for your custom code...\n        self.filename = filename\n        self.line_number = line_number\n        self.column_number = column_number\n        self.message = message\n\n\nclass NodeConstructor(SafeConstructor):\n    \"\"\"\n    Node Constructors for loading different types in Yaml\n    \"\"\"\n\n    def __init__(self, filename):\n        # Call the base class constructor\n        super(NodeConstructor, self).__init__()\n\n        self.filename = filename\n\n    # To support lazy loading, the original constructors first yield\n    # an empty object, then fill them in when iterated. Due to\n    # laziness we omit this behaviour (and will only do \"deep\n    # construction\") by first exhausting iterators, then yielding\n    # copies.\n    def construct_yaml_map(self, node):\n\n        # Check for duplicate keys on the current level, this is not desirable\n        # because a dict does not support this. It overwrites it with the last\n        # occurance, which can give unexpected results\n        mapping = {}\n        self.flatten_mapping(node)\n        for key_node, value_node in node.value:\n            key = self.construct_object(key_node, False)\n            value = self.construct_object(value_node, False)\n\n            if key in mapping:\n                raise CfnParseError(\n                    self.filename,\n                    'Duplicate resource found \"{}\" (line {})'.format(\n                        key, key_node.start_mark.line + 1),\n                    key_node.start_mark.line, key_node.start_mark.column, key)\n            mapping[key] = value\n\n        obj, = SafeConstructor.construct_yaml_map(self, node)\n        return DictNode(obj, node.start_mark, node.end_mark)\n\n    def construct_yaml_str(self, node):\n        obj = SafeConstructor.construct_yaml_str(self, node)\n        assert isinstance(obj, str)  # nosec\n        return StrNode(obj, node.start_mark, node.end_mark)\n\n    def construct_yaml_seq(self, node):\n        obj, = SafeConstructor.construct_yaml_seq(self, node)\n        assert isinstance(obj, list) # nosec\n        return ListNode(obj, node.start_mark, node.end_mark) # nosec\n\n    def construct_yaml_null_error(self, node):\n        \"\"\"Throw a null error\"\"\"\n        raise CfnParseError(\n            self.filename,\n            'Null value at line {0} column {1}'.format(\n                node.start_mark.line + 1, node.start_mark.column + 1),\n            node.start_mark.line, node.start_mark.column, ' ')\n\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:map',\n    NodeConstructor.construct_yaml_map)\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:str',\n    NodeConstructor.construct_yaml_str)\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:seq',\n    NodeConstructor.construct_yaml_seq)\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:null',\n    NodeConstructor.construct_yaml_null_error)\n\n\nclass MarkedLoader(Reader, Scanner, Parser, Composer, NodeConstructor, Resolver):\n    \"\"\"\n    Class for marked loading YAML\n    \"\"\"\n\n    # pylint: disable=non-parent-init-called,super-init-not-called\n\n    def __init__(self, stream, filename):\n        Reader.__init__(self, stream)\n        Scanner.__init__(self)\n        if cyaml:\n            Parser.__init__(self, stream)\n        else:\n            Parser.__init__(self)\n        Composer.__init__(self)\n        SafeConstructor.__init__(self)\n        Resolver.__init__(self)\n        NodeConstructor.__init__(self, filename)\n\n    def construct_mapping(self, node, deep=False):\n        mapping = super(MarkedLoader, self).construct_mapping(node, deep=deep)\n        # Add 1 so line numbering starts at 1\n        # mapping['__line__'] = node.start_mark.line + 1\n        mapping['__startline__'] = node.start_mark.line + 1\n        mapping['__endline__'] = node.end_mark.line + 1\n        return mapping\n\n\ndef multi_constructor(loader, tag_suffix, node):\n    \"\"\"\n    Deal with !Ref style function format\n    \"\"\"\n\n    if tag_suffix not in UNCONVERTED_SUFFIXES:\n        tag_suffix = '{}{}'.format(FN_PREFIX, tag_suffix)\n\n    constructor = None\n    if tag_suffix == 'Fn::GetAtt':\n        constructor = construct_getatt\n    elif isinstance(node, ScalarNode):\n        constructor = loader.construct_scalar\n    elif isinstance(node, SequenceNode):\n        constructor = loader.construct_sequence\n    elif isinstance(node, MappingNode):\n        constructor = loader.construct_mapping\n    else:\n        raise 'Bad tag: !{}'.format(tag_suffix)\n\n    return DictNode({tag_suffix: constructor(node)}, node.start_mark, node.end_mark)\n\n\ndef construct_getatt(node):\n    \"\"\"\n    Reconstruct !GetAtt into a list\n    \"\"\"\n\n    if isinstance(node.value, str):\n        return ListNode(node.value.split('.'), node.start_mark, node.end_mark)\n    if isinstance(node.value, list):\n        return ListNode([s.value for s in node.value], node.start_mark, node.end_mark)\n\n    raise ValueError('Unexpected node type: {}'.format(type(node.value)))\n\n\ndef loads(yaml_string, fname=None):\n    \"\"\"\n    Load the given YAML string\n    \"\"\"\n    loader = MarkedLoader(yaml_string, fname)\n    loader.add_multi_constructor('!', multi_constructor)\n\n    template = loader.get_single_data()\n    # Convert an empty file to an empty dict\n    if template is None:\n        template = {}\n\n    return template\n\n\ndef load(filename):\n    \"\"\"\n    Load the given YAML file\n    \"\"\"\n\n    content = ''\n\n    with open(filename) as fp:\n        content = fp.read()\n        fp.seek(0)\n        file_lines = [(ind + 1, line) for (ind, line) in\n                      list(enumerate(fp.readlines()))]\n\n    return (loads(content, filename), file_lines)\n", "path": "checkov/cloudformation/parser/cfn_yaml.py"}, {"content": "import logging\nfrom typing import Tuple, List, Union, Dict\n\nfrom checkov.cloudformation.parser import cfn_yaml\nfrom checkov.common.parsers.json import parse as json_parse\nfrom checkov.common.parsers.node import DictNode\nfrom checkov.cloudformation.parser.cfn_keywords import TemplateSections\nfrom yaml.parser import ScannerError\nfrom yaml import YAMLError\n\nLOGGER = logging.getLogger(__name__)\n\n\ndef parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:\n    \"\"\"\n        Decode filename into an object\n    \"\"\"\n    template = None\n    template_lines = None\n    error = None\n    try:\n        (template, template_lines) = cfn_yaml.load(filename)\n    except IOError as err:\n        if err.errno == 2:\n            error = f\"Template file not found: {filename} - {err}\"\n            LOGGER.error(error)\n        elif err.errno == 21:\n            error = f\"Template references a directory, not a file: {filename} - {err}\"\n            LOGGER.error(error)\n        elif err.errno == 13:\n            error = f\"Permission denied when accessing template file: {filename} - {err}\"\n            LOGGER.error(error)\n    except UnicodeDecodeError as err:\n        error = f\"Cannot read file contents: {filename} - {err}\"\n        LOGGER.error(error)\n    except cfn_yaml.CfnParseError as err:\n        error = f\"Parsing error in file: {filename} - {err}\"\n        LOGGER.info(error)\n    except ValueError as err:\n        error = f\"Parsing error in file: {filename} - {err}\"\n        LOGGER.info(error)\n    except ScannerError as err:\n        if err.problem in [\"found character '\\\\t' that cannot start any token\", \"found unknown escape character\"]:\n            try:\n                (template, template_lines) = json_parse(filename, allow_nulls=False)\n            except Exception as json_err:  # pylint: disable=W0703\n                error = f\"Template {filename} is malformed: {err.problem}. Tried to parse {filename} as JSON but got error: {json_err}\"\n                LOGGER.info(error)\n    except YAMLError as err:\n        error = f\"Parsing error in file: {filename} - {err}\"\n        LOGGER.info(error)\n\n    if error:\n        out_parsing_errors[filename] = error\n\n    if isinstance(template, dict):\n        resources = template.get(TemplateSections.RESOURCES.value, None)\n        if resources:\n            if '__startline__' in resources:\n                del resources['__startline__']\n            if '__endline__' in resources:\n                del resources['__endline__']\n    return template, template_lines\n", "path": "checkov/cloudformation/parser/__init__.py"}], "after_files": [{"content": "\"\"\"\nCopyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.\nSPDX-License-Identifier: MIT-0\n\"\"\"\nimport logging\nfrom pathlib import Path\nfrom typing import List, Tuple\n\nfrom yaml import MappingNode\nfrom yaml import ScalarNode\nfrom yaml import SequenceNode\nfrom yaml.composer import Composer\nfrom yaml.constructor import ConstructorError\nfrom yaml.constructor import SafeConstructor\nfrom yaml.reader import Reader\nfrom yaml.resolver import Resolver\nfrom yaml.scanner import Scanner\n\nfrom checkov.common.parsers.node import StrNode, DictNode, ListNode\n\ntry:\n    from yaml.cyaml import CParser as Parser  # pylint: disable=ungrouped-imports\n\n    cyaml = True\nexcept ImportError:\n    from yaml.parser import Parser  # pylint: disable=ungrouped-imports\n\n    cyaml = False\n\nUNCONVERTED_SUFFIXES = ['Ref', 'Condition']\nFN_PREFIX = 'Fn::'\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass CfnParseError(ConstructorError):\n    \"\"\"\n    Error thrown when the template contains Cfn Error\n    \"\"\"\n\n    def __init__(self, filename, message, line_number, column_number, key=' '):\n        # Call the base class constructor with the parameters it needs\n        super(CfnParseError, self).__init__(message)\n\n        # Now for your custom code...\n        self.filename = filename\n        self.line_number = line_number\n        self.column_number = column_number\n        self.message = message\n\n\nclass NodeConstructor(SafeConstructor):\n    \"\"\"\n    Node Constructors for loading different types in Yaml\n    \"\"\"\n\n    def __init__(self, filename):\n        # Call the base class constructor\n        super(NodeConstructor, self).__init__()\n\n        self.filename = filename\n\n    # To support lazy loading, the original constructors first yield\n    # an empty object, then fill them in when iterated. Due to\n    # laziness we omit this behaviour (and will only do \"deep\n    # construction\") by first exhausting iterators, then yielding\n    # copies.\n    def construct_yaml_map(self, node):\n\n        # Check for duplicate keys on the current level, this is not desirable\n        # because a dict does not support this. It overwrites it with the last\n        # occurance, which can give unexpected results\n        mapping = {}\n        self.flatten_mapping(node)\n        for key_node, value_node in node.value:\n            key = self.construct_object(key_node, False)\n            value = self.construct_object(value_node, False)\n\n            if key in mapping:\n                raise CfnParseError(\n                    self.filename,\n                    'Duplicate resource found \"{}\" (line {})'.format(\n                        key, key_node.start_mark.line + 1),\n                    key_node.start_mark.line, key_node.start_mark.column, key)\n            mapping[key] = value\n\n        obj, = SafeConstructor.construct_yaml_map(self, node)\n        return DictNode(obj, node.start_mark, node.end_mark)\n\n    def construct_yaml_str(self, node):\n        obj = SafeConstructor.construct_yaml_str(self, node)\n        assert isinstance(obj, str)  # nosec\n        return StrNode(obj, node.start_mark, node.end_mark)\n\n    def construct_yaml_seq(self, node):\n        obj, = SafeConstructor.construct_yaml_seq(self, node)\n        assert isinstance(obj, list) # nosec\n        return ListNode(obj, node.start_mark, node.end_mark) # nosec\n\n    def construct_yaml_null_error(self, node):\n        \"\"\"Throw a null error\"\"\"\n        raise CfnParseError(\n            self.filename,\n            'Null value at line {0} column {1}'.format(\n                node.start_mark.line + 1, node.start_mark.column + 1),\n            node.start_mark.line, node.start_mark.column, ' ')\n\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:map',\n    NodeConstructor.construct_yaml_map)\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:str',\n    NodeConstructor.construct_yaml_str)\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:seq',\n    NodeConstructor.construct_yaml_seq)\n\nNodeConstructor.add_constructor(\n    u'tag:yaml.org,2002:null',\n    NodeConstructor.construct_yaml_null_error)\n\n\nclass MarkedLoader(Reader, Scanner, Parser, Composer, NodeConstructor, Resolver):\n    \"\"\"\n    Class for marked loading YAML\n    \"\"\"\n\n    # pylint: disable=non-parent-init-called,super-init-not-called\n\n    def __init__(self, stream, filename):\n        Reader.__init__(self, stream)\n        Scanner.__init__(self)\n        if cyaml:\n            Parser.__init__(self, stream)\n        else:\n            Parser.__init__(self)\n        Composer.__init__(self)\n        SafeConstructor.__init__(self)\n        Resolver.__init__(self)\n        NodeConstructor.__init__(self, filename)\n\n    def construct_mapping(self, node, deep=False):\n        mapping = super(MarkedLoader, self).construct_mapping(node, deep=deep)\n        # Add 1 so line numbering starts at 1\n        # mapping['__line__'] = node.start_mark.line + 1\n        mapping['__startline__'] = node.start_mark.line + 1\n        mapping['__endline__'] = node.end_mark.line + 1\n        return mapping\n\n\ndef multi_constructor(loader, tag_suffix, node):\n    \"\"\"\n    Deal with !Ref style function format\n    \"\"\"\n\n    if tag_suffix not in UNCONVERTED_SUFFIXES:\n        tag_suffix = '{}{}'.format(FN_PREFIX, tag_suffix)\n\n    constructor = None\n    if tag_suffix == 'Fn::GetAtt':\n        constructor = construct_getatt\n    elif isinstance(node, ScalarNode):\n        constructor = loader.construct_scalar\n    elif isinstance(node, SequenceNode):\n        constructor = loader.construct_sequence\n    elif isinstance(node, MappingNode):\n        constructor = loader.construct_mapping\n    else:\n        raise 'Bad tag: !{}'.format(tag_suffix)\n\n    return DictNode({tag_suffix: constructor(node)}, node.start_mark, node.end_mark)\n\n\ndef construct_getatt(node):\n    \"\"\"\n    Reconstruct !GetAtt into a list\n    \"\"\"\n\n    if isinstance(node.value, str):\n        return ListNode(node.value.split('.'), node.start_mark, node.end_mark)\n    if isinstance(node.value, list):\n        return ListNode([s.value for s in node.value], node.start_mark, node.end_mark)\n\n    raise ValueError('Unexpected node type: {}'.format(type(node.value)))\n\n\ndef loads(yaml_string, fname=None):\n    \"\"\"\n    Load the given YAML string\n    \"\"\"\n    loader = MarkedLoader(yaml_string, fname)\n    loader.add_multi_constructor('!', multi_constructor)\n\n    template = loader.get_single_data()\n    # Convert an empty file to an empty dict\n    if template is None:\n        template = {}\n\n    return template\n\n\ndef load(filename: str) -> Tuple[DictNode, List[Tuple[int, str]]]:\n    \"\"\"\n    Load the given YAML file\n    \"\"\"\n\n    file_path = Path(filename)\n    content = file_path.read_text()\n    file_lines = [(idx + 1, line) for idx, line in enumerate(content.splitlines(keepends=True))]\n\n    return (loads(content, filename), file_lines)\n", "path": "checkov/cloudformation/parser/cfn_yaml.py"}, {"content": "import logging\nfrom typing import Tuple, List, Union, Dict, Optional\n\nfrom checkov.cloudformation.parser import cfn_yaml\nfrom checkov.common.parsers.json import parse as json_parse\nfrom checkov.common.parsers.node import DictNode\nfrom checkov.cloudformation.parser.cfn_keywords import TemplateSections\nfrom yaml.parser import ScannerError\nfrom yaml import YAMLError\n\nLOGGER = logging.getLogger(__name__)\n\n\ndef parse(\n    filename: str, out_parsing_errors: Optional[Dict[str, str]] = None\n) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:\n    \"\"\"\n    Decode filename into an object\n    \"\"\"\n    template = None\n    template_lines = None\n    error = None\n\n    if out_parsing_errors is None:\n        out_parsing_errors = {}\n\n    try:\n        (template, template_lines) = cfn_yaml.load(filename)\n    except IOError as err:\n        if err.errno == 2:\n            error = f\"Template file not found: {filename} - {err}\"\n            LOGGER.error(error)\n        elif err.errno == 21:\n            error = f\"Template references a directory, not a file: {filename} - {err}\"\n            LOGGER.error(error)\n        elif err.errno == 13:\n            error = f\"Permission denied when accessing template file: {filename} - {err}\"\n            LOGGER.error(error)\n    except UnicodeDecodeError as err:\n        error = f\"Cannot read file contents: {filename} - {err}\"\n        LOGGER.error(error)\n    except cfn_yaml.CfnParseError as err:\n        if \"Null value at\" in err.message:\n            LOGGER.info(f\"Null values do not exist in CFN templates: {filename} - {err}\")\n            return None, None\n\n        error = f\"Parsing error in file: {filename} - {err}\"\n        LOGGER.info(error)\n    except ValueError as err:\n        error = f\"Parsing error in file: {filename} - {err}\"\n        LOGGER.info(error)\n    except ScannerError as err:\n        if err.problem in [\"found character '\\\\t' that cannot start any token\", \"found unknown escape character\"]:\n            try:\n                (template, template_lines) = json_parse(filename, allow_nulls=False)\n            except Exception as json_err:  # pylint: disable=W0703\n                error = f\"Template {filename} is malformed: {err.problem}. Tried to parse {filename} as JSON but got error: {json_err}\"\n                LOGGER.info(error)\n    except YAMLError as err:\n        error = f\"Parsing error in file: {filename} - {err}\"\n        LOGGER.info(error)\n\n    if error:\n        out_parsing_errors[filename] = error\n\n    if isinstance(template, dict):\n        resources = template.get(TemplateSections.RESOURCES.value, None)\n        if resources:\n            if \"__startline__\" in resources:\n                del resources[\"__startline__\"]\n            if \"__endline__\" in resources:\n                del resources[\"__endline__\"]\n    return template, template_lines\n", "path": "checkov/cloudformation/parser/__init__.py"}]}