From 82ebaa4d361b5e5539b6f1394dc5f8d1aecc7860 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 12 Jan 2021 00:45:14 +0100 Subject: [PATCH] Implement stanza parsing in .data files Parse the existing dependencies. For now, just write them back. Subsequent commits will implement the dependency processing that is the goal of this program. Signed-off-by: Gilles Peskine --- tests/scripts/set_psa_test_dependencies.py | 55 +++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/tests/scripts/set_psa_test_dependencies.py b/tests/scripts/set_psa_test_dependencies.py index 36f0eae21..96dd94bdb 100755 --- a/tests/scripts/set_psa_test_dependencies.py +++ b/tests/scripts/set_psa_test_dependencies.py @@ -19,8 +19,20 @@ # limitations under the License. import os +import re import sys +def updated_dependencies(file_name, function_name, arguments, dependencies): + """Rework the list of dependencies into PSA_WANT_xxx. + + Remove classic crypto dependencies such as MBEDTLS_RSA_C, + MBEDTLS_PKCS1_V15, etc. + + Add systematic PSA_WANT_xxx dependencies based on the called function and + its arguments, replacing existing PSA_WANT_xxx dependencies. + """ + return dependencies #TODO + def process_data_stanza(stanza, file_name, test_case_number): """Update PSA crypto dependencies in one Mbed TLS test case. @@ -29,7 +41,48 @@ def process_data_stanza(stanza, file_name, test_case_number): a new stanza with an updated dependency line, preserving everything else (description, comments, arguments, etc.). """ - #TODO: not implemented yet + if not stanza.lstrip('\n'): + # Just blank lines + return stanza + # Expect 2 or 3 non-comment lines: description, optional dependencies, + # function-and-arguments. + content_matches = list(re.finditer(r'^[\t ]*([^\t #].*)$', stanza, re.M)) + if len(content_matches) < 2: + raise Exception('Not enough content lines in paragraph {} in {}' + .format(test_case_number, file_name)) + if len(content_matches) > 3: + raise Exception('Too many content lines in paragraph {} in {}' + .format(test_case_number, file_name)) + arguments = content_matches[-1].group(0).split(':') + function_name = arguments.pop(0) + if len(content_matches) == 2: + # Insert a line for the dependencies. If it turns out that there are + # no dependencies, we'll remove that empty line below. + dependencies_location = content_matches[-1].start() + text_before = stanza[:dependencies_location] + text_after = '\n' + stanza[dependencies_location:] + old_dependencies = [] + dependencies_leader = 'depends_on:' + else: + dependencies_match = content_matches[-2] + text_before = stanza[:dependencies_match.start()] + text_after = stanza[dependencies_match.end():] + old_dependencies = dependencies_match.group(0).split(':') + dependencies_leader = old_dependencies.pop(0) + ':' + if dependencies_leader != 'depends_on:': + raise Exception('Next-to-last line does not start with "depends_on:"' + ' in paragraph {} in {}' + .format(test_case_number, file_name)) + new_dependencies = updated_dependencies(file_name, function_name, arguments, + old_dependencies) + if new_dependencies: + stanza = (text_before + + dependencies_leader + ':'.join(new_dependencies) + + text_after) + else: + # The dependencies have become empty. Remove the depends_on: line. + assert text_after[0] == '\n' + stanza = text_before + text_after[1:] return stanza def process_data_file(file_name, old_content):