Mahmoud Mostapha

24 papers B 7Journal 5Unranked 11
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Darshan Thaker, Mahmoud Mostapha, Radu Miron, Shihan Qiu, Mariappan S. Nadar
2025 conf
ISBI
Saikat Roy, Mahmoud Mostapha, Radu Miron, Matt Holbrook, Mariappan S. Nadar
2025 J jnl
CoRR
Saikat Roy, Mahmoud Mostapha, Radu Miron, Matt Holbrook, Mariappan S. Nadar
2025 conf
MICCAI (13)
Shihan Qiu, Radu Miron, Yahang Li, Cornelius Eichner, Thorsten Feiweier, Nirmal Janardhanan, Bryan Clifford, Omar Darwish, Mahmoud Mostapha, Mariappan S. Nadar
2021 J jnl
IEEE Trans. Medical Imaging
Matthew J. Muckley, Bruno Riemenschneider, Alireza Radmanesh, Sunwoo Kim, Geunu Jeong, Jingyu Ko, Yohan Jun, Hyungseob Shin, Dosik Hwang, Mahmoud Mostapha, Simon Arberet, Dominik Nickel, Zaccharie Ramzi, Philippe Ciuciu, Jean-Luc Starck, Jonas Teuwen, Dimitrios Karkalousos, Chaoping Zhang, Anuroop Sriram, Zhengnan Huang, Nafissa Yakubova, Yvonne W. Lui, Florian Knoll
2020 conf
Biomedical Applications in Molecular, Structural, and Functional Imaging
Arthur Le Maout, Han Bit Yoon, Sun Hyung Kim, Mahmoud Mostapha, Mark D. Shen, Juan-Carlos Prieto, Martin Styner
2020 conf
ISBI
Mahmoud Mostapha, Boris Mailhé, Xiao Chen, Pascal Ceccaldi, Youngjin Yoo, Mariappan S. Nadar
2020
Mahmoud Mostapha
2020 J jnl
CoRR
Matthew J. Muckley, Bruno Riemenschneider, Alireza Radmanesh, Sunwoo Kim, Geunu Jeong, Jingyu Ko, Yohan Jun, Hyungseob Shin, Dosik Hwang, Mahmoud Mostapha, Simon Arberet, Dominik Nickel, Zaccharie Ramzi, Philippe Ciuciu, Jean-Luc Starck, Jonas Teuwen, Dimitrios Karkalousos, Chaoping Zhang, Anuroop Sriram, Zhengnan Huang, Nafissa Yakubova, Yvonne W. Lui, Florian Knoll
2019 conf
Biomedical Applications in Molecular, Structural, and Functional Imaging
Zhengyang Fang, Mahmoud Mostapha, Juan Prieto, Martin Styner
2019 B conf
Image Processing
James Fishbaugh, Beatriz Paniagua, Mahmoud Mostapha, Martin Styner, Veronica Murphy, John H. Gilmore, Guido Gerig
2019 conf
MICCAI (3)
Mahmoud Mostapha, Juan Prieto, Veronica Murphy, Jessica B. Girault, Mark Foster, Ashley Rumple, Joseph Blocher, Weili Lin, Jed T. Elison, John H. Gilmore, Steven M. Pizer, Martin Styner
2018 B conf
Image Processing
Mahmoud Mostapha, Mark D. Shen, Sun Hyung Kim, Meghan R. Swanson, D. Louis Collins, Vladimir S. Fonov, Guido Gerig, Joseph Piven, Martin A. Styner
2018 conf
ISBI
Mahmoud Mostapha, Sun Hyung Kim, Guorong Wu, Leo Zsembik, Stephen M. Pizer, Martin Styner
2018 conf
ShapeMI@MICCAI
Jared Vicory, Laura Pascal, Pablo Hernandez, James Fishbaugh, Juan-Carlos Prieto, Mahmoud Mostapha, Chao Huang, Hina Shah, Jun-Pyo Hong, Zhiyuan Liu, Loic Michoud, Jean-Christophe Fillion-Robin, Guido Gerig, Hongtu Zhu, Stephen M. Pizer, Martin Styner, Beatriz Paniagua
2017 B conf
Image Processing
Mahmoud Mostapha, Jared Vicory, Martin Styner, Stephen M. Pizer
2016 J jnl
IEEE J. Biomed. Health Informatics
Amir Alansary, Marwa Ismail, Ahmed Soliman, Fahmi Khalifa, Matthew Nitzken, Ahmed Elnakib, Mahmoud Mostapha, Austin Black, Katie Stinebruner, Manuel F. Casanova, Jacek M. Zurada, Ayman El-Baz
2016 conf
ISBI
Fahmi Khalifa, Ahmed Soliman, Ali E. Takieldeen, Mohamed Shehata, Mahmoud Mostapha, Ahmed Shaffie, Rosemary Ouseph, Adel Elmaghraby, Ayman El-Baz
2015 B conf
ICIP
Mahmoud Mostapha, Manuel F. Casanova, Ayman El-Baz
2015 B conf
ICIP
Marwa Ismail, Mahmoud Mostapha, Ahmed Soliman, Matthew Nitzken, Fahmi Khalifa, Ahmed Elnakib, Georgy L. Gimel'farb, Manuel Casanova, Ayman El-Baz
2015 conf
MICCAI (2)
Mahmoud Mostapha, Manuel Casanova, Georgy L. Gimel'farb, Ayman El-Baz
2014 B conf
ICIP
Mahmoud Mostapha, Ahmed Soliman, Fahmi Khalifa, Ahmed Elnakib, Amir Alansary, Matthew Nitzken, Manuel F. Casanova, Ayman El-Baz
2014 B conf
ICIP
Amir Alansary, Ahmed Soliman, Matthew Nitzken, Fahmi Khalifa, Ahmed Elnakib, Mahmoud Mostapha, Manuel F. Casanova, Ayman El-Baz
2014 conf
ISBI
Mahmoud Mostapha, Amir Alansary, Ahmed Soliman, Fahmi Khalifa, Matthew Nitzken, Rasha Khodeir, Manuel F. Casanova, Ayman El-Baz
redb/extractors/decompiler/apk/smali_parser.py
← Index redb/extractors/decompiler/apk/smali_parser.py python
"""Smali file parser — extracts individual method bodies from apktool output.

Parses .smali files produced by apktool and extracts per-method bodies,
instruction counts, and register counts.
"""

import os
import re
from dataclasses import dataclass, field
from typing import Dict, List, Optional


@dataclass
class SmaliMethod:
    """Parsed smali method data."""
    class_name: str
    method_name: str
    method_signature: str
    body: str
    instruction_count: int = 0
    register_count: int = 0
    access_flags: List[str] = field(default_factory=list)


# Directives start with '.' — these are metadata, not instructions
_DIRECTIVE_RE = re.compile(r"^\s*\.")
# Labels start with ':'
_LABEL_RE = re.compile(r"^\s*:")
# Blank or comment lines
_BLANK_OR_COMMENT_RE = re.compile(r"^\s*(#.*)?$")
# Method declaration
_METHOD_START_RE = re.compile(
    r"^\.method\s+(.*?)\s+(\S+)\(([^)]*)\)(\S+)\s*$"
)
_METHOD_START_SIMPLE_RE = re.compile(
    r"^\.method\s+(.*)"
)
# .registers or .locals directive
_REGISTERS_RE = re.compile(r"^\s*\.registers\s+(\d+)")
_LOCALS_RE = re.compile(r"^\s*\.locals\s+(\d+)")
# .line directive
_LINE_RE = re.compile(r"^\s*\.line\s+\d+")


class SmaliParser:
    """Parser for apktool smali output files."""

    @staticmethod
    def parse_smali_file(filepath: str) -> List[SmaliMethod]:
        """Parse a single .smali file and return list of methods.

        Each .smali file contains one class with all its methods.
        """
        with open(filepath, "r", encoding="utf-8", errors="replace") as f:
            content = f.read()

        return SmaliParser._parse_smali_content(content, filepath)

    @staticmethod
    def _parse_smali_content(content: str, source: str = "") -> List[SmaliMethod]:
        """Parse smali text content and extract methods."""
        lines = content.split("\n")
        methods = []

        # Extract class name from .class directive
        class_name = ""
        for line in lines:
            if line.startswith(".class "):
                parts = line.split()
                class_name = parts[-1]  # Last token is the class descriptor
                break

        in_method = False
        method_lines = []
        method_header = ""
        access_flags = []
        skip_method = False

        for line in lines:
            if line.startswith(".method "):
                in_method = True
                method_lines = []
                method_header = line
                skip_method = False

                # Parse access flags and method signature
                remainder = line[len(".method "):].strip()
                tokens = remainder.split()
                access_flags = []
                method_sig_token = tokens[-1] if tokens else ""

                for t in tokens[:-1]:
                    access_flags.append(t)

                # Skip abstract and native methods (no body)
                if "abstract" in access_flags or "native" in access_flags:
                    skip_method = True

            elif line.startswith(".end method"):
                if in_method and not skip_method:
                    body = "\n".join(method_lines)
                    method_name, signature = SmaliParser._parse_method_sig(
                        method_header
                    )
                    instruction_count = SmaliParser.count_instructions(body)
                    register_count = SmaliParser._extract_register_count(body)

                    methods.append(
                        SmaliMethod(
                            class_name=class_name,
                            method_name=method_name,
                            method_signature=signature,
                            body=body,
                            instruction_count=instruction_count,
                            register_count=register_count,
                            access_flags=access_flags,
                        )
                    )
                in_method = False
                method_lines = []
                access_flags = []

            elif in_method and not skip_method:
                method_lines.append(line)

        return methods

    @staticmethod
    def parse_smali_directory(dirpath: str) -> Dict[str, SmaliMethod]:
        """Parse all .smali files in a directory tree.

        Returns dict keyed by 'ClassName->methodName(signature)ReturnType'.
        """
        result = {}
        for root, _dirs, files in os.walk(dirpath):
            for fname in files:
                if fname.endswith(".smali"):
                    fpath = os.path.join(root, fname)
                    try:
                        methods = SmaliParser.parse_smali_file(fpath)
                        for m in methods:
                            key = SmaliParser.make_method_key(
                                m.class_name, m.method_name, m.method_signature
                            )
                            result[key] = m
                    except Exception:
                        continue
        return result

    @staticmethod
    def normalize_smali_body(body: str) -> str:
        """Normalize smali body for consistent hashing.

        Strips comments, .line directives, normalizes whitespace.
        """
        lines = []
        for line in body.split("\n"):
            stripped = line.strip()
            # Skip empty lines, comments, and .line directives
            if not stripped or stripped.startswith("#"):
                continue
            if _LINE_RE.match(stripped):
                continue
            lines.append(stripped)
        return "\n".join(lines)

    @staticmethod
    def count_instructions(body: str) -> int:
        """Count actual Dalvik instructions (skip directives, labels, blanks)."""
        count = 0
        for line in body.split("\n"):
            stripped = line.strip()
            if not stripped:
                continue
            if _DIRECTIVE_RE.match(stripped):
                continue
            if _LABEL_RE.match(stripped):
                continue
            if _BLANK_OR_COMMENT_RE.match(stripped):
                continue
            count += 1
        return count

    @staticmethod
    def _extract_register_count(body: str) -> int:
        """Extract register count from .registers or .locals directive.

        apktool outputs .locals (local registers only) by default.
        .registers (total = locals + params) is used with --use-registers.
        We return whichever is present.
        """
        for line in body.split("\n"):
            stripped = line.strip()
            m = _REGISTERS_RE.match(stripped)
            if m:
                return int(m.group(1))
            m = _LOCALS_RE.match(stripped)
            if m:
                return int(m.group(1))
        return 0

    @staticmethod
    def _parse_method_sig(header_line: str) -> tuple:
        """Parse method name and signature from .method header line.

        Input: '.method public onCreate(Landroid/os/Bundle;)V'
        Returns: ('onCreate', '(Landroid/os/Bundle;)V')
        """
        remainder = header_line[len(".method "):].strip()
        tokens = remainder.split()
        if not tokens:
            return ("unknown", "()")

        # Last token contains methodName(params)returnType
        method_part = tokens[-1]

        paren_idx = method_part.find("(")
        if paren_idx == -1:
            return (method_part, "()")

        method_name = method_part[:paren_idx]
        signature = method_part[paren_idx:]

        return (method_name, signature)

    @staticmethod
    def make_method_key(class_name: str, method_name: str, signature: str) -> str:
        """Build a canonical method key for cross-tool matching.

        Format: 'Lcom/example/Foo;->methodName(params)ReturnType'
        """
        return f"{class_name}->{method_name}{signature}"