tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ThreadAllows.py (2764B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 # You can obtain one at http://mozilla.org/MPL/2.0/.
      4 import json
      5 import os
      6 import posixpath
      7 from collections.abc import Iterable
      8 from os import PathLike
      9 
     10 FIRST_LINE = "// This file was generated by {}. DO NOT EDIT.".format(
     11    # `posixpath` for forward slashes, for presentation purposes
     12    posixpath.relpath(__file__, os.getenv("TOPSRCDIR", "/"))
     13 )
     14 
     15 
     16 def generate_allowed_items(
     17    which: str,  # should be: Literal["files", "names"],
     18    paths: Iterable[PathLike],
     19 ) -> str:
     20    def remove_trailing_comment(s: str) -> str:
     21        return s[0 : s.find("#")]
     22 
     23    def read_items_from_path(path: PathLike) -> set[str]:
     24        out = set()
     25        with open(path) as file:
     26            for line in file.readlines():
     27                line = remove_trailing_comment(line).strip()
     28                if not line:
     29                    continue  # comment or empty line; discard
     30                out.add(line)
     31        return out
     32 
     33    allowed = set().union(*(read_items_from_path(path) for path in paths))
     34    # BUG: `json.dumps` may not correctly handle use of the quote character in
     35    #   thread names
     36    allowed_list_s = ",\n  ".join(json.dumps(elem) for elem in sorted(allowed))
     37 
     38    return f"""\
     39 static const char *allow_thread_{which}[] = {{
     40  {allowed_list_s}
     41 }};"""
     42 
     43 
     44 def generate_allows(
     45    *, allowed_names: Iterable[PathLike], allowed_files: Iterable[PathLike]
     46 ) -> str:
     47    """
     48    This function reads in the specified sets of files -- ordinarily,
     49    ["ThreadAllows.txt"] and ["ThreadFileAllows.txt"] -- and generates the text
     50    of a header file containing two arrays with their contents, for inclusion by
     51    the thread-name checker.
     52 
     53    The checker will reject the creation of any thread via NS_NewNamedThread
     54    unless either:
     55      - the thread's name is a literal string which is found in the set of
     56        allowed thread names; or
     57      - the thread's creation occurs within a file which is found in the set of
     58        unchecked files.
     59 
     60    The latter condition exists mostly for the definition of NS_NewNamedThread,
     61    but there also exist a few cases where the thread name is dynamically
     62    computed (and so can't be checked).
     63    """
     64    output_string = (
     65        FIRST_LINE
     66        + "\n\n"
     67        + generate_allowed_items("files", allowed_files)
     68        + "\n\n"
     69        + generate_allowed_items("names", allowed_names)
     70        + "\n"
     71    )
     72    return output_string
     73 
     74 
     75 # Entry point used by build/clang-plugin/moz.build (q.v.).
     76 def generate_file(output, allowed_names, allowed_files):
     77    output.write(
     78        generate_allows(allowed_names=[allowed_names], allowed_files=[allowed_files])
     79    )