We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Update solc-version detector with Solidity 0.7
Currently, the recommended versions are:
```
- 0.5.11 - 0.5.13,
- 0.5.15 - 0.5.17,
- 0.6.8,
- 0.6.10 - 0.6.11. Use a simple pragma version that allows any of these versions. 
```

We need to review the 0.7.x branch and update the detector (including 0.6/0.8)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `slither/detectors/attributes/incorrect_solc.py`
Content:
```
1 """
2     Check if an incorrect version of solc is used
3 """
4 
5 import re
6 from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
7 from slither.formatters.attributes.incorrect_solc import custom_format
8 
9 # group:
10 # 0: ^ > >= < <= (optional)
11 # 1: ' ' (optional)
12 # 2: version number
13 # 3: version number
14 # 4: version number
15 
16 # pylint: disable=anomalous-backslash-in-string
17 PATTERN = re.compile("(\^|>|>=|<|<=)?([ ]+)?(\d+)\.(\d+)\.(\d+)")
18 
19 
20 class IncorrectSolc(AbstractDetector):
21     """
22     Check if an old version of solc is used
23     """
24 
25     ARGUMENT = "solc-version"
26     HELP = "Incorrect Solidity version"
27     IMPACT = DetectorClassification.INFORMATIONAL
28     CONFIDENCE = DetectorClassification.HIGH
29 
30     WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity"
31 
32     WIKI_TITLE = "Incorrect versions of Solidity"
33     WIKI_DESCRIPTION = """
34 `solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.
35 We also recommend avoiding complex `pragma` statement."""
36     WIKI_RECOMMENDATION = """
37 Deploy with any of the following Solidity versions:
38 - 0.5.11 - 0.5.13,
39 - 0.5.15 - 0.5.17,
40 - 0.6.8,
41 - 0.6.10 - 0.6.11.
42 Use a simple pragma version that allows any of these versions.
43 Consider using the latest version of Solidity for testing."""
44 
45     COMPLEX_PRAGMA_TXT = "is too complex"
46     OLD_VERSION_TXT = "allows old versions"
47     LESS_THAN_TXT = "uses lesser than"
48 
49     TOO_RECENT_VERSION_TXT = (
50         "necessitates a version too recent to be trusted. Consider deploying with 0.6.11"
51     )
52     BUGGY_VERSION_TXT = (
53         "is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)"
54     )
55 
56     # Indicates the allowed versions. Must be formatted in increasing order.
57     ALLOWED_VERSIONS = [
58         "0.5.11",
59         "0.5.12",
60         "0.5.13",
61         "0.5.15",
62         "0.5.16",
63         "0.5.17",
64         "0.6.8",
65         "0.6.10",
66         "0.6.11",
67     ]
68 
69     # Indicates the versions that should not be used.
70     BUGGY_VERSIONS = [
71         "0.4.22",
72         "^0.4.22",
73         "0.5.5",
74         "^0.5.5",
75         "0.5.6",
76         "^0.5.6",
77         "0.5.14",
78         "^0.5.14",
79         "0.6.9",
80         "^0.6.9",
81     ]
82 
83     def _check_version(self, version):
84         op = version[0]
85         if op and op not in [">", ">=", "^"]:
86             return self.LESS_THAN_TXT
87         version_number = ".".join(version[2:])
88         if version_number not in self.ALLOWED_VERSIONS:
89             if list(map(int, version[2:])) > list(map(int, self.ALLOWED_VERSIONS[-1].split("."))):
90                 return self.TOO_RECENT_VERSION_TXT
91             return self.OLD_VERSION_TXT
92         return None
93 
94     def _check_pragma(self, version):
95         if version in self.BUGGY_VERSIONS:
96             return self.BUGGY_VERSION_TXT
97         versions = PATTERN.findall(version)
98         if len(versions) == 1:
99             version = versions[0]
100             return self._check_version(version)
101         if len(versions) == 2:
102             version_left = versions[0]
103             version_right = versions[1]
104             # Only allow two elements if the second one is
105             # <0.5.0 or <0.6.0
106             if version_right not in [
107                 ("<", "", "0", "5", "0"),
108                 ("<", "", "0", "6", "0"),
109                 ("<", "", "0", "7", "0"),
110             ]:
111                 return self.COMPLEX_PRAGMA_TXT
112             return self._check_version(version_left)
113         return self.COMPLEX_PRAGMA_TXT
114 
115     def _detect(self):
116         """
117         Detects pragma statements that allow for outdated solc versions.
118         :return: Returns the relevant JSON data for the findings.
119         """
120         # Detect all version related pragmas and check if they are disallowed.
121         results = []
122         pragma = self.slither.pragma_directives
123         disallowed_pragmas = []
124 
125         for p in pragma:
126             # Skip any pragma directives which do not refer to version
127             if len(p.directive) < 1 or p.directive[0] != "solidity":
128                 continue
129 
130             # This is version, so we test if this is disallowed.
131             reason = self._check_pragma(p.version)
132             if reason:
133                 disallowed_pragmas.append((reason, p))
134 
135         # If we found any disallowed pragmas, we output our findings.
136         if disallowed_pragmas:
137             for (reason, p) in disallowed_pragmas:
138                 info = ["Pragma version", p, f" {reason}\n"]
139 
140                 json = self.generate_result(info)
141 
142                 results.append(json)
143 
144         if self.slither.crytic_compile:
145             if self.slither.crytic_compile.compiler_version:
146                 if (
147                     self.slither.crytic_compile.compiler_version.version
148                     not in self.ALLOWED_VERSIONS
149                 ):
150                     info = [
151                         "solc-",
152                         self.slither.crytic_compile.compiler_version.version,
153                         " is not recommended for deployment\n",
154                     ]
155 
156                     json = self.generate_result(info)
157 
158                     # TODO: Once crytic-compile adds config file info, add a source mapping element pointing to
159                     #       the line in the config that specifies the problematic version of solc
160 
161                     results.append(json)
162 
163         return results
164 
165     @staticmethod
166     def _format(slither, result):
167         custom_format(slither, result)
168
```

Path: `slither/detectors/statements/array_length_assignment.py`
Content:
```
1 """
2 Module detecting assignment of array length
3 """
4 
5 from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
6 from slither.core.cfg.node import NodeType
7 from slither.slithir.operations import Assignment, Length
8 from slither.slithir.variables.reference import ReferenceVariable
9 from slither.slithir.operations.binary import Binary
10 from slither.analyses.data_dependency.data_dependency import is_tainted
11 
12 
13 def detect_array_length_assignment(contract):
14     """
15     Detects and returns all nodes which assign array length.
16     :param contract: Contract to detect assignment within.
17     :return: A list of tuples with (Variable, node) where Variable references an array whose length was set by node.
18     """
19 
20     # Create our result set.
21     results = set()
22 
23     # Loop for each function and modifier.
24     # pylint: disable=too-many-nested-blocks
25     for function in contract.functions_and_modifiers_declared:
26         # Define a set of reference variables which refer to array length.
27         array_length_refs = set()
28 
29         # Loop for every node in this function, looking for expressions where array length references are made,
30         # and subsequent expressions where array length references are assigned to.
31         for node in function.nodes:
32             if node.type == NodeType.EXPRESSION:
33                 for ir in node.irs:
34 
35                     # First we look for the member access for 'length', for which a reference is created.
36                     # We add the reference to our list of array length references.
37                     if isinstance(ir, Length):  # a
38                         #                            if ir.variable_right == "length":
39                         array_length_refs.add(ir.lvalue)
40 
41                     # If we have an assignment/binary operation, verify the left side refers to a reference variable
42                     # which is in our list or array length references. (Array length is being assigned to).
43                     elif isinstance(ir, (Assignment, Binary)):
44                         if isinstance(ir.lvalue, ReferenceVariable):
45                             if ir.lvalue in array_length_refs and any(
46                                 is_tainted(v, contract) for v in ir.read
47                             ):
48                                 # the taint is not precise enough yet
49                                 # as a result, REF_0 = REF_0 + 1
50                                 # where REF_0 points to a LENGTH operation
51                                 # is considered as tainted
52                                 if ir.lvalue in ir.read:
53                                     continue
54                                 results.add(node)
55                                 break
56 
57     # Return the resulting set of nodes which set array length.
58     return results
59 
60 
61 class ArrayLengthAssignment(AbstractDetector):
62     """
63     Array length assignment
64     """
65 
66     ARGUMENT = "controlled-array-length"
67     HELP = "Tainted array length assignment"
68     IMPACT = DetectorClassification.HIGH
69     CONFIDENCE = DetectorClassification.MEDIUM
70 
71     WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment"
72 
73     WIKI_TITLE = "Array Length Assignment"
74     WIKI_DESCRIPTION = """Detects the direct assignment of an array's length."""
75     WIKI_EXPLOIT_SCENARIO = """
76 ```solidity
77 contract A {
78 	uint[] testArray; // dynamic size array
79 
80 	function f(uint usersCount) public {
81 		// ...
82 		testArray.length = usersCount;
83 		// ...
84 	}
85 
86 	function g(uint userIndex, uint val) public {
87 		// ...
88 		testArray[userIndex] = val;
89 		// ...
90 	}
91 }
92 ```
93 Contract storage/state-variables are indexed by a 256-bit integer.
94 The user can set the array length to `2**256-1` in order to index all storage slots. 
95 In the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired. 
96 Note that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker."""
97 
98     WIKI_RECOMMENDATION = """Do not allow array lengths to be set directly set; instead, opt to add values as needed.
99 Otherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment."""
100 
101     def _detect(self):
102         """
103         Detect array length assignments
104         """
105         results = []
106         for contract in self.contracts:
107             array_length_assignments = detect_array_length_assignment(contract)
108             if array_length_assignments:
109                 contract_info = [
110                     contract,
111                     " contract sets array length with a user-controlled value:\n",
112                 ]
113                 for node in array_length_assignments:
114                     node_info = contract_info + ["\t- ", node, "\n"]
115                     res = self.generate_result(node_info)
116                     results.append(res)
117 
118         return results
119
```
--- 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/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py
--- a/slither/detectors/attributes/incorrect_solc.py
+++ b/slither/detectors/attributes/incorrect_solc.py
@@ -35,10 +35,9 @@
 We also recommend avoiding complex `pragma` statement."""
     WIKI_RECOMMENDATION = """
 Deploy with any of the following Solidity versions:
-- 0.5.11 - 0.5.13,
-- 0.5.15 - 0.5.17,
-- 0.6.8,
-- 0.6.10 - 0.6.11.
+- 0.5.16 - 0.5.17
+- 0.6.11 - 0.6.12
+- 0.7.5 - 0.7.6
 Use a simple pragma version that allows any of these versions.
 Consider using the latest version of Solidity for testing."""
 
@@ -47,7 +46,7 @@
     LESS_THAN_TXT = "uses lesser than"
 
     TOO_RECENT_VERSION_TXT = (
-        "necessitates a version too recent to be trusted. Consider deploying with 0.6.11"
+        "necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6"
     )
     BUGGY_VERSION_TXT = (
         "is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)"
@@ -55,15 +54,12 @@
 
     # Indicates the allowed versions. Must be formatted in increasing order.
     ALLOWED_VERSIONS = [
-        "0.5.11",
-        "0.5.12",
-        "0.5.13",
-        "0.5.15",
         "0.5.16",
         "0.5.17",
-        "0.6.8",
-        "0.6.10",
         "0.6.11",
+        "0.6.12",
+        "0.7.5",
+        "0.7.6",
     ]
 
     # Indicates the versions that should not be used.
diff --git a/slither/detectors/statements/array_length_assignment.py b/slither/detectors/statements/array_length_assignment.py
--- a/slither/detectors/statements/array_length_assignment.py
+++ b/slither/detectors/statements/array_length_assignment.py
@@ -103,6 +103,9 @@
         Detect array length assignments
         """
         results = []
+        # Starting from 0.6 .length is read only
+        if self.slither.solc_version >= "0.6.":
+            return results
         for contract in self.contracts:
             array_length_assignments = detect_array_length_assignment(contract)
             if array_length_assignments:

{"golden_diff": "diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py\n--- a/slither/detectors/attributes/incorrect_solc.py\n+++ b/slither/detectors/attributes/incorrect_solc.py\n@@ -35,10 +35,9 @@\n We also recommend avoiding complex `pragma` statement.\"\"\"\n     WIKI_RECOMMENDATION = \"\"\"\n Deploy with any of the following Solidity versions:\n-- 0.5.11 - 0.5.13,\n-- 0.5.15 - 0.5.17,\n-- 0.6.8,\n-- 0.6.10 - 0.6.11.\n+- 0.5.16 - 0.5.17\n+- 0.6.11 - 0.6.12\n+- 0.7.5 - 0.7.6\n Use a simple pragma version that allows any of these versions.\n Consider using the latest version of Solidity for testing.\"\"\"\n \n@@ -47,7 +46,7 @@\n     LESS_THAN_TXT = \"uses lesser than\"\n \n     TOO_RECENT_VERSION_TXT = (\n-        \"necessitates a version too recent to be trusted. Consider deploying with 0.6.11\"\n+        \"necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6\"\n     )\n     BUGGY_VERSION_TXT = (\n         \"is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)\"\n@@ -55,15 +54,12 @@\n \n     # Indicates the allowed versions. Must be formatted in increasing order.\n     ALLOWED_VERSIONS = [\n-        \"0.5.11\",\n-        \"0.5.12\",\n-        \"0.5.13\",\n-        \"0.5.15\",\n         \"0.5.16\",\n         \"0.5.17\",\n-        \"0.6.8\",\n-        \"0.6.10\",\n         \"0.6.11\",\n+        \"0.6.12\",\n+        \"0.7.5\",\n+        \"0.7.6\",\n     ]\n \n     # Indicates the versions that should not be used.\ndiff --git a/slither/detectors/statements/array_length_assignment.py b/slither/detectors/statements/array_length_assignment.py\n--- a/slither/detectors/statements/array_length_assignment.py\n+++ b/slither/detectors/statements/array_length_assignment.py\n@@ -103,6 +103,9 @@\n         Detect array length assignments\n         \"\"\"\n         results = []\n+        # Starting from 0.6 .length is read only\n+        if self.slither.solc_version >= \"0.6.\":\n+            return results\n         for contract in self.contracts:\n             array_length_assignments = detect_array_length_assignment(contract)\n             if array_length_assignments:\n", "issue": "Update solc-version detector with Solidity 0.7\nCurrently, the recommended versions are:\r\n```\r\n- 0.5.11 - 0.5.13,\r\n- 0.5.15 - 0.5.17,\r\n- 0.6.8,\r\n- 0.6.10 - 0.6.11. Use a simple pragma version that allows any of these versions. \r\n```\r\n\r\nWe need to review the 0.7.x branch and update the detector (including 0.6/0.8)\n", "before_files": [{"content": "\"\"\"\n    Check if an incorrect version of solc is used\n\"\"\"\n\nimport re\nfrom slither.detectors.abstract_detector import AbstractDetector, DetectorClassification\nfrom slither.formatters.attributes.incorrect_solc import custom_format\n\n# group:\n# 0: ^ > >= < <= (optional)\n# 1: ' ' (optional)\n# 2: version number\n# 3: version number\n# 4: version number\n\n# pylint: disable=anomalous-backslash-in-string\nPATTERN = re.compile(\"(\\^|>|>=|<|<=)?([ ]+)?(\\d+)\\.(\\d+)\\.(\\d+)\")\n\n\nclass IncorrectSolc(AbstractDetector):\n    \"\"\"\n    Check if an old version of solc is used\n    \"\"\"\n\n    ARGUMENT = \"solc-version\"\n    HELP = \"Incorrect Solidity version\"\n    IMPACT = DetectorClassification.INFORMATIONAL\n    CONFIDENCE = DetectorClassification.HIGH\n\n    WIKI = \"https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity\"\n\n    WIKI_TITLE = \"Incorrect versions of Solidity\"\n    WIKI_DESCRIPTION = \"\"\"\n`solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.\nWe also recommend avoiding complex `pragma` statement.\"\"\"\n    WIKI_RECOMMENDATION = \"\"\"\nDeploy with any of the following Solidity versions:\n- 0.5.11 - 0.5.13,\n- 0.5.15 - 0.5.17,\n- 0.6.8,\n- 0.6.10 - 0.6.11.\nUse a simple pragma version that allows any of these versions.\nConsider using the latest version of Solidity for testing.\"\"\"\n\n    COMPLEX_PRAGMA_TXT = \"is too complex\"\n    OLD_VERSION_TXT = \"allows old versions\"\n    LESS_THAN_TXT = \"uses lesser than\"\n\n    TOO_RECENT_VERSION_TXT = (\n        \"necessitates a version too recent to be trusted. Consider deploying with 0.6.11\"\n    )\n    BUGGY_VERSION_TXT = (\n        \"is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)\"\n    )\n\n    # Indicates the allowed versions. Must be formatted in increasing order.\n    ALLOWED_VERSIONS = [\n        \"0.5.11\",\n        \"0.5.12\",\n        \"0.5.13\",\n        \"0.5.15\",\n        \"0.5.16\",\n        \"0.5.17\",\n        \"0.6.8\",\n        \"0.6.10\",\n        \"0.6.11\",\n    ]\n\n    # Indicates the versions that should not be used.\n    BUGGY_VERSIONS = [\n        \"0.4.22\",\n        \"^0.4.22\",\n        \"0.5.5\",\n        \"^0.5.5\",\n        \"0.5.6\",\n        \"^0.5.6\",\n        \"0.5.14\",\n        \"^0.5.14\",\n        \"0.6.9\",\n        \"^0.6.9\",\n    ]\n\n    def _check_version(self, version):\n        op = version[0]\n        if op and op not in [\">\", \">=\", \"^\"]:\n            return self.LESS_THAN_TXT\n        version_number = \".\".join(version[2:])\n        if version_number not in self.ALLOWED_VERSIONS:\n            if list(map(int, version[2:])) > list(map(int, self.ALLOWED_VERSIONS[-1].split(\".\"))):\n                return self.TOO_RECENT_VERSION_TXT\n            return self.OLD_VERSION_TXT\n        return None\n\n    def _check_pragma(self, version):\n        if version in self.BUGGY_VERSIONS:\n            return self.BUGGY_VERSION_TXT\n        versions = PATTERN.findall(version)\n        if len(versions) == 1:\n            version = versions[0]\n            return self._check_version(version)\n        if len(versions) == 2:\n            version_left = versions[0]\n            version_right = versions[1]\n            # Only allow two elements if the second one is\n            # <0.5.0 or <0.6.0\n            if version_right not in [\n                (\"<\", \"\", \"0\", \"5\", \"0\"),\n                (\"<\", \"\", \"0\", \"6\", \"0\"),\n                (\"<\", \"\", \"0\", \"7\", \"0\"),\n            ]:\n                return self.COMPLEX_PRAGMA_TXT\n            return self._check_version(version_left)\n        return self.COMPLEX_PRAGMA_TXT\n\n    def _detect(self):\n        \"\"\"\n        Detects pragma statements that allow for outdated solc versions.\n        :return: Returns the relevant JSON data for the findings.\n        \"\"\"\n        # Detect all version related pragmas and check if they are disallowed.\n        results = []\n        pragma = self.slither.pragma_directives\n        disallowed_pragmas = []\n\n        for p in pragma:\n            # Skip any pragma directives which do not refer to version\n            if len(p.directive) < 1 or p.directive[0] != \"solidity\":\n                continue\n\n            # This is version, so we test if this is disallowed.\n            reason = self._check_pragma(p.version)\n            if reason:\n                disallowed_pragmas.append((reason, p))\n\n        # If we found any disallowed pragmas, we output our findings.\n        if disallowed_pragmas:\n            for (reason, p) in disallowed_pragmas:\n                info = [\"Pragma version\", p, f\" {reason}\\n\"]\n\n                json = self.generate_result(info)\n\n                results.append(json)\n\n        if self.slither.crytic_compile:\n            if self.slither.crytic_compile.compiler_version:\n                if (\n                    self.slither.crytic_compile.compiler_version.version\n                    not in self.ALLOWED_VERSIONS\n                ):\n                    info = [\n                        \"solc-\",\n                        self.slither.crytic_compile.compiler_version.version,\n                        \" is not recommended for deployment\\n\",\n                    ]\n\n                    json = self.generate_result(info)\n\n                    # TODO: Once crytic-compile adds config file info, add a source mapping element pointing to\n                    #       the line in the config that specifies the problematic version of solc\n\n                    results.append(json)\n\n        return results\n\n    @staticmethod\n    def _format(slither, result):\n        custom_format(slither, result)\n", "path": "slither/detectors/attributes/incorrect_solc.py"}, {"content": "\"\"\"\nModule detecting assignment of array length\n\"\"\"\n\nfrom slither.detectors.abstract_detector import AbstractDetector, DetectorClassification\nfrom slither.core.cfg.node import NodeType\nfrom slither.slithir.operations import Assignment, Length\nfrom slither.slithir.variables.reference import ReferenceVariable\nfrom slither.slithir.operations.binary import Binary\nfrom slither.analyses.data_dependency.data_dependency import is_tainted\n\n\ndef detect_array_length_assignment(contract):\n    \"\"\"\n    Detects and returns all nodes which assign array length.\n    :param contract: Contract to detect assignment within.\n    :return: A list of tuples with (Variable, node) where Variable references an array whose length was set by node.\n    \"\"\"\n\n    # Create our result set.\n    results = set()\n\n    # Loop for each function and modifier.\n    # pylint: disable=too-many-nested-blocks\n    for function in contract.functions_and_modifiers_declared:\n        # Define a set of reference variables which refer to array length.\n        array_length_refs = set()\n\n        # Loop for every node in this function, looking for expressions where array length references are made,\n        # and subsequent expressions where array length references are assigned to.\n        for node in function.nodes:\n            if node.type == NodeType.EXPRESSION:\n                for ir in node.irs:\n\n                    # First we look for the member access for 'length', for which a reference is created.\n                    # We add the reference to our list of array length references.\n                    if isinstance(ir, Length):  # a\n                        #                            if ir.variable_right == \"length\":\n                        array_length_refs.add(ir.lvalue)\n\n                    # If we have an assignment/binary operation, verify the left side refers to a reference variable\n                    # which is in our list or array length references. (Array length is being assigned to).\n                    elif isinstance(ir, (Assignment, Binary)):\n                        if isinstance(ir.lvalue, ReferenceVariable):\n                            if ir.lvalue in array_length_refs and any(\n                                is_tainted(v, contract) for v in ir.read\n                            ):\n                                # the taint is not precise enough yet\n                                # as a result, REF_0 = REF_0 + 1\n                                # where REF_0 points to a LENGTH operation\n                                # is considered as tainted\n                                if ir.lvalue in ir.read:\n                                    continue\n                                results.add(node)\n                                break\n\n    # Return the resulting set of nodes which set array length.\n    return results\n\n\nclass ArrayLengthAssignment(AbstractDetector):\n    \"\"\"\n    Array length assignment\n    \"\"\"\n\n    ARGUMENT = \"controlled-array-length\"\n    HELP = \"Tainted array length assignment\"\n    IMPACT = DetectorClassification.HIGH\n    CONFIDENCE = DetectorClassification.MEDIUM\n\n    WIKI = \"https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment\"\n\n    WIKI_TITLE = \"Array Length Assignment\"\n    WIKI_DESCRIPTION = \"\"\"Detects the direct assignment of an array's length.\"\"\"\n    WIKI_EXPLOIT_SCENARIO = \"\"\"\n```solidity\ncontract A {\n\tuint[] testArray; // dynamic size array\n\n\tfunction f(uint usersCount) public {\n\t\t// ...\n\t\ttestArray.length = usersCount;\n\t\t// ...\n\t}\n\n\tfunction g(uint userIndex, uint val) public {\n\t\t// ...\n\t\ttestArray[userIndex] = val;\n\t\t// ...\n\t}\n}\n```\nContract storage/state-variables are indexed by a 256-bit integer.\nThe user can set the array length to `2**256-1` in order to index all storage slots. \nIn the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired. \nNote that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker.\"\"\"\n\n    WIKI_RECOMMENDATION = \"\"\"Do not allow array lengths to be set directly set; instead, opt to add values as needed.\nOtherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment.\"\"\"\n\n    def _detect(self):\n        \"\"\"\n        Detect array length assignments\n        \"\"\"\n        results = []\n        for contract in self.contracts:\n            array_length_assignments = detect_array_length_assignment(contract)\n            if array_length_assignments:\n                contract_info = [\n                    contract,\n                    \" contract sets array length with a user-controlled value:\\n\",\n                ]\n                for node in array_length_assignments:\n                    node_info = contract_info + [\"\\t- \", node, \"\\n\"]\n                    res = self.generate_result(node_info)\n                    results.append(res)\n\n        return results\n", "path": "slither/detectors/statements/array_length_assignment.py"}], "after_files": [{"content": "\"\"\"\n    Check if an incorrect version of solc is used\n\"\"\"\n\nimport re\nfrom slither.detectors.abstract_detector import AbstractDetector, DetectorClassification\nfrom slither.formatters.attributes.incorrect_solc import custom_format\n\n# group:\n# 0: ^ > >= < <= (optional)\n# 1: ' ' (optional)\n# 2: version number\n# 3: version number\n# 4: version number\n\n# pylint: disable=anomalous-backslash-in-string\nPATTERN = re.compile(\"(\\^|>|>=|<|<=)?([ ]+)?(\\d+)\\.(\\d+)\\.(\\d+)\")\n\n\nclass IncorrectSolc(AbstractDetector):\n    \"\"\"\n    Check if an old version of solc is used\n    \"\"\"\n\n    ARGUMENT = \"solc-version\"\n    HELP = \"Incorrect Solidity version\"\n    IMPACT = DetectorClassification.INFORMATIONAL\n    CONFIDENCE = DetectorClassification.HIGH\n\n    WIKI = \"https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity\"\n\n    WIKI_TITLE = \"Incorrect versions of Solidity\"\n    WIKI_DESCRIPTION = \"\"\"\n`solc` frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.\nWe also recommend avoiding complex `pragma` statement.\"\"\"\n    WIKI_RECOMMENDATION = \"\"\"\nDeploy with any of the following Solidity versions:\n- 0.5.16 - 0.5.17\n- 0.6.11 - 0.6.12\n- 0.7.5 - 0.7.6\nUse a simple pragma version that allows any of these versions.\nConsider using the latest version of Solidity for testing.\"\"\"\n\n    COMPLEX_PRAGMA_TXT = \"is too complex\"\n    OLD_VERSION_TXT = \"allows old versions\"\n    LESS_THAN_TXT = \"uses lesser than\"\n\n    TOO_RECENT_VERSION_TXT = (\n        \"necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6\"\n    )\n    BUGGY_VERSION_TXT = (\n        \"is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)\"\n    )\n\n    # Indicates the allowed versions. Must be formatted in increasing order.\n    ALLOWED_VERSIONS = [\n        \"0.5.16\",\n        \"0.5.17\",\n        \"0.6.11\",\n        \"0.6.12\",\n        \"0.7.5\",\n        \"0.7.6\",\n    ]\n\n    # Indicates the versions that should not be used.\n    BUGGY_VERSIONS = [\n        \"0.4.22\",\n        \"^0.4.22\",\n        \"0.5.5\",\n        \"^0.5.5\",\n        \"0.5.6\",\n        \"^0.5.6\",\n        \"0.5.14\",\n        \"^0.5.14\",\n        \"0.6.9\",\n        \"^0.6.9\",\n    ]\n\n    def _check_version(self, version):\n        op = version[0]\n        if op and op not in [\">\", \">=\", \"^\"]:\n            return self.LESS_THAN_TXT\n        version_number = \".\".join(version[2:])\n        if version_number not in self.ALLOWED_VERSIONS:\n            if list(map(int, version[2:])) > list(map(int, self.ALLOWED_VERSIONS[-1].split(\".\"))):\n                return self.TOO_RECENT_VERSION_TXT\n            return self.OLD_VERSION_TXT\n        return None\n\n    def _check_pragma(self, version):\n        if version in self.BUGGY_VERSIONS:\n            return self.BUGGY_VERSION_TXT\n        versions = PATTERN.findall(version)\n        if len(versions) == 1:\n            version = versions[0]\n            return self._check_version(version)\n        if len(versions) == 2:\n            version_left = versions[0]\n            version_right = versions[1]\n            # Only allow two elements if the second one is\n            # <0.5.0 or <0.6.0\n            if version_right not in [\n                (\"<\", \"\", \"0\", \"5\", \"0\"),\n                (\"<\", \"\", \"0\", \"6\", \"0\"),\n                (\"<\", \"\", \"0\", \"7\", \"0\"),\n            ]:\n                return self.COMPLEX_PRAGMA_TXT\n            return self._check_version(version_left)\n        return self.COMPLEX_PRAGMA_TXT\n\n    def _detect(self):\n        \"\"\"\n        Detects pragma statements that allow for outdated solc versions.\n        :return: Returns the relevant JSON data for the findings.\n        \"\"\"\n        # Detect all version related pragmas and check if they are disallowed.\n        results = []\n        pragma = self.slither.pragma_directives\n        disallowed_pragmas = []\n\n        for p in pragma:\n            # Skip any pragma directives which do not refer to version\n            if len(p.directive) < 1 or p.directive[0] != \"solidity\":\n                continue\n\n            # This is version, so we test if this is disallowed.\n            reason = self._check_pragma(p.version)\n            if reason:\n                disallowed_pragmas.append((reason, p))\n\n        # If we found any disallowed pragmas, we output our findings.\n        if disallowed_pragmas:\n            for (reason, p) in disallowed_pragmas:\n                info = [\"Pragma version\", p, f\" {reason}\\n\"]\n\n                json = self.generate_result(info)\n\n                results.append(json)\n\n        if self.slither.crytic_compile:\n            if self.slither.crytic_compile.compiler_version:\n                if (\n                    self.slither.crytic_compile.compiler_version.version\n                    not in self.ALLOWED_VERSIONS\n                ):\n                    info = [\n                        \"solc-\",\n                        self.slither.crytic_compile.compiler_version.version,\n                        \" is not recommended for deployment\\n\",\n                    ]\n\n                    json = self.generate_result(info)\n\n                    # TODO: Once crytic-compile adds config file info, add a source mapping element pointing to\n                    #       the line in the config that specifies the problematic version of solc\n\n                    results.append(json)\n\n        return results\n\n    @staticmethod\n    def _format(slither, result):\n        custom_format(slither, result)\n", "path": "slither/detectors/attributes/incorrect_solc.py"}, {"content": "\"\"\"\nModule detecting assignment of array length\n\"\"\"\n\nfrom slither.detectors.abstract_detector import AbstractDetector, DetectorClassification\nfrom slither.core.cfg.node import NodeType\nfrom slither.slithir.operations import Assignment, Length\nfrom slither.slithir.variables.reference import ReferenceVariable\nfrom slither.slithir.operations.binary import Binary\nfrom slither.analyses.data_dependency.data_dependency import is_tainted\n\n\ndef detect_array_length_assignment(contract):\n    \"\"\"\n    Detects and returns all nodes which assign array length.\n    :param contract: Contract to detect assignment within.\n    :return: A list of tuples with (Variable, node) where Variable references an array whose length was set by node.\n    \"\"\"\n\n    # Create our result set.\n    results = set()\n\n    # Loop for each function and modifier.\n    # pylint: disable=too-many-nested-blocks\n    for function in contract.functions_and_modifiers_declared:\n        # Define a set of reference variables which refer to array length.\n        array_length_refs = set()\n\n        # Loop for every node in this function, looking for expressions where array length references are made,\n        # and subsequent expressions where array length references are assigned to.\n        for node in function.nodes:\n            if node.type == NodeType.EXPRESSION:\n                for ir in node.irs:\n\n                    # First we look for the member access for 'length', for which a reference is created.\n                    # We add the reference to our list of array length references.\n                    if isinstance(ir, Length):  # a\n                        #                            if ir.variable_right == \"length\":\n                        array_length_refs.add(ir.lvalue)\n\n                    # If we have an assignment/binary operation, verify the left side refers to a reference variable\n                    # which is in our list or array length references. (Array length is being assigned to).\n                    elif isinstance(ir, (Assignment, Binary)):\n                        if isinstance(ir.lvalue, ReferenceVariable):\n                            if ir.lvalue in array_length_refs and any(\n                                is_tainted(v, contract) for v in ir.read\n                            ):\n                                # the taint is not precise enough yet\n                                # as a result, REF_0 = REF_0 + 1\n                                # where REF_0 points to a LENGTH operation\n                                # is considered as tainted\n                                if ir.lvalue in ir.read:\n                                    continue\n                                results.add(node)\n                                break\n\n    # Return the resulting set of nodes which set array length.\n    return results\n\n\nclass ArrayLengthAssignment(AbstractDetector):\n    \"\"\"\n    Array length assignment\n    \"\"\"\n\n    ARGUMENT = \"controlled-array-length\"\n    HELP = \"Tainted array length assignment\"\n    IMPACT = DetectorClassification.HIGH\n    CONFIDENCE = DetectorClassification.MEDIUM\n\n    WIKI = \"https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment\"\n\n    WIKI_TITLE = \"Array Length Assignment\"\n    WIKI_DESCRIPTION = \"\"\"Detects the direct assignment of an array's length.\"\"\"\n    WIKI_EXPLOIT_SCENARIO = \"\"\"\n```solidity\ncontract A {\n\tuint[] testArray; // dynamic size array\n\n\tfunction f(uint usersCount) public {\n\t\t// ...\n\t\ttestArray.length = usersCount;\n\t\t// ...\n\t}\n\n\tfunction g(uint userIndex, uint val) public {\n\t\t// ...\n\t\ttestArray[userIndex] = val;\n\t\t// ...\n\t}\n}\n```\nContract storage/state-variables are indexed by a 256-bit integer.\nThe user can set the array length to `2**256-1` in order to index all storage slots. \nIn the example above, one could call the function `f` to set the array length, then call the function `g` to control any storage slot desired. \nNote that storage slots here are indexed via a hash of the indexers; nonetheless, all storage will still be accessible and could be controlled by the attacker.\"\"\"\n\n    WIKI_RECOMMENDATION = \"\"\"Do not allow array lengths to be set directly set; instead, opt to add values as needed.\nOtherwise, thoroughly review the contract to ensure a user-controlled variable cannot reach an array length assignment.\"\"\"\n\n    def _detect(self):\n        \"\"\"\n        Detect array length assignments\n        \"\"\"\n        results = []\n        # Starting from 0.6 .length is read only\n        if self.slither.solc_version >= \"0.6.\":\n            return results\n        for contract in self.contracts:\n            array_length_assignments = detect_array_length_assignment(contract)\n            if array_length_assignments:\n                contract_info = [\n                    contract,\n                    \" contract sets array length with a user-controlled value:\\n\",\n                ]\n                for node in array_length_assignments:\n                    node_info = contract_info + [\"\\t- \", node, \"\\n\"]\n                    res = self.generate_result(node_info)\n                    results.append(res)\n\n        return results\n", "path": "slither/detectors/statements/array_length_assignment.py"}]}