style-checker: Add UAF to the list of security words to warn about.
[WebKit-https.git] / Tools / Scripts / webkitpy / style / checkers / changelog.py
index a096d3f..399dacf 100644 (file)
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-#
 # Copyright (C) 2011 Patrick Gansterer <paroga@paroga.com>
 #
 # Redistribution and use in source and binary forms, with or without
@@ -25,9 +23,9 @@
 
 """Checks WebKit style for ChangeLog files."""
 
-import re
-from common import TabChecker
+from sys import maxsize
 from webkitpy.common.checkout.changelog import parse_bug_id_from_changelog
+from webkitpy.style.checkers.common import TabChecker, match, search, searchIgnorecase
 
 
 class ChangeLogChecker(object):
@@ -47,9 +45,9 @@ class ChangeLogChecker(object):
         for line in entry_lines:
             if parse_bug_id_from_changelog(line):
                 break
-            if re.search("Unreviewed", line, re.IGNORECASE):
+            if searchIgnorecase("Unreviewed", line):
                 break
-            if re.search("build", line, re.IGNORECASE) and re.search("fix", line, re.IGNORECASE):
+            if searchIgnorecase("build", line) and searchIgnorecase("fix", line):
                 break
         else:
             self.handle_style_error(first_line_checked,
@@ -60,23 +58,25 @@ class ChangeLogChecker(object):
         for line in entry_lines:
             line_no = line_no + 1
             # filter file change descriptions
-            if not re.match('\s*\*\s', line):
+            if not match('\s*\*\s', line):
                 continue
-            if re.search(':\s*$', line) or re.search(':\s', line):
+            if search(':\s*$', line) or search(':\s', line):
                 continue
             self.handle_style_error(line_no,
                                     "changelog/filechangedescriptionwhitespace", 5,
                                     "Need whitespace between colon and description")
 
-        # check for a lingering "No new tests. (OOPS!)" left over from prepare-changeLog.
+        # check for a lingering "No new tests (OOPS!)." left over from prepare-changeLog.
         line_no = first_line_checked - 1
         for line in entry_lines:
             line_no = line_no + 1
-            if re.match('\s*No new tests. \(OOPS!\)$', line):
+            if match('\s*No new tests \(OOPS!\)\.$', line):
                 self.handle_style_error(line_no,
                                         "changelog/nonewtests", 5,
                                         "You should remove the 'No new tests' and either add and list tests, or explain why no new tests were possible.")
 
+        self.check_for_unwanted_security_phrases(first_line_checked, entry_lines)
+
     def check(self, lines):
         self._tab_checker.check(lines)
         first_line_checked = 0
@@ -94,3 +94,36 @@ class ChangeLogChecker(object):
             entry_lines.append(line)
 
         self.check_entry(first_line_checked, entry_lines)
+
+    def contains_phrase_in_first_line_or_across_two_lines(self, phrase, line1, line2):
+        return searchIgnorecase(phrase, line1) or ((not searchIgnorecase(phrase, line2)) and searchIgnorecase(phrase, line1 + " " + line2))
+
+    def check_for_unwanted_security_phrases(self, first_line_checked, lines):
+        unwanted_security_phrases = [
+            "arbitrary code execution", "buffer overflow", "buffer overrun",
+            "buffer underrun", "dangling pointer", "double free", "fuzzer", "fuzzing", "fuzz test",
+            "invalid cast", "jsfunfuzz", "malicious", "memory corruption", "security bug",
+            "security flaw", "use after free", "use-after-free", "UAF", "UXSS",
+            "WTFCrashWithSecurityImplication",
+            "spoof",  # Captures spoof, spoofed, spoofing
+            "vulnerab",  # Captures vulnerable, vulnerability, vulnerabilities
+        ]
+
+        lines_with_single_spaces = []
+        for line in lines:
+            lines_with_single_spaces.append(" ".join(line.split()))
+
+        found_unwanted_security_phrases = []
+        last_index = len(lines_with_single_spaces) - 1
+        first_line_number_with_unwanted_phrase = maxsize
+        for unwanted_phrase in unwanted_security_phrases:
+            for line_index, line in enumerate(lines_with_single_spaces):
+                next_line = "" if line_index >= last_index else lines_with_single_spaces[line_index + 1]
+                if self.contains_phrase_in_first_line_or_across_two_lines(unwanted_phrase, line, next_line):
+                    found_unwanted_security_phrases.append(unwanted_phrase)
+                    first_line_number_with_unwanted_phrase = min(first_line_number_with_unwanted_phrase, first_line_checked + line_index)
+
+        if len(found_unwanted_security_phrases) > 0:
+            self.handle_style_error(first_line_number_with_unwanted_phrase,
+                                    "changelog/unwantedsecurityterms", 3,
+                                    "Please consider whether the use of security-sensitive phrasing could help someone exploit WebKit: {}".format(", ".join(found_unwanted_security_phrases)))