From 0d41abbde61e40ab00ac512f16340262640ba6fb Mon Sep 17 00:00:00 2001 From: Mateusz Starzyk Date: Wed, 12 May 2021 14:48:40 +0200 Subject: [PATCH] Introduce scripts automating wrapping structs members with MBEDTLS_PRIVATE. Usage: run setup_and_run_MBEDTLS_PRIVATE.sh Signed-off-by: Mateusz Starzyk --- apply_MBEDTLS_PRIVATE.py | 84 ++++++++++++++++++++++++++++++++ setup_and_run_MBEDTLS_PRIVATE.sh | 10 ++++ 2 files changed, 94 insertions(+) create mode 100644 apply_MBEDTLS_PRIVATE.py create mode 100755 setup_and_run_MBEDTLS_PRIVATE.sh diff --git a/apply_MBEDTLS_PRIVATE.py b/apply_MBEDTLS_PRIVATE.py new file mode 100644 index 0000000000..4160287f22 --- /dev/null +++ b/apply_MBEDTLS_PRIVATE.py @@ -0,0 +1,84 @@ +import re +import fileinput +import glob +import pprint +import os +import xml.etree.ElementTree as ET + + +files_to_visit = {} + +struct_files = glob.glob("apidoc/xml/structmbedtls*.xml") + glob.glob("apidoc/xml/structpsa*.xml") + +for struct_file in struct_files: + struct_file_tree = ET.parse(struct_file) + all_struct_members_definitions = struct_file_tree.getroot().findall(".//memberdef[@kind='variable']") + + # Create dictionary with following structre + # "filepath" : { "variable_name1": (1, 2, 40, 61), # line numbers + # "variable_name2": (60, 64), + # } + for struct_member_def in all_struct_members_definitions: + # find file path for this variable + member_id = struct_member_def.attrib["id"] + location = struct_member_def.find("location") + file_path = location.attrib["file"] + variable_name = struct_member_def.find("name").text + # if path not yet in dictionary, create empty record to initialize + if file_path not in files_to_visit: + files_to_visit[file_path] = {} + # if variable is not yet in this file's dictionary, create empty set to initialize + if variable_name not in files_to_visit[file_path]: + files_to_visit[file_path][variable_name] = set() + + # add variable definition + files_to_visit[file_path][variable_name].add(int(location.attrib["line"])) + + # check where the variable was referenced + references = struct_member_def.findall("referencedby") + for reference in references: + refid = reference.attrib["refid"] + # assuming that compound name is related to header's xml file + header_file = "apidoc/xml/" + reference.attrib["compoundref"] + ".xml" + header_file_tree = ET.parse(header_file) + # check if this reference is created by static inline function + static_inline_function_definition = header_file_tree.getroot().find(f".//memberdef[@id='{refid}'][@kind='function'][@static='yes'][@inline='yes']") + if static_inline_function_definition: + static_inline_function_file_path = static_inline_function_definition.find("location").attrib["file"] + # if path not yet in dictionary, create empty record to initialize. + # This could happen if reference is inside header file which was not yet processed in search for variable definitions + if static_inline_function_file_path not in files_to_visit: + files_to_visit[static_inline_function_file_path] = {} + # if variable is not yet in this file's dictionary, create empty set to initialize + if variable_name not in files_to_visit[static_inline_function_file_path]: + files_to_visit[static_inline_function_file_path][variable_name] = set() + # function block scope + function_lines_from = int(reference.attrib["startline"]) + function_lines_to = int(reference.attrib["endline"]) + # find codelines referencing struct's variable + codelines_xml = header_file_tree.getroot().findall(f".//ref[@refid='{member_id}']/../..") + # filter by function's scope + codelines = [int(line.attrib["lineno"]) for line in codelines_xml if int(line.attrib["lineno"]) >= function_lines_from and int(line.attrib["lineno"]) <= function_lines_to] + # add variable reference + files_to_visit[static_inline_function_file_path][variable_name].update(codelines) + +pp = pprint.PrettyPrinter(indent=4) +pp.pprint(files_to_visit) + +for file_path, variables in files_to_visit.items(): + with fileinput.FileInput(file_path, inplace=True) as file: + output_line_number = 1 + re_include_guard = re.compile(r"^#define.*{name}$".format(name=os.path.basename(file_path).replace('.','_').upper())) + for line in file: + insert_allow_private_include = False + if re_include_guard.match(line): + insert_allow_private_include = True + for variable, var_lines in variables.items(): + for var_line in var_lines: + if output_line_number == var_line: + line = re.sub(r"(^.*?\W+)({var})(\W+.*$)".format(var=variable), r"\1MBEDTLS_PRIVATE(\2)\3", line) + output_line_number += 1 + print(line, end='') # fileinput redirects stdout to the target file + if insert_allow_private_include: + insert_allow_private_include = False + print("#include \"mbedtls/private_access.h\"") diff --git a/setup_and_run_MBEDTLS_PRIVATE.sh b/setup_and_run_MBEDTLS_PRIVATE.sh new file mode 100755 index 0000000000..9a0e599790 --- /dev/null +++ b/setup_and_run_MBEDTLS_PRIVATE.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +make clean +sed -i 's/GENERATE_XML = NO/GENERATE_XML = YES/g' doxygen/mbedtls.doxyfile +scripts/config.py full +cd doxygen +doxygen mbedtls.doxyfile +cd .. +python3 apply_MBEDTLS_PRIVATE.py +git checkout include/mbedtls/config.h doxygen/mbedtls.doxyfile