diff options
Diffstat (limited to 'tools/lint/trojan-source')
-rw-r--r-- | tools/lint/trojan-source/__init__.py | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/lint/trojan-source/__init__.py b/tools/lint/trojan-source/__init__.py new file mode 100644 index 0000000000..a20c10203d --- /dev/null +++ b/tools/lint/trojan-source/__init__.py @@ -0,0 +1,67 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +import sys +import unicodedata + +from mozlint import result +from mozlint.pathutils import expand_exclusions + +# Code inspired by Red Hat +# https://github.com/siddhesh/find-unicode-control/ +# published under the 'BSD 3-Clause' license +# https://access.redhat.com/security/vulnerabilities/RHSB-2021-007 + +results = [] + +disallowed = set( + chr(c) for c in range(sys.maxunicode) if unicodedata.category(chr(c)) == "Cf" +) + + +def getfiletext(config, filename): + # Make a text string from a file, attempting to decode from latin1 if necessary. + # Other non-utf-8 locales are not supported at the moment. + with open(filename, "rb") as infile: + try: + return infile.read().decode("utf-8") + except Exception as e: + res = { + "path": filename, + "message": "Could not open file as utf-8 - maybe an encoding error: %s" + % e, + "level": "error", + } + results.append(result.from_config(config, **res)) + return None + + return None + + +def analyze_text(filename, text, disallowed): + line = 0 + for t in text.splitlines(): + line = line + 1 + subset = [c for c in t if chr(ord(c)) in disallowed] + if subset: + return (subset, line) + + return ("", 0) + + +def lint(paths, config, **lintargs): + files = list(expand_exclusions(paths, config, lintargs["root"])) + for f in files: + text = getfiletext(config, f) + if text: + (subset, line) = analyze_text(f, text, disallowed) + if subset: + res = { + "path": f, + "lineno": line, + "message": "disallowed characters: %s" % subset, + "level": "error", + } + results.append(result.from_config(config, **res)) + + return {"results": results, "fixed": 0} |