summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/ThreadAllows.py
diff options
context:
space:
mode:
Diffstat (limited to 'build/clang-plugin/ThreadAllows.py')
-rw-r--r--build/clang-plugin/ThreadAllows.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/build/clang-plugin/ThreadAllows.py b/build/clang-plugin/ThreadAllows.py
new file mode 100644
index 0000000000..f3e1ee894c
--- /dev/null
+++ b/build/clang-plugin/ThreadAllows.py
@@ -0,0 +1,82 @@
+# 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 json
+import os
+import posixpath
+from os import PathLike
+
+# `typing.Literal` not available until Python 3.8;
+# `typing_extensions` not generally available here
+from typing import Iterable, Set
+
+FIRST_LINE = "// This file was generated by {}. DO NOT EDIT.".format(
+ # `posixpath` for forward slashes, for presentation purposes
+ posixpath.relpath(__file__, os.getenv("TOPSRCDIR", "/"))
+)
+
+
+def generate_allowed_items(
+ which: str, # should be: Literal["files", "names"],
+ paths: Iterable[PathLike],
+) -> str:
+ def remove_trailing_comment(s: str) -> str:
+ return s[0 : s.find("#")]
+
+ def read_items_from_path(path: PathLike) -> Set[str]:
+ out = set()
+ with open(path) as file:
+ for line in file.readlines():
+ line = remove_trailing_comment(line).strip()
+ if not line:
+ continue # comment or empty line; discard
+ out.add(line)
+ return out
+
+ allowed = set().union(*(read_items_from_path(path) for path in paths))
+ # BUG: `json.dumps` may not correctly handle use of the quote character in
+ # thread names
+ allowed_list_s = ",\n ".join(json.dumps(elem) for elem in sorted(allowed))
+
+ return f"""\
+static const char *allow_thread_{which}[] = {{
+ {allowed_list_s}
+}};"""
+
+
+def generate_allows(
+ *, allowed_names: Iterable[PathLike], allowed_files: Iterable[PathLike]
+) -> str:
+ """
+ This function reads in the specified sets of files -- ordinarily,
+ ["ThreadAllows.txt"] and ["ThreadFileAllows.txt"] -- and generates the text
+ of a header file containing two arrays with their contents, for inclusion by
+ the thread-name checker.
+
+ The checker will reject the creation of any thread via NS_NewNamedThread
+ unless either:
+ - the thread's name is a literal string which is found in the set of
+ allowed thread names; or
+ - the thread's creation occurs within a file which is found in the set of
+ unchecked files.
+
+ The latter condition exists mostly for the definition of NS_NewNamedThread,
+ but there also exist a few cases where the thread name is dynamically
+ computed (and so can't be checked).
+ """
+ output_string = (
+ FIRST_LINE
+ + "\n\n"
+ + generate_allowed_items("files", allowed_files)
+ + "\n\n"
+ + generate_allowed_items("names", allowed_names)
+ + "\n"
+ )
+ return output_string
+
+
+# Entry point used by build/clang-plugin/moz.build (q.v.).
+def generate_file(output, allowed_names, allowed_files):
+ output.write(
+ generate_allows(allowed_names=[allowed_names], allowed_files=[allowed_files])
+ )