Repository: crytic/slither

Issue:
Improvements on solc-version detectors
The allowed version is out of date:
https://github.com/crytic/slither/blob/0891f9a8a5e5e096084476e4b2bd292c3685f251/slither/detectors/attributes/incorrect_solc.py#L39

Due to the frequent solc release, we might want to change the logic to allow future releases.

Additionally:
- 0.5.5 should not be used: https://twitter.com/ethchris/status/1105903546602528768
- the wiki link is incorrect


Discussion:
(There appears to be roughly one release per month https://github.com/ethereum/solidity/releases)

The options I see are:
1. Dynamically check released versions from Solidity github. While future proof, we might want to disallow any released versions that are later found to have bugs (e.g. 0.5.5) or deprecated.
2. Specify allowed versions in a config file which gets updated periodically instead of the detector code.
3. Allow user to specify/override allowed versions via CLI option.
4. Retain current logic and update allowed versions in detector code periodically.
5. ?

Any preferences?


Resolving patch:
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
@@ -23,31 +23,43 @@ class IncorrectSolc(AbstractDetector):
     IMPACT = DetectorClassification.INFORMATIONAL
     CONFIDENCE = DetectorClassification.HIGH
 
-    WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-version-of-solidity'
+    WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity'
 
     WIKI_TITLE = 'Incorrect versions of Solidity'
     WIKI_DESCRIPTION = '''
 Solc frequently releases new compiler versions. Using an old version prevents access to new Solidity security checks.
 We recommend avoiding complex pragma statement.'''
-    WIKI_RECOMMENDATION = 'Use Solidity 0.4.25 or 0.5.2.'
+    WIKI_RECOMMENDATION = '''
+Use Solidity 0.4.25 or 0.5.3. Consider using the latest version of Solidity for testing the compilation, and a trusted version for deploying.'''
 
-    COMPLEX_PRAGMA = "is too complex"
-    OLD_VERSION = "allows old versions"
-    LESS_THAN = "uses lesser than"
+    COMPLEX_PRAGMA_TXT = "is too complex"
+    OLD_VERSION_TXT = "allows old versions"
+    LESS_THAN_TXT = "uses lesser than"
+
+    TOO_RECENT_VERSION_TXT = "necessitates versions too recent to be trusted. Consider deploying with 0.5.3"
+    BUGGY_VERSION_TXT = "is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html)"
 
     # Indicates the allowed versions.
-    ALLOWED_VERSIONS = ["0.4.24", "0.4.25", "0.5.2", "0.5.3"]
+    ALLOWED_VERSIONS = ["0.4.25", "0.4.26", "0.5.3"]
+    # Indicates the versions too recent.
+    TOO_RECENT_VERSIONS = ["0.5.4", "0.5.7", "0.5.8", "0.5.9", "0.5.10"]
+    # Indicates the versions that should not be used.
+    BUGGY_VERSIONS = ["0.4.22", "0.5.5", "0.5.6", "^0.4.22", "^0.5.5", "^0.5.6"]
 
     def _check_version(self, version):
         op = version[0]
         if op and not op in ['>', '>=', '^']:
-            return self.LESS_THAN
+            return self.LESS_THAN_TXT
         version_number = '.'.join(version[2:])
         if version_number not in self.ALLOWED_VERSIONS:
-            return self.OLD_VERSION
+            if version_number in self.TOO_RECENT_VERSIONS:
+                return self.TOO_RECENT_VERSION_TXT
+            return self.OLD_VERSION_TXT
         return None
 
     def _check_pragma(self, version):
+        if version in self.BUGGY_VERSIONS:
+            return self.BUGGY_VERSION_TXT
         versions = PATTERN.findall(version)
         if len(versions) == 1:
             version = versions[0]
@@ -58,10 +70,10 @@ def _check_pragma(self, version):
             # Only allow two elements if the second one is
             # <0.5.0 or <0.6.0
             if version_right not in [('<', '', '0', '5', '0'), ('<', '', '0', '6', '0')]:
-                return self.COMPLEX_PRAGMA
+                return self.COMPLEX_PRAGMA_TXT
             return self._check_version(version_left)
         else:
-            return self.COMPLEX_PRAGMA
+            return self.COMPLEX_PRAGMA_TXT
     def _detect(self):
         """
         Detects pragma statements that allow for outdated solc versions.


Test patch:
diff --git a/scripts/tests_generate_expected_json_5.sh b/scripts/tests_generate_expected_json_5.sh
--- a/scripts/tests_generate_expected_json_5.sh
+++ b/scripts/tests_generate_expected_json_5.sh
@@ -20,6 +20,7 @@ generate_expected_json(){
     sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i
 }
 
+#generate_expected_json tests/solc_version_incorrect_05.ast.json "solc-version"
 #generate_expected_json tests/uninitialized-0.5.1.sol "uninitialized-state"
 #generate_expected_json tests/backdoor.sol "backdoor"
 #generate_expected_json tests/backdoor.sol "suicidal"
diff --git a/scripts/travis_test_5.sh b/scripts/travis_test_5.sh
--- a/scripts/travis_test_5.sh
+++ b/scripts/travis_test_5.sh
@@ -69,6 +69,7 @@ test_slither(){
 }
 
 
+test_slither tests/solc_version_incorrect_05.ast.json "solc-version"
 test_slither tests/unchecked_lowlevel-0.5.1.sol "unchecked-lowlevel"
 test_slither tests/unchecked_send-0.5.1.sol "unchecked-send"
 test_slither tests/uninitialized-0.5.1.sol "uninitialized-state"
diff --git a/scripts/travis_test_etherscan.sh b/scripts/travis_test_etherscan.sh
--- a/scripts/travis_test_etherscan.sh
+++ b/scripts/travis_test_etherscan.sh
@@ -10,7 +10,7 @@ chmod +x solc-0.4.25
 
 slither 0x7F37f78cBD74481E593F9C737776F7113d76B315 --solc "./solc-0.4.25"
 
-if [ $? -ne 5 ]
+if [ $? -ne 6 ]
 then
     echo "Etherscan test failed"
     exit -1
diff --git a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json
new file mode 100644
--- /dev/null
+++ b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.json
@@ -0,0 +1,69 @@
+{
+  "success": true,
+  "error": null,
+  "results": {
+    "detectors": [
+      {
+        "check": "solc-version",
+        "impact": "Informational",
+        "confidence": "High",
+        "description": "Pragma version \"^0.5.5\" is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html) (None)\n",
+        "elements": [
+          {
+            "type": "pragma",
+            "name": "^0.5.5",
+            "source_mapping": {
+              "start": 63,
+              "length": 23,
+              "filename_used": "solc_version_incorrect_05.sol",
+              "filename_relative": null,
+              "filename_absolute": null,
+              "filename_short": null,
+              "lines": [],
+              "starting_column": null,
+              "ending_column": null
+            },
+            "type_specific_fields": {
+              "directive": [
+                "solidity",
+                "^",
+                "0.5",
+                ".5"
+              ]
+            }
+          }
+        ]
+      },
+      {
+        "check": "solc-version",
+        "impact": "Informational",
+        "confidence": "High",
+        "description": "Pragma version \"0.5.7\" necessitates versions too recent to be trusted. Consider deploying with 0.5.3 (None)\n",
+        "elements": [
+          {
+            "type": "pragma",
+            "name": "0.5.7",
+            "source_mapping": {
+              "start": 87,
+              "length": 22,
+              "filename_used": "solc_version_incorrect_05.sol",
+              "filename_relative": null,
+              "filename_absolute": null,
+              "filename_short": null,
+              "lines": [],
+              "starting_column": null,
+              "ending_column": null
+            },
+            "type_specific_fields": {
+              "directive": [
+                "solidity",
+                "0.5",
+                ".7"
+              ]
+            }
+          }
+        ]
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt
new file mode 100644
--- /dev/null
+++ b/tests/expected_json/solc_version_incorrect_05.ast.json.solc-version.txt
@@ -0,0 +1,5 @@
+INFO:Detectors:[92m
+Pragma version "^0.5.5" is known to contain severe issue (https://solidity.readthedocs.io/en/v0.5.8/bugs.html) (None)
+Pragma version "0.5.7" necessitates versions too recent to be trusted. Consider deploying with 0.5.3 (None)
+Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-version-of-solidity[0m
+INFO:Slither:tests/solc_version_incorrect_05.ast.json analyzed (1 contracts), 2 result(s) found
diff --git a/tests/solc_version_incorrect_05.ast.json b/tests/solc_version_incorrect_05.ast.json
new file mode 100644
--- /dev/null
+++ b/tests/solc_version_incorrect_05.ast.json
@@ -0,0 +1,82 @@
+JSON AST:
+
+
+======= solc_version_incorrect_05.sol =======
+{
+	"attributes" : 
+	{
+		"absolutePath" : "solc_version_incorrect_05.sol",
+		"exportedSymbols" : 
+		{
+			"Contract" : 
+			[
+				3
+			]
+		}
+	},
+	"children" : 
+	[
+		{
+			"attributes" : 
+			{
+				"literals" : 
+				[
+					"solidity",
+					"^",
+					"0.5",
+					".5"
+				]
+			},
+			"id" : 1,
+			"name" : "PragmaDirective",
+			"src" : "63:23:0"
+		},
+		{
+			"attributes" : 
+			{
+				"literals" : 
+				[
+					"solidity",
+					"0.5",
+					".7"
+				]
+			},
+			"id" : 2,
+			"name" : "PragmaDirective",
+			"src" : "87:22:0"
+		},
+		{
+			"attributes" : 
+			{
+				"baseContracts" : 
+				[
+					null
+				],
+				"contractDependencies" : 
+				[
+					null
+				],
+				"contractKind" : "contract",
+				"documentation" : null,
+				"fullyImplemented" : true,
+				"linearizedBaseContracts" : 
+				[
+					3
+				],
+				"name" : "Contract",
+				"nodes" : 
+				[
+					null
+				],
+				"scope" : 4
+			},
+			"id" : 3,
+			"name" : "ContractDefinition",
+			"src" : "111:21:0"
+		}
+	],
+	"id" : 4,
+	"name" : "SourceUnit",
+	"src" : "63:70:0"
+}
+======= solc_version_incorrect_05.sol:Contract =======
diff --git a/tests/solc_version_incorrect_05.sol b/tests/solc_version_incorrect_05.sol
new file mode 100644
--- /dev/null
+++ b/tests/solc_version_incorrect_05.sol
@@ -0,0 +1,7 @@
+// The version pragma below should get flagged by the detector
+pragma solidity ^0.5.5;
+pragma solidity 0.5.7;
+
+contract Contract{
+
+}