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 )