Nashat Mansour

65 papers A 1B 1C 6Misc 6Journal 30Unranked 20
YearRankTypeTitle / Venue / Authors
2021 J jnl
Expert Syst. Appl.
Mahdi Dhaini, Nashat Mansour
2018 J jnl
Appl. Artif. Intell.
Ramzi A. Haraty, Nashat Mansour, Hratch Zeitunlian
2017 conf
ICSI (2)
Sarah El-Bizri, Nashat Mansour
2016 C conf
HealthCom
Fadi Louis Nammour, Konstantinos Danas, Nashat Mansour
2016 J jnl
Int. J. Softw. Eng. Knowl. Eng.
Ramzi A. Haraty, Nashat Mansour, Lama Moukahal, Iman Khalil
2016 conf
ICSI (1)
Mouses Stamboulian, Nashat Mansour
2014 conf
ICIC (3)
Nashat Mansour, Hussein Mohsen
2013 Misc conf
ICNC
Nashat Mansour, Hanaa El-Jazzar
2013 Misc conf
ICNC
Nashat Mansour, Rouba Zantout, Mirvat El-Sibai
2012 conf
EVOLVE
Nashat Mansour, Hratch Zeitunlian, Abbas Tarhini
2011 conf
BICoB
Nashat Mansour, Iman Ghalayini, Sandra Rizk, Mirvat El-Sibai
2011 J jnl
Int. Arab J. Inf. Technol.
Mohammad Salameh, Rached Zantout, Nashat Mansour
2011 J jnl
Int. J. Appl. Metaheuristic Comput.
Nashat Mansour, Ghia Sleiman Haidar
2011 Misc conf
ICNC
Amer E. Mouawad, Nashat Mansour
2011 J jnl
Appl. Intell.
Nashat Mansour, Vatche Isahakian, Iman Ghalayini
2011 J jnl
J. Softw. Maintenance Res. Pract.
Nashat Mansour, Husam Takkoush, Ali Nehme
2010 Misc conf
ICNC
Nashat Mansour, Fatima Kanj, Hassan Khachfe
2010 J jnl
Clust. Comput.
Nashat Mansour, Maya I. Chehab, Ahmad Faour
2010 Misc conf
ICNC
Nashat Mansour, Ghia Sleiman Haidar
2010 J jnl
Int. J. Inf. Technol. Web Eng.
Nashat Mansour, Nabil Baba
2009 C conf
AICCSA
Fatima Kanj, Nashat Mansour, Hassan Khachfe, Faisal N. Abu-Khzam
2009 J jnl
Adv. Softw. Eng.
Nashat Mansour, Wael Statieh
2009 J jnl
Int. J. Bioinform. Res. Appl.
Nashat Mansour, Christine Kehyayan, Hassan Khachfe
2008 J jnl
Inf. Process. Manag.
Nashat Mansour, Ramzi A. Haraty, Walid Daher, Manal Houri
2008 conf
ISPAN
Maya Shehab, Nashat Mansour, Ahmad Faour
2006 C conf
AICCSA
Hamed Siefoddini, Khaled El-Fakih, Jalal Kawash, Nashat Mansour
2006 C conf
AICCSA
Abbas Tarhini, Hacène Fouchal, Nashat Mansour
2006 J jnl
J. Comput. Methods Sci. Eng.
Nashat Mansour, Hani Salem
2006 J jnl
Inf. Softw. Technol.
Nashat Mansour, Manal Houri
2006 J jnl
Adv. Eng. Softw.
Ahmad Faour, Nashat Mansour
2005 conf
IICS
Abbas Tarhini, Hacène Fouchal, Nashat Mansour
2005 C conf
AICCSA
Reda Siblini, Nashat Mansour
2005 J jnl
Int. J. Comput. Their Appl.
Nashat Mansour, Reda Siblini, Abbas Tarhini
2004 J jnl
Comput. Oper. Res.
Nashat Mansour, Hiba Tabbara, Tarek Dana
2004 J jnl
Softw. Qual. J.
Nashat Mansour, Miran Salame
2004 ch.
Advanced Topics in Database Research, Vol. 3
Ramzi A. Haraty, Nashat Mansour, Bassel Daou
2003 conf
Applied Informatics
Ramzi A. Haraty, Nashat Mansour, Walid Daher
2003 conf
ISCIS
Joe Abboud Syriani, Nashat Mansour
2003 conf
ISCIS
Rabih Zeineddine, Nashat Mansour
2002 J jnl
Inf. Softw. Technol.
Nashat Mansour, Rami Bahsoon
2002 J jnl
J. Database Manag.
Ramzi A. Haraty, Nashat Mansour, Bassel Daou
2001 J jnl
J. Syst. Softw.
Nashat Mansour, Rami Bahsoon, Ghinwa Baradhi
2001 C conf
AICCSA
Rami Bahsoon, Nashat Mansour
2001 Misc conf
SAC
Ramzi A. Haraty, Nashat Mansour, Bassel Daou
2001 J jnl
Int. J. Comput. Their Appl.
Ramzi A. Haraty, Nashat Mansour, Sana Abiad
2000 conf
ICECS
Hiba Tabbara, Tarek Dana, Nashat Mansour
2000 conf
SAC (2)
Sana Abiad, Ramzi A. Haraty, Nashat Mansour
2000 conf
ICECS
Hassan Diab, Emad Abdennour, Nashat Mansour
1999 J jnl
Eur. J. Oper. Res.
Fred F. Easton, Nashat Mansour
1999 J jnl
J. Softw. Maintenance Res. Pract.
Nashat Mansour, Khaled El-Fakih
1997 conf
Australian Software Engineering Conference
Ghinwa Baradhi, Nashat Mansour
1997 J jnl
Concurr. Pract. Exp.
Nikos Chrisochoides, Nashat Mansour, Geoffrey C. Fox
1997 B conf
COMPSAC
Nashat Mansour, Khaled El-Fakih
1997 J jnl
Parallel Algorithms Appl.
Nashat Mansour, Jalal Kawash, Hassan B. Diab
1995 conf
Parallel and Distributed Computing and Systems
Jalal Kawash, Nashat Mansour, Hassan B. Diab
1995 conf
Parallel and Distributed Computing and Systems
Hassan B. Diab, Hassan S. Tabbara, Nashat Mansour
1994 J jnl
Concurr. Pract. Exp.
Nashat Mansour, Geoffrey C. Fox
1994 J jnl
Sci. Program.
Ravi Ponnusamy, Nashat Mansour, Alok N. Choudhary, Geoffrey Charles Fox
1994 J jnl
J. Supercomput.
Nashat Mansour, Geoffrey Charles Fox
1993 conf
ICGA
Fred F. Easton, Nashat Mansour
1993 A conf
International Conference on Supercomputing
Nashat Mansour, Ravi Ponnusamy, Alok N. Choudhary, Geoffrey C. Fox
1993 conf
IPPS
Ravi Ponnusamy, Nashat Mansour, Alok N. Choudhary, Geoffrey C. Fox
1992 J jnl
Concurr. Pract. Exp.
Nashat Mansour, Geoffrey C. Fox
1992 conf
CONPAR
Nashat Mansour, Geoffrey C. Fox
1991 conf
ICGA
Nashat Mansour, Geoffrey C. Fox
redb/extractors/decompiler/bninja/analysis/cfg-old.py
← Index redb/extractors/decompiler/bninja/analysis/cfg-old.py python
from collections import deque
from enum import Enum

from binaryninja.enums import (
    BranchType,
    InstructionTextTokenType,
)

# Support both package and standalone imports
try:
    from ..utils.hashes import calculate_md5, calculate_sha256
except ImportError:
    # Fallback to absolute imports (for multiprocessing spawned processes)
    from redb.extractors.decompiler.bninja.utils.hashes import calculate_md5, calculate_sha256


class CFGAnalysis:
    def __init__(self, function):
        self.function = function

    def determine_block_type(self, block) -> str:
        """Determine the type of a basic block."""
        # Check if it's a thunk function (usually just a jump or call)
        if len(block.disassembly_text) <= 2 and any(
            "jmp" in line.tokens[0].text.lower() for line in block.disassembly_text
        ):
            return "THUNK"

        # Check if it contains only data (no valid instructions)
        if all(not line.tokens for line in block.disassembly_text):
            return "DATA"

        # Default to code
        return "CODE"

    def extract_cyclomatic_complexity(self):
        """
        Cyclomatic complexity (McCabe’s metric) measures the number of linearly independent paths
        through a function’s control flow graph (CFG).
        The standard formula is:

            M = E - N + 2

        where:
            - E = number of edges in the CFG
            - N = number of nodes (basic blocks)
            - 2 accounts for the entry and exit nodes of a single connected graph
        """
        if self.function is None:
            return 0

        # number of basic blocks
        num_blocks = len(self.function.basic_blocks)
        # number of edges in the graph
        num_edges = sum(
            len(basic_block.outgoing_edges)
            for basic_block in self.function.basic_blocks
        )
        return num_edges - num_blocks + 2

    def extract_function_cfg(self):
        """Extract information about a function CFG and return it as a dictionary."""

        function = self.function
        function_data = {
            "function_address": self.function.start,
            "blocks": [],
            "measures": {
                "cyclomatic_complexity": self.extract_cyclomatic_complexity(),
            },
        }

        if self.function is None:
            return function_data

        # Get the map of the depth associated to every block
        depths = self.get_map_depth()

        # Get the map of the positions associated to every block
        id_maps = self.get_block_id_map()

        # Extract block data with graph structure information
        for block in function.basic_blocks:
            # dominators per every block translated
            dominators = sorted(self.extract_dominators(block, id_maps))

            # post dominators
            post_dominators = sorted(self.extract_post_dominators(block, id_maps))

            # Build block instructions string
            block_instructions = "\n".join(str(line) for line in block.disassembly_text)

            # Determine block type
            block_type = self.determine_block_type(block)

            # Extract successors directly from basic block
            successor_blocks = [edge.target.start for edge in block.outgoing_edges]
            # We ensure a canonical order and we sort the edges
            successor_blocks.sort()

            # Extract predecessors directly from basic block
            predecessor_blocks = [edge.source.start for edge in block.incoming_edges]
            # We ensure a canonical order and we sort the edges
            predecessor_blocks.sort()

            # Determine branch type from outgoing edges
            branch_type = self.determine_branch_type(block)

            instructions_count = len(block.disassembly_text)

            # Create block record
            block_json = {
                "function_address": self.function.start,
                "block_start_address": block.start,
                "block_end_address": block.end,
                "block_size": block.end - block.start,
                "instructions_count": instructions_count,
                "block_instructions_hash": calculate_sha256(block_instructions),
                "predecessor_blocks": predecessor_blocks,
                "successor_blocks": successor_blocks,
                "depth": depths[block.start],
                "position": id_maps[block.start],
                "branch_type": branch_type,
                "block_type": block_type,
                "flags": self.extract_block_flags(block),
                "dominators": dominators,
                "post_dominators": post_dominators,
            }
            function_data["blocks"].append(block_json)

        return function_data

    def extract_dominators(self, bb, id_maps):
        """Extract the dominators normalized"""
        dom_idx = [id_maps[d.start] for d in bb.dominators]
        return dom_idx

    def extract_post_dominators(self, bb, id_maps):
        """Extract the post-dominators normalized"""
        post_dom_idx = [id_maps[d.start] for d in bb.post_dominators]
        return post_dom_idx

    def determine_branch_type(self, block):
        """
        Determine the type of branch at the end of a basic block.
        This combines edge type information with instruction analysis.
        """
        # If no outgoing edges, it might be a return or terminal block
        if not block.outgoing_edges:
            # Check if the last instruction is a return
            for line in reversed(list(block.disassembly_text)):
                if line.tokens and any(
                    token.text.lower() in ["ret", "retn"] for token in line.tokens
                ):
                    return "RETURN"
            return "UNKNOWN"

        # Collect branch types from all outgoing edges
        branch_types = []
        for edge in block.outgoing_edges:
            edge_type = edge.type
            # Map edge type to our branch type enum
            if isinstance(edge_type, str):
                if edge_type == "IndirectCall":
                    branch_types.append("CALL")
                else:
                    branch_types.append("UNKNOWN")
            else:
                # Use our mapping for integer/enum values
                type_mapping = {
                    BranchType.UnconditionalBranch: "DIRECT",
                    BranchType.FalseBranch: "CONDITIONAL",
                    BranchType.TrueBranch: "CONDITIONAL",
                    BranchType.CallDestination: "CALL",
                    BranchType.FunctionReturn: "RETURN",
                    BranchType.SystemCall: "CALL",
                    BranchType.IndirectBranch: "INDIRECT",
                    BranchType.ExceptionBranch: "UNKNOWN",
                    BranchType.UnresolvedBranch: "UNKNOWN",
                    BranchType.UserDefinedBranch: "UNKNOWN",
                }
                branch_types.append(type_mapping.get(edge_type, "UNKNOWN"))

        # Determine overall branch type (prioritize CALL > RETURN > CONDITIONAL > DIRECT)
        if "CALL" in branch_types:
            return "CALL"
        elif "RETURN" in branch_types:
            return "RETURN"
        elif "CONDITIONAL" in branch_types:
            return "CONDITIONAL"
        elif "DIRECT" in branch_types:
            return "DIRECT"
        elif len(block.outgoing_edges) == 1:
            return "FALLTHROUGH"

        # If edge analysis was inconclusive, fall back to instruction analysis
        last_instr = None
        for line in reversed(list(block.disassembly_text)):
            if line.tokens:
                last_instr = line
                break

        if last_instr:
            mnemonic = None
            for token in last_instr.tokens:
                if token.type == InstructionTextTokenType.InstructionToken:
                    mnemonic = token.text.lower()
                    break

            if mnemonic:
                if mnemonic == "call":
                    return "CALL"
                elif mnemonic == "jmp":
                    return "DIRECT"
                elif mnemonic.startswith("j") and mnemonic != "jmp":
                    return "CONDITIONAL"
                elif mnemonic in ["ret", "retn"]:
                    return "RETURN"

        return "UNKNOWN"

    def get_map_depth(self):
        """
        Run a BFS on the basic blocks of the function to assign a depth to every block
        """

        depths = {}
        entry = self.function.get_basic_block_at(self.function.start)

        ### Simple BFS
        q = deque()
        q.append(entry)
        depths[entry.start] = 0

        while q:
            b = q.popleft()
            b_depth = depths[b.start]
            for edge in b.outgoing_edges:
                tgt = edge.target

                if tgt is None:
                    continue

                if tgt.start not in depths:
                    depths[tgt.start] = b_depth + 1
                    q.append(tgt)

        return depths

    def get_block_id_map(self):
        """
        Assign a unique, sequential ID to each basic block of the function using a BFS starting from the entry block.
        """

        id_map = {}
        entry = self.function.get_basic_block_at(self.function.start)

        q = deque()
        q.append(entry)

        current_id = 0
        id_map[entry.start] = current_id

        while q:
            b = q.popleft()
            for edge in b.outgoing_edges:
                tgt = edge.target

                if tgt is None:
                    continue

                if tgt.start not in id_map:
                    current_id += 1
                    id_map[tgt.start] = current_id
                    q.append(tgt)

        return id_map

    def extract_block_flags(self, block):
        """
        Get the flags for every basic block. Currently, we implemented these heuristics:
            - if a basic block is the entry node for a function
            - if a basic block is the exit block for a function
            - if a basic block is part of a natural loop
        """
        flags = []

        if block.start == self.function.start:
            flags.append(BlockFlags.EntryBlock.value)

        if any(edge.type == BranchType.FunctionReturn for edge in block.outgoing_edges):
            flags.append(BlockFlags.ExitBlock.value)

        # if this block is in its dominance frontier, then it's part of a natural loop
        if block in block.dominance_frontier:
            flags.append(BlockFlags.LoopBlock.value)

        return flags


class BlockFlags(Enum):
    # generally, the basic block identifying the entry point of the function
    EntryBlock = "EntryBlock"
    # any basic blocks that makes the control flow exiting from the current function
    ExitBlock = "ExitBlock"
    # any block is in a natural loop if it is in its own dominance frontier
    LoopBlock = "LoopBlock"


class BlockType(Enum):
    THUNK = "THUNK"
    DATA = "DATA"
    PADDING = "PADDING"
    CODE = "CODE"