Jacques Carlier

70 papers B 4Misc 2Journal 48Unranked 14
YearRankTypeTitle / Venue / Authors
2026 J jnl
Discret. Appl. Math.
Jacques Carlier, Antoine Jouglet, Kristina Kumbria, Abderrahim Sahli
2025 J jnl
RAIRO Oper. Res.
Jacques Carlier, Eric Pinson, Abderrahim Sahli, Antoine Jouglet
2025 J jnl
Discret. Appl. Math.
Istenç Tarhan, Claire Hanen, Alix Munier Kordon, Jacques Carlier, Antoine Jouglet
2025 conf
SoSE
Kristina Kumbria, Jacques Carlier, Antoine Jouglet, Abderrahim Sahli
2024 J jnl
Ann. Oper. Res.
Jacques Carlier, Antoine Jouglet, Abderrahim Sahli
2024 J jnl
Ann. Oper. Res.
Jacques Carlier, Claire Hanen
2023 conf
Euro-Par
Istenç Tarhan, Jacques Carlier, Claire Hanen, Antoine Jouglet, Alix Munier Kordon
2022 J jnl
J. Comb. Optim.
Jacques Carlier, Antoine Jouglet, Eric Pinson, Abderrahim Sahli
2022 J jnl
Int. J. Prod. Res.
Jacques Carlier, Abderrahim Sahli, Antoine Jouglet, Eric Pinson
2021 J jnl
RAIRO Oper. Res.
Abderrahim Sahli, Jacques Carlier, Aziz Moukrim
2020 J jnl
Eur. J. Oper. Res.
Jacques Carlier, Eric Pinson, Abderrahim Sahli, Antoine Jouglet
2019 J jnl
Ad Hoc Networks
Jacques Carlier, Joël Lattmann, Jean-Luc Lutton, Dritan Nace, Thanh Son Pham
2018 J jnl
Discret. Appl. Math.
Jacques Carlier, Aziz Moukrim, Abderrahim Sahli
2017 conf
IPDPS Workshops
Julien Collet, Tanguy Sassolas, Yves Lhuillier, Renaud Sirdey, Jacques Carlier
2016 conf
HPCS
Julien Collet, Tanguy Sassolas, Yves Lhuillier, Renaud Sirdey, Jacques Carlier
2015 J jnl
4OR
Oana Stan, Renaud Sirdey, Jacques Carlier, Dritan Nace
2015 J jnl
Eur. J. Oper. Res.
Ronan Bocquillon, Antoine Jouglet, Jacques Carlier
2014 J jnl
J. Sched.
Mohamed Haouari, Anis Kooli, Emmanuel Néron, Jacques Carlier
2014 J jnl
J. Heuristics
Oana Stan, Renaud Sirdey, Jacques Carlier, Dritan Nace
2013 conf
3PGCIC
Thanh Son Pham, Jacques Carlier, Joël Lattmann, Jean-Luc Lutton, Dritan Nace, Laurent Valeyre
2013 conf
3PGCIC
Oana Stan, Renaud Sirdey, Jacques Carlier, Dritan Nace
2012 conf
ICUMT
Thanh Son Pham, Joël Lattmann, Jean-Luc Lutton, Laurent Valeyre, Jacques Carlier, Dritan Nace
2012 J jnl
Oper. Res. Lett.
Philippe Baptiste, Jacques Carlier, Alexander V. Kononov, Maurice Queyranne, Sergey Sevastyanov, Maxim Sviridenko
2012 J jnl
Comput. Oper. Res.
Sergiu Carpov, Jacques Carlier, Dritan Nace, Renaud Sirdey
2011 J jnl
Eur. J. Oper. Res.
Antoine Jouglet, Jacques Carlier
2011 conf
NBiS
Sergiu Carpov, Jacques Carlier, Dritan Nace, Renaud Sirdey
2011 J jnl
Discret. Appl. Math.
Philippe Baptiste, Jacques Carlier, Alexander V. Kononov, Maurice Queyranne, Sergey Sevastyanov, Maxim Sviridenko
2011 Misc conf
COCOON
Sergiu Carpov, Jacques Carlier, Dritan Nace, Renaud Sirdey
2010 J jnl
Eur. J. Oper. Res.
Jacques Carlier, Mohamed Haouari, Mohamed Kharbeche, Aziz Moukrim
2010 J jnl
Electron. Notes Discret. Math.
Mohamed Kharbeche, Jacques Carlier, Mohamed Haouari, Aziz Moukrim
2010 J jnl
Comput. Ind. Eng.
Jacques Carlier, Fatma Hermès, Aziz Moukrim, Khaled Ghédira
2010 J jnl
Electron. Notes Discret. Math.
Sergiu Carpov, Renaud Sirdey, Jacques Carlier, Dritan Nace
2009 J jnl
J. Heuristics
Renaud Sirdey, Jacques Carlier, Dritan Nace
2009 Misc conf
CSR
Philippe Baptiste, Jacques Carlier, Alexander V. Kononov, Maurice Queyranne, Sergey Sevastyanov, Maxim Sviridenko
2009 conf
ICINCO-ICSO
Fatma Hermès, Jacques Carlier, Aziz Moukrim, Khaled Ghédira
2009 J jnl
Discret. Appl. Math.
Jacques Carlier, Aziz Moukrim, Huang Xu
2008 J jnl
Comput. Oper. Res.
François Clautiaux, Antoine Jouglet, Jacques Carlier, Aziz Moukrim
2008 J jnl
Eur. J. Oper. Res.
Antoine Jouglet, David Savourey, Jacques Carlier, Philippe Baptiste
2008 J jnl
Discret. Appl. Math.
Dominique de Werra, Endre Boros, Jacques Carlier, Alain Hertz, Marino Widmer
2007 J jnl
Oper. Res. Lett.
François Clautiaux, Jacques Carlier, Aziz Moukrim
2007 J jnl
Eur. J. Oper. Res.
François Clautiaux, Jacques Carlier, Aziz Moukrim
2007 J jnl
Eur. J. Oper. Res.
Jacques Carlier, Emmanuel Néron
2007 J jnl
Comput. Oper. Res.
Jacques Carlier, François Clautiaux, Aziz Moukrim
2007 J jnl
Eur. J. Oper. Res.
Renaud Sirdey, Jacques Carlier, Hervé Kerivin, Dritan Nace
2004 J jnl
Eur. J. Oper. Res.
Philippe Baptiste, Jacques Carlier, Antoine Jouglet
2004 ch.
Handbook of Scheduling
Antoine Jouglet, Philippe Baptiste, Jacques Carlier
2004 ch.
Handbook of Scheduling
Jacques Carlier, Laurent Péridy, Eric Pinson, David Rivreau
2004 J jnl
RAIRO Oper. Res.
François Clautiaux, Aziz Moukrim, Stéphane Nègre, Jacques Carlier
2004 J jnl
Ann. Oper. Res.
Philippe Baptiste, Jacques Carlier, Alix Munier, Andreas S. Schulz
2004 J jnl
Discret. Appl. Math.
Jacques Carlier, Eric Pinson
2003 conf
WEA
François Clautiaux, Jacques Carlier, Aziz Moukrim, Stéphane Nègre
2003 J jnl
Eur. J. Oper. Res.
Jacques Carlier, Emmanuel Néron
2002 B conf
SMC
Antoine Jouglet, Philippe Baptiste, Jacques Carlier
2000 J jnl
Eur. J. Oper. Res.
Jacques Carlier, Emmanuel Néron
2000 J jnl
RAIRO Oper. Res.
Jacques Carlier, Emmanuel Néron
2000 J jnl
Telecommun. Syst.
Jean-Luc Lutton, Dritan Nace, Jacques Carlier
2000 J jnl
Algorithmica
Corinne Lucet, Jean-Francois Manouvrier, Jacques Carlier
1999 J jnl
Discret. Appl. Math.
Jean-Paul Boufflet, Jacques Carlier
1999 B conf
OPODIS
Dritan Nace, Jacques Carlier, Jean-Luc Lutton
1999 J jnl
Discret. Appl. Math.
Jacques Carlier, Alain Hertz, Frédéric Maffray, Marino Widmer
1998 B conf
OPODIS
Jacques Carlier, Stéphane Cateloin, Christophe Beaujean
1998 J jnl
Ann. Oper. Res.
Jacques Carlier, Eric Pinson
1997 conf
JFPLC
Jacques Carlier, Eric Pinson
1997 B conf
OPODIS
Jean-Luc Lutton, Dritan Nace, Jacques Carlier
1997 J jnl
Discret. Appl. Math.
Jacques Carlier, Yu Li, Jean-Luc Lutton
1996 J jnl
Discret. Appl. Math.
Jacques Carlier, Corinne Lucet
1995 conf
Combinatorics and Computer Science
Dritan Nace, Jacques Carlier
1993 conf
System Modelling and Optimization
Jacques Carlier, Yu Li, Jean-Luc Lutton
1993 conf
Cliques, Coloring, and Satisfiability
Olivier Dubois, Pascal André, Yacine Boufkhad, Jacques Carlier
1991 J jnl
Theor. Comput. Sci.
Olivier Dubois, Jacques Carlier
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