From 5e2103faebf3a3a16331ba26e657df7f2e497d97 Mon Sep 17 00:00:00 2001 From: AfonsoSantos96 Date: Thu, 18 May 2023 10:31:35 +0100 Subject: [PATCH 1/3] feat(HIS): add HIS script into makefile python scripts Signed-off-by: Afonso Santos --- his_checker.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/his_checker.py b/his_checker.py index 9f2a17d..e86059a 100755 --- a/his_checker.py +++ b/his_checker.py @@ -1,3 +1,4 @@ +<<<<<<< HEAD #!/bin/python3 # SPDX-License-Identifier: Apache-2.0 @@ -215,3 +216,7 @@ def process_v_g(files, threshold): # If there were any failures, exit with an error code if CHECK_FAIL: sys.exit(-1) +======= + +# wip +>>>>>>> 6e30066 (feat(HIS): add HIS script into makefile python scripts) From bf0fdaae245eb0347a00700c987dabd9fd1433da Mon Sep 17 00:00:00 2001 From: AfonsoSantos96 Date: Thu, 18 May 2023 10:44:47 +0100 Subject: [PATCH 2/3] feat(HIS): add HIS checker to ci makefile Signed-off-by: Afonso Santos --- his_checker.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/his_checker.py b/his_checker.py index e86059a..9f2a17d 100755 --- a/his_checker.py +++ b/his_checker.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD #!/bin/python3 # SPDX-License-Identifier: Apache-2.0 @@ -216,7 +215,3 @@ def process_v_g(files, threshold): # If there were any failures, exit with an error code if CHECK_FAIL: sys.exit(-1) -======= - -# wip ->>>>>>> 6e30066 (feat(HIS): add HIS script into makefile python scripts) From 6ee60dabf715eddc3aaec6e60a2071e56ee19dfe Mon Sep 17 00:00:00 2001 From: AfonsoSantos96 Date: Tue, 10 Oct 2023 10:19:40 +0100 Subject: [PATCH 3/3] feat(HIS): add function calls metric check to script Signed-off-by: Afonso Santos --- docker/Dockerfile | 6 ++-- his_checker.py | 88 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 9fe1a6d..1ccb26f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -38,7 +38,8 @@ RUN apt-get update && apt-get install -y \ tree \ vim \ nano \ - device-tree-compiler + device-tree-compiler \ + cflow # Install python packages RUN pip3 install \ @@ -56,7 +57,8 @@ RUN pip3 install \ pyspellchecker \ ROPgadget \ capstone \ - GitPython + GitPython \ + anytree # Install javascript packages RUN npm install -g cspell@latest diff --git a/his_checker.py b/his_checker.py index 9f2a17d..a06f05c 100755 --- a/his_checker.py +++ b/his_checker.py @@ -9,6 +9,39 @@ import sys import argparse +import os +from anytree import Node + +def traverse(node, threshold, failed_nodes=None): + """ + Helper function to traverse the tree create in the process_calls function + """ + if failed_nodes is None: + failed_nodes = [] + + # Initialize a variable to True. This will remain True if all checks pass. + is_new_node = True + + # Check each node in failed_nodes + for f_node in failed_nodes: + # If the current node's name is the same as a name in failed_nodes + if node.name == f_node.name: + # Set is_new_node to False and break the loop + is_new_node = False + break + + # If the node has more children than the threshold and is_new_node is still True + if len(node.children) > threshold and is_new_node: + # Add the node to failed_nodes + failed_nodes.append(node) + + # For each child of the current node + for child in node.children: + # Recursively traverse the child's subtree, passing the current list of nodes + traverse(child, threshold, failed_nodes) + + + return failed_nodes def process_calling(files, threshold): """ @@ -21,12 +54,61 @@ def process_calling(files, threshold): def process_calls(files, threshold): """ - Process the calls metric + Process the number of called functions. This function checks the number of functions does a + particular function calls. If the number of 'calls' in a function exceeds the defined + threshold, an error message is printed and the error count is incremented. + + Args: + files: A list of file paths to check for 'calls'. + threshold: The maximum number of permitted 'calls' in a function. + + Returns: + The number of files that exceed the number of 'calls'. """ - print(f"Processing CALLS metric with threshold [0-{threshold}] for files: {', '.join(files)}") + metric_fail = 0 + nodes = {} + root = None + + print("--------------------------------------------") + print(f"Processing CALLS metric with threshold [0-{threshold}]") + print("--------------------------------------------") + + # Process each file + for file in files: + # Run 'cflow' on the file and split the output into lines + lines = os.popen(f"cflow -l {file}").read().split('\n') + + trees = [] + for line in lines: + + if not line.strip(): + continue # Skip empty lines + + # Extract level and func/file name + lvl, descriptor = line.split('}', 1) + lvl = int(lvl.strip('{').strip()) + + # Create root node or child node based on level + if lvl == 0: + root = Node(descriptor) # Create a new root node + trees.append(root) + nodes = {0: root} # Reset nodes dictionary for the new tree + else: + parent = nodes[lvl - 1] + # Update the current node and its parent reference + nodes[lvl] = Node(descriptor, parent=parent) + + # Check the number of calls in each tree + for root in trees: + nodes_failed = traverse(root, threshold) + for node in nodes_failed: + func_name = node.name.split(')', 1)[0].strip() + ')' + print(f"At {file} has {len(node.children)} calls in function {func_name}") + metric_fail += 1 + + return metric_fail - return 0 def process_comf(files, threshold): """