Rahul Mazumder

112 papers A* 16A 6B 1Journal 78Unranked 11
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Mehdi Makni, Xiang Meng, Rahul Mazumder
2026 J jnl
CoRR
Gregory Dexter, Aida Rahmattalabi, Sanjana Garg, Qinquan Song, Ruby Tu, Yuan Gao, Yi Zhang, Zhipeng Wang, Rahul Mazumder
2026 J jnl
CoRR
Jelena Markovic-Voronov, Kayhan Behdin, Yuanda Xu, Zhengze Zhou, Zhipeng Wang, Rahul Mazumder
2025 conf
CPAL
Mehdi Makni, Kayhan Behdin, Zheng Xu, Natalia Ponomareva, Rahul Mazumder
2025 J jnl
CoRR
Mehdi Makni, Kayhan Behdin, Gabriel Afriat, Zheng Xu, Sergei Vassilvitskii, Natalia Ponomareva, Hussein Hazimeh, Rahul Mazumder
2025 J jnl
CoRR
Petros Prastakos, Kayhan Behdin, Rahul Mazumder
2025 J jnl
CoRR
Kayhan Behdin, Yun Dai, Ata Fatahi Baarzi, Aman Gupta, Qingquan Song, Shao Tang, Hejian Sang, Gregory Dexter, Sirou Zhu, Siyu Zhu, Tejas Dharamsi, Maziar Sanjabi, Vignesh Kothapalli, Hamed Firooz, Zhoutong Fu, Yihan Cao, Pin-Lun Hsu, Fedor Borisyuk, Zhipeng Wang, Rahul Mazumder, Natesh S. Pillai, Luke Simon
2025 conf
WWW (Companion Volume)
Kayhan Behdin, Yun Dai, Gregory Dexter, Aman Gupta, Rahul Mazumder, Ankan Saha, Qingquan Song, Shao Tang, Sirou Zhu, Pin-Lun Hsu
2025 J jnl
CoRR
Brian Liu, Rahul Mazumder, Peter Radchenko
2025 J jnl
CoRR
Mehdi Makni, Kayhan Behdin, Zheng Xu, Natalia Ponomareva, Rahul Mazumder
2025 conf
KDD (2)
Brian Liu, Rahul Mazumder
2025 J jnl
CoRR
Brian Liu, Rahul Mazumder
2025 J jnl
SIAM J. Math. Data Sci.
Haoyue Wang, Shibal Ibrahim, Rahul Mazumder
2025 A* conf
ICLR
Ryan Lucas, Rahul Mazumder
2025 J jnl
J. Mach. Learn. Res.
Brian Liu, Rahul Mazumder
2025 J jnl
CoRR
Ryan Lucas, Kayhan Behdin, Zhipeng Wang, Qingquan Song, Shao Tang, Rahul Mazumder
2025 conf
KDD (2)
Mehdi Makni, Kayhan Behdin, Gabriel Afriat, Zheng Xu, Sergei Vassilvitskii, Natalia Ponomareva, Rahul Mazumder, Hussein Hazimeh
2025 conf
EMNLP (Industry Track)
Kayhan Behdin, Ata Fatahi Baarzi, Qingquan Song, Yun Dai, Aman Gupta, Zhipeng Wang, Hejian Sang, Shao Tang, Gregory Dexter, Sirou Zhu, Siyu Zhu, Tejas Dharamsi, Vignesh Kothapalli, Zhoutong Fu, Yihan Cao, Pin-Lun Hsu, Fedor Borisyuk, Natesh S. Pillai, Luke Simon, Rahul Mazumder
2025 J jnl
CoRR
Xiang Meng, Mehdi Makni, Rahul Mazumder
2025 J jnl
CoRR
Houssam El Cheairi, David Gamarnik, Rahul Mazumder
2024 J jnl
Math. Program. Comput.
Wenyu Chen, Rahul Mazumder, Richard J. Samworth
2024 A* conf
NeurIPS
Xiang Meng, Kayhan Behdin, Haoyue Wang, Rahul Mazumder
2024 J jnl
CoRR
Xiang Meng, Kayhan Behdin, Haoyue Wang, Rahul Mazumder
2024 J jnl
CoRR
Lars Hertel, Neil Daftary, Fedor Borisyuk, Aman Gupta, Rahul Mazumder
2024 A conf
AISTATS
Shibal Ibrahim, Kayhan Behdin, Rahul Mazumder
2024 A conf
AISTATS
Xiang Meng, Wenyu Chen, Riade Benbaki, Rahul Mazumder
2024 J jnl
CoRR
Xiang Meng, Wenyu Chen, Riade Benbaki, Rahul Mazumder
2024 A* conf
KDD
Brian Liu, Rahul Mazumder
2024 J jnl
CoRR
Brian Liu, Rahul Mazumder
2024 J jnl
CoRR
Zirui Liu, Qingquan Song, Qiang Charles Xiao, Sathiya Keerthi Selvaraj, Rahul Mazumder, Aman Gupta, Xia Hu
2024 A* conf
ICML
Xiang Meng, Shibal Ibrahim, Kayhan Behdin, Hussein Hazimeh, Natalia Ponomareva, Rahul Mazumder
2024 J jnl
CoRR
Xiang Meng, Shibal Ibrahim, Kayhan Behdin, Hussein Hazimeh, Natalia Ponomareva, Rahul Mazumder
2024 J jnl
SIAM J. Optim.
Rahul Mazumder, Haoyue Wang
2024 J jnl
CoRR
Ryan Lucas, Rahul Mazumder
2024 J jnl
CoRR
Brian Liu, Rahul Mazumder
2024 J jnl
J. Mach. Learn. Res.
Kayhan Behdin, Rahul Mazumder
2024 J jnl
SIAM J. Optim.
Wenyu Chen, Rahul Mazumder
2023 A* conf
KDD
Shibal Ibrahim, Wenyu Chen, Hussein Hazimeh, Natalia Ponomareva, Zhe Zhao, Rahul Mazumder
2023 J jnl
CoRR
Shibal Ibrahim, Wenyu Chen, Hussein Hazimeh, Natalia Ponomareva, Zhe Zhao, Rahul Mazumder
2023 conf
ICAIF
Shibal Ibrahim, Max Tell, Rahul Mazumder
2023 conf
ICAIF
Wenyu Chen, Riade Benbaki, Yada Zhu, Rahul Mazumder
2023 J jnl
CoRR
Shibal Ibrahim, Kayhan Behdin, Rahul Mazumder
2023 J jnl
CoRR
Brian Liu, Rahul Mazumder
2023 A* conf
ICML
Riade Benbaki, Wenyu Chen, Xiang Meng, Hussein Hazimeh, Natalia Ponomareva, Zhe Zhao, Rahul Mazumder
2023 J jnl
CoRR
Riade Benbaki, Wenyu Chen, Xiang Meng, Hussein Hazimeh, Natalia Ponomareva, Zhe Zhao, Rahul Mazumder
2023 A* conf
KDD
Brian Liu, Rahul Mazumder
2023 A conf
AISTATS
Brian Liu, Rahul Mazumder
2023 A* conf
NeurIPS
Shibal Ibrahim, Gabriel Afriat, Kayhan Behdin, Rahul Mazumder
2023 J jnl
J. Mach. Learn. Res.
Hussein Hazimeh, Rahul Mazumder, Tim Nonet
2023 J jnl
Math. Program.
Rahul Mazumder, Haoyue Wang
2023 J jnl
CoRR
Hanbyul Lee, Rahul Mazumder, Qifan Song, Jean Honorio
2023 A* conf
NeurIPS
Rahul Mazumder, Haoyue Wang
2023 J jnl
CoRR
Rahul Mazumder, Haoyue Wang
2023 A conf
CIKM
Ayan Acharya, Siyuan Gao, Ankan Saha, Borja Ocejo, Kinjal Basu, Sathiya Keerthi Selvaraj, Rahul Mazumder, Aman Gupta, Parag Agrawal
2023 A* conf
KDD
Aman Gupta, S. Sathiya Keerthi, Ayan Acharya, Miao Cheng, Borja Ocejo Elizondo, Rohan Ramanath, Rahul Mazumder, Kinjal Basu, J. Kenneth Tay, Rupesh Gupta
2023 conf
WWW (Companion Volume)
Ayan Acharya, Siyuan Gao, Borja Ocejo, Kinjal Basu, Ankan Saha, Sathiya Keerthi Selvaraj, Rahul Mazumder, Parag Agrawal, Aman Gupta
2023 J jnl
CoRR
Kayhan Behdin, Ayan Acharya, Aman Gupta, Sathiya Keerthi Selvaraj, Rahul Mazumder
2023 J jnl
CoRR
Kayhan Behdin, Rahul Mazumder
2023 J jnl
CoRR
Kayhan Behdin, Wenyu Chen, Rahul Mazumder
2023 J jnl
Oper. Res.
Rahul Mazumder, Peter Radchenko, Antoine Dedieu
2023 J jnl
CoRR
Kayhan Behdin, Qingquan Song, Aman Gupta, Ayan Acharya, David Durfee, Borja Ocejo, S. Sathiya Keerthi, Rahul Mazumder
2022 A* conf
KDD
Shibal Ibrahim, Hussein Hazimeh, Rahul Mazumder
2022 J jnl
CoRR
Shibal Ibrahim, Hussein Hazimeh, Rahul Mazumder
2022 J jnl
CoRR
Brian Liu, Rahul Mazumder
2022 J jnl
SIAM J. Optim.
Haoyue Wang, Haihao Lu, Rahul Mazumder
2022 J jnl
CoRR
Kayhan Behdin, Qingquan Song, Aman Gupta, David Durfee, Ayan Acharya, S. Sathiya Keerthi, Rahul Mazumder
2022 conf
ICAIF
Shibal Ibrahim, Wenyu Chen, Yada Zhu, Pin-Yu Chen, Yang Zhang, Rahul Mazumder
2022 J jnl
CoRR
Hussein Hazimeh, Rahul Mazumder, Tim Nonet
2022 conf
ECML/PKDD (1)
Shibal Ibrahim, Natalia Ponomareva, Rahul Mazumder
2022 A* conf
NeurIPS
Brian Hsu, Rahul Mazumder, Preetam Nandy, Kinjal Basu
2022 J jnl
CoRR
Brian Hsu, Rahul Mazumder, Preetam Nandy, Kinjal Basu
2022 A* conf
ICML
Rahul Mazumder, Xiang Meng, Haoyue Wang
2022 J jnl
CoRR
Rahul Mazumder, Xiang Meng, Haoyue Wang
2022 J jnl
J. Mach. Learn. Res.
Antoine Dedieu, Rahul Mazumder, Haoyue Wang
2022 J jnl
Math. Program.
Hussein Hazimeh, Rahul Mazumder, Ali Saab
2022 J jnl
Oper. Res.
Santanu S. Dey, Rahul Mazumder, Guanyi Wang
2021 J jnl
CoRR
Kayhan Behdin, Rahul Mazumder
2021 A* conf
NeurIPS
Hussein Hazimeh, Zhe Zhao, Aakanksha Chowdhery, Maheswaran Sathiamoorthy, Yihua Chen, Rahul Mazumder, Lichan Hong, Ed H. Chi
2021 J jnl
CoRR
Hussein Hazimeh, Zhe Zhao, Aakanksha Chowdhery, Maheswaran Sathiamoorthy, Yihua Chen, Rahul Mazumder, Lichan Hong, Ed H. Chi
2021 J jnl
CoRR
Hussein Hazimeh, Rahul Mazumder, Peter Radchenko
2021 J jnl
J. Mach. Learn. Res.
Antoine Dedieu, Hussein Hazimeh, Rahul Mazumder
2021 B conf
IPCO
Rahul Mazumder, Haoyue Wang
2021 J jnl
CoRR
Shibal Ibrahim, Natalia Ponomareva, Rahul Mazumder
2021 J jnl
CoRR
Gabriel Loewinger, Rolando Acosta Nunez, Rahul Mazumder, Giovanni Parmigiani
2021 J jnl
CoRR
Shibal Ibrahim, Rahul Mazumder, Peter Radchenko, Emanuel Ben-David
2020 A* conf
ICML
Kinjal Basu, Amol Ghoting, Rahul Mazumder, Yao Pan
2020 J jnl
Oper. Res.
Hussein Hazimeh, Rahul Mazumder
2020 A conf
AISTATS
Hussein Hazimeh, Rahul Mazumder
2020 J jnl
CoRR
Antoine Dedieu, Hussein Hazimeh, Rahul Mazumder
2020 J jnl
Stat. Comput.
Rahul Mazumder, Diego Saldana, Haolei Weng
2020 J jnl
SIAM J. Optim.
Haihao Lu, Rahul Mazumder
2020 J jnl
CoRR
Hussein Hazimeh, Rahul Mazumder, Ali Saab
2020 A* conf
ICML
Hussein Hazimeh, Natalia Ponomareva, Petros Mol, Zhenyu Tan, Rahul Mazumder
2020 J jnl
CoRR
Hussein Hazimeh, Natalia Ponomareva, Petros Mol, Zhenyu Tan, Rahul Mazumder
2019 J jnl
Math. Program.
Koulik Khamaru, Rahul Mazumder
2019 J jnl
CoRR
Hussein Hazimeh, Rahul Mazumder
2019 J jnl
INFORMS J. Optim.
Hari Bandi, Dimitris Bertsimas, Rahul Mazumder
2019 J jnl
CoRR
Antoine Dedieu, Rahul Mazumder
2018 J jnl
CoRR
Robert M. Freund, Paul Grigas, Rahul Mazumder
2018 J jnl
CoRR
Antoine Dedieu, Rahul Mazumder, Zhen Zhu, Hossein Vahabi
2018 A conf
CIKM
Antoine Dedieu, Rahul Mazumder, Zhen Zhu, Hossein Vahabi
2018 J jnl
CoRR
Haihao Lu, Rahul Mazumder
2017 J jnl
SIAM J. Optim.
Robert M. Freund, Paul Grigas, Rahul Mazumder
2017 J jnl
J. Mach. Learn. Res.
Dimitris Bertsimas, Martin S. Copenhaver, Rahul Mazumder
2017 J jnl
IEEE Trans. Inf. Theory
Rahul Mazumder, Peter Radchenko
2015 J jnl
CoRR
Robert M. Freund, Paul Grigas, Rahul Mazumder
2015 J jnl
J. Mach. Learn. Res.
Trevor Hastie, Rahul Mazumder, Jason D. Lee, Reza Zadeh
2013 J jnl
CoRR
Robert M. Freund, Paul Grigas, Rahul Mazumder
2013 conf
MLSP
Dennis L. Sun, Rahul Mazumder
2012 J jnl
J. Mach. Learn. Res.
Rahul Mazumder, Trevor Hastie
2011 J jnl
CoRR
Rahul Mazumder, Trevor Hastie
2010 J jnl
J. Mach. Learn. Res.
Rahul Mazumder, Trevor Hastie, Robert Tibshirani
redb/extractors/decompiler/DecompileAPK.py
← Index redb/extractors/decompiler/DecompileAPK.py python
"""APK Code Analysis Extractor.

Decompiles and disassembles APK DEX bytecode at the method level,
producing per-method content and reference records analogous to
the Binary Ninja code_binja_* tables.

Uses androguard + JADX + apktool to replicate Binary Ninja analysis
depth for Android applications.
"""

import gc
import hashlib
import inspect
import logging
import os
import threading
import time
from datetime import datetime, timezone
from typing import Any, Dict, Optional

from redb.extractors.decompiler.apk.analyzer import APKCodeAnalyzer
from redb.extractors.enum import Tag
from redb.extractors.extractor import Extractor


class DecompileAPK(Extractor):
    """APK code analysis extractor — produces multi-table ClickHouse export.

    Follows the same pattern as DecompileBinja for consistency.
    """

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        known_benign=False,
        known_malicious=False,
        filetype=None,
        decompile_modules=None,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            known_benign=known_benign,
            known_malicious=known_malicious,
        )
        self.log.debug(inspect.currentframe().f_code.co_name)
        self.analysis_results = None
        self.analyzer = None
        self.filetype = filetype or "apk"
        self.decompile_modules = decompile_modules or {"all"}

        try:
            self.APK_DECOMPILE_TIMEOUT = int(
                os.getenv("APK_DECOMPILE_TIMEOUT", "600")
            )
        except ValueError:
            self.log.warning(
                "Invalid APK_DECOMPILE_TIMEOUT value, using default of 600 seconds"
            )
            self.APK_DECOMPILE_TIMEOUT = 600

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cleanup_run()

    def calculate_md5(self, input_str):
        """Calculate MD5 hash of a string."""
        return hashlib.md5(input_str.encode("utf-8")).hexdigest()

    def cleanup_run(self):
        """Clean up after analysis."""
        try:
            if self.analyzer:
                self.analyzer.cleanup()
                self.analyzer = None
            gc.collect()
        except Exception as e:
            self.log.error(f"Error in cleanup: {e}")

    def analyze_apk(self) -> Optional[Dict[str, Any]]:
        """Run APK code analysis and return results."""
        self.log.debug("Starting APK code analysis")
        try:
            self.analyzer = APKCodeAnalyzer(
                filepath=self.filepath,
                timeout=self.APK_DECOMPILE_TIMEOUT,
                log=self.log,
                decompile_modules=self.decompile_modules,
            )
            results = self.analyzer.extract()
            return results
        except Exception as e:
            self.log.error(f"Error in APK code analysis: {e}")
            import traceback
            self.log.error(f"Traceback: {traceback.format_exc()}")
            return None
        finally:
            self.cleanup_run()

    def extract(self):
        """Extract and process all analysis results.

        Uses daemon thread with timeout, same pattern as DecompileBinja.
        """
        self.log.debug(inspect.currentframe().f_code.co_name)

        extraction_completed = False
        extraction_result = False
        extraction_error = None

        def do_extraction():
            nonlocal extraction_completed, extraction_result, extraction_error
            try:
                results = self.analyze_apk()
                if not results:
                    extraction_result = False
                else:
                    self.analysis_results = results
                    self.analysis_results["sha256"] = self.sha256
                    self.analysis_results["sha1"] = self.sha1
                    self.analysis_results["md5"] = self.md5
                    extraction_result = True
            except Exception as e:
                extraction_error = e
                extraction_result = False
            finally:
                extraction_completed = True

        extraction_thread = threading.Thread(target=do_extraction)
        extraction_thread.daemon = True
        extraction_thread.start()

        start_time = time.time()
        while (
            not extraction_completed
            and (time.time() - start_time) < self.APK_DECOMPILE_TIMEOUT
        ):
            time.sleep(1)

        if not extraction_completed:
            self.log.error(
                f"APK extraction timed out after {self.APK_DECOMPILE_TIMEOUT} seconds"
            )
            self.cleanup_run()
            return None

        if extraction_error:
            self.log.error(f"Error in APK extraction: {extraction_error}")
            return None

        return self.analysis_results if extraction_result else None

    def prepare_export_data(self, exporter_type: str) -> Any:
        """Prepare data for database export."""
        self.log.debug(inspect.currentframe().f_code.co_name)
        if not self.analysis_results:
            return None

        if exporter_type == "ClickHouseExporter":
            now = datetime.now(timezone.utc)
            export = {"multi_table": True}

            # Table 1: Decompiled method content
            if self.analysis_results.get("decompiled_content"):
                export["decompiled_content"] = {
                    "table": "code_apk_decompiled_methods_content",
                    "data": [
                        [
                            f["decompiled_method_hash"],
                            f["decompiled_method"],
                            f.get("decompiled_method_type", "UNKNOWN"),
                            1 if f.get("decompiled_has_string_encryption") else 0,
                            1 if f.get("decompiled_has_reflection_calls") else 0,
                            1 if f.get("decompiled_excessive_goto_count") else 0,
                            now,
                        ]
                        for f in self.analysis_results["decompiled_content"]
                    ],
                    "column_names": [
                        "decompiled_method_hash",
                        "decompiled_method",
                        "decompiled_method_type",
                        "decompiled_has_string_encryption",
                        "decompiled_has_reflection_calls",
                        "decompiled_excessive_goto_count",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'UNKNOWN'=5)",
                        "UInt8",
                        "UInt8",
                        "UInt8",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 2: Decompiled method references
            if self.analysis_results.get("decompiled_refs"):
                export["decompiled_refs"] = {
                    "table": "code_apk_decompiled_methods_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["decompiled_method_hash"],
                            f.get("smali_method_hash"),
                            f.get("decompiled_class_name", ""),
                            f.get("decompiled_method_name", ""),
                            f.get("decompiled_method_signature", ""),
                            f.get("decompiled_method_prototype", ""),
                            f.get("functions_caller", []),
                            f.get("functions_call", []),
                            now,
                        ]
                        for f in self.analysis_results["decompiled_refs"]
                    ],
                    "column_names": [
                        "sha256",
                        "decompiled_method_hash",
                        "smali_method_hash",
                        "decompiled_class_name",
                        "decompiled_method_name",
                        "decompiled_method_signature",
                        "decompiled_method_prototype",
                        "functions_caller",
                        "functions_call",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "String",
                        "String",
                        "Array(String)",
                        "Array(String)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 3: Smali method content
            if self.analysis_results.get("smali_content"):
                export["smali_content"] = {
                    "table": "code_apk_smali_methods_content",
                    "data": [
                        [
                            f["smali_method_hash"],
                            f["smali_method"],
                            f.get("smali_method_type", "UNKNOWN"),
                            f.get("smali_instructions_count", 0),
                            f.get("smali_register_count", 0),
                            1 if f.get("smali_has_string_encryption") else 0,
                            1 if f.get("smali_has_reflection_calls") else 0,
                            1 if f.get("smali_excessive_goto_count") else 0,
                            f.get("smali_flattened_score", 0.0),
                            f.get("smali_mba_score", 0.0),
                            now,
                        ]
                        for f in self.analysis_results["smali_content"]
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "smali_method",
                        "smali_method_type",
                        "smali_instructions_count",
                        "smali_register_count",
                        "smali_has_string_encryption",
                        "smali_has_reflection_calls",
                        "smali_excessive_goto_count",
                        "smali_flattened_score",
                        "smali_mba_score",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "Enum8('USER'=1, 'LIBRARY'=2, 'UNKNOWN'=5)",
                        "UInt32",
                        "UInt16",
                        "UInt8",
                        "UInt8",
                        "UInt8",
                        "Float64",
                        "Float64",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 4: Smali method references
            if self.analysis_results.get("smali_refs"):
                export["smali_refs"] = {
                    "table": "code_apk_smali_methods_references",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f["smali_method_hash"],
                            f.get("decompiled_method_hash"),
                            f.get("smali_class_name", ""),
                            f.get("smali_method_name", ""),
                            f.get("smali_method_signature", ""),
                            now,
                        ]
                        for f in self.analysis_results["smali_refs"]
                    ],
                    "column_names": [
                        "sha256",
                        "smali_method_hash",
                        "decompiled_method_hash",
                        "smali_class_name",
                        "smali_method_name",
                        "smali_method_signature",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(64)",
                        "Nullable(FixedString(64))",
                        "LowCardinality(String)",
                        "LowCardinality(String)",
                        "String",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 5: Method similarity metrics (content-based fuzzy matching)
            if self.analysis_results.get("similarity_metrics"):
                export["method_similarity_metrics"] = {
                    "table": "code_apk_method_similarity_metrics",
                    "data": [
                        [
                            f["smali_method_hash"],
                            f.get("ssdeep_smali"),
                            f.get("tlsh_smali"),
                            f.get("ssdeep_smali_normalized"),
                            f.get("tlsh_smali_normalized"),
                            f.get("minhash", []),
                            now,
                        ]
                        for f in self.analysis_results["similarity_metrics"]
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "ssdeep_smali",
                        "tlsh_smali",
                        "ssdeep_smali_normalized",
                        "tlsh_smali_normalized",
                        "minhash",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Nullable(String)",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 5b: CFG method features (structural/topological)
            if self.analysis_results.get("cfg"):
                export["cfg_methods"] = {
                    "table": "code_apk_cfg_methods",
                    "data": [
                        [
                            cfg["smali_method_hash"],
                            cfg["cfg_topology_hash"],
                            cfg["block_count"],
                            cfg["edge_count"],
                            cfg.get("cfg_instructions_count", 0),
                            cfg.get("call_count", 0),
                            cfg["cyclomatic_complexity"],
                            cfg.get("loop_count", 0),
                            cfg.get("max_depth", 0),
                            cfg.get("max_fan_out", 0),
                            cfg.get("md_index_topdown", 0),
                            cfg.get("md_index_bottomup", 0),
                            cfg.get("prime_product_smali", 0),
                            cfg.get("cfg_feature_tlsh"),
                            cfg.get("wl_minhash", []),
                            cfg.get("bb_features", []),
                            cfg.get("cfg_adjacency", []),
                            now,
                        ]
                        for cfg in self.analysis_results["cfg"]
                        if cfg is not None
                    ],
                    "column_names": [
                        "smali_method_hash",
                        "cfg_topology_hash",
                        "block_count",
                        "edge_count",
                        "cfg_instructions_count",
                        "call_count",
                        "cyclomatic_complexity",
                        "loop_count",
                        "max_depth",
                        "max_fan_out",
                        "md_index_topdown",
                        "md_index_bottomup",
                        "prime_product_smali",
                        "cfg_feature_tlsh",
                        "wl_minhash",
                        "bb_features",
                        "cfg_adjacency",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "FixedString(16)",
                        "UInt16",
                        "UInt16",
                        "UInt32",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt16",
                        "UInt64",
                        "UInt64",
                        "UInt64",
                        "Nullable(FixedString(72))",
                        "Array(UInt8)",
                        "Array(Array(UInt16))",
                        "Array(UInt32)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            # Table 6: Strings — reuse code_binja_strings_raw for cross-format correlation
            # DEX strings are MUTF-8; string_raw = string since no encoding difference
            if self.analysis_results.get("strings"):
                export["strings_raw"] = {
                    "table": "code_binja_strings_raw",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            s["string"],
                            s["string"],  # string_raw = string (MUTF-8 decoded to UTF-8)
                            s.get("string_encoding", "UTF8"),
                            s.get("string_offset", 0),
                            s.get("string_length", len(s["string"])),
                            s.get("string_length", len(s["string"])),  # string_raw_length = string_length
                            s.get("string_entropy", 0.0),
                        ]
                        for s in self.analysis_results["strings"]
                    ],
                    "column_names": [
                        "sha256",
                        "string",
                        "string_raw",
                        "string_encoding",
                        "string_offset",
                        "string_length",
                        "string_raw_length",
                        "string_entropy",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "String",
                        "String",
                        "LowCardinality(String)",
                        "UInt64",
                        "UInt32",
                        "UInt32",
                        "Float32",
                    ],
                }

            # Table 7: Analysis errors
            if self.analysis_results.get("analysis_errors"):
                export["analysis_errors"] = {
                    "table": "code_apk_analysis_errors",
                    "data": [
                        [
                            self.analysis_results["sha256"],
                            f.get("class_name"),
                            f.get("method_name"),
                            f.get("error_location", "unknown"),
                            f.get("error_message", ""),
                            f.get("error_type", "unknown"),
                            self.calculate_md5(
                                f"{f.get('error_message', '')}"
                                f"{f.get('class_name', '')}"
                                f"{f.get('method_name', '')}"
                                f"{f.get('error_location', 'unknown')}"
                            ),
                            "new",
                            now,
                        ]
                        for f in self.analysis_results["analysis_errors"]
                    ],
                    "column_names": [
                        "sha256",
                        "class_name",
                        "method_name",
                        "error_location",
                        "error_message",
                        "error_type",
                        "error_hash",
                        "status",
                        "analysis_date",
                    ],
                    "column_type_names": [
                        "FixedString(64)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "LowCardinality(String)",
                        "Nullable(String)",
                        "Nullable(String)",
                        "FixedString(32)",
                        "Enum8('new'=1, 'investigating'=2, 'fixed'=3, 'wontfix'=4)",
                        "DateTime64(3, 'UTC')",
                    ],
                }

            return export

        return None

    def tag(self) -> str:
        """Return the tag for this extractor."""
        return Tag.APK_DECOMPILED.value

    def get_clickhouse_table(self) -> str:
        """Not used directly as we're handling multiple tables."""
        pass