Olivier Rioul

139 papers A* 4A 3B 16C 7Misc 9Journal 68Unranked 31
YearRankTypeTitle / Venue / Authors
2026 J jnl
IACR Trans. Cryptogr. Hardw. Embed. Syst.
Julien Béguinot, Olivier Rioul, Loïc Masure, François-Xavier Standaert, Wei Cheng, Sylvain Guilley
2025 conf
GSI (2)
Olivier Rioul
2025 J jnl
Inf. Process. Lett.
Olivier Rioul, Patrick Solé
2025 J jnl
CoRR
Dimitri Lanier, Julien Béguinot, Olivier Rioul
2025 J jnl
IACR Cryptol. ePrint Arch.
Julien Béguinot, Olivier Rioul, Loïc Masure, François-Xavier Standaert, Wei Cheng, Sylvain Guilley
2024 J jnl
Entropy
Idris Delsol, Olivier Rioul, Julien Béguinot, Victor Rabiet, Antoine Souloumiac
2024 J jnl
Microprocess. Microsystems
Julien Béguinot, Wei Cheng, Sylvain Guilley, Olivier Rioul
2024 J jnl
CoRR
Ilyass Mejdoub, Julien Béguinot, Olivier Rioul
2024 conf
CRYPTO (6)
Julien Béguinot, Wei Cheng, Sylvain Guilley, Olivier Rioul
2024 J jnl
IACR Cryptol. ePrint Arch.
Julien Béguinot, Wei Cheng, Sylvain Guilley, Olivier Rioul
2024 J jnl
J. Cryptogr. Eng.
Wei Cheng, Yi Liu, Sylvain Guilley, Olivier Rioul
2024 conf
EUSIPCO
Olivier Rioul, Antoine Souloumiac
2024 B conf
ISIT
Julien Béguinot, Olivier Rioul
2024 J jnl
CoRR
Julien Béguinot, Olivier Rioul
2023 conf
GSI (1)
Olivier Rioul
2023 J jnl
CoRR
Idris Delsol, Olivier Rioul, Julien Béguinot, Victor Rabiet, Antoine Souloumiac
2023 B conf
ITW
Yi Liu, Julien Béguinot, Wei Cheng, Sylvain Guilley, Loïc Masure, Olivier Rioul, François-Xavier Standaert
2023 B conf
ISIT
Julien Béguinot, Yi Liu, Olivier Rioul, Wei Cheng, Sylvain Guilley
2023 J jnl
CoRR
Julien Béguinot, Yi Liu, Olivier Rioul, Wei Cheng, Sylvain Guilley
2023 Misc conf
IWSEC
Julien Béguinot, Wei Cheng, Jean-Luc Danger, Sylvain Guilley, Olivier Rioul, Ville Yli-Mäyry
2023 conf
COSADE
Julien Béguinot, Wei Cheng, Sylvain Guilley, Yi Liu, Loïc Masure, Olivier Rioul, François-Xavier Standaert
2023 J jnl
Entropy
Olivier Rioul
2022 C conf
CARDIS
Loïc Masure, Olivier Rioul, François-Xavier Standaert
2022 J jnl
IACR Cryptol. ePrint Arch.
Loïc Masure, Olivier Rioul, François-Xavier Standaert
2022 J jnl
CoRR
Yanxi Li, Derek S. Young, Julien Gori, Olivier Rioul
2022 B conf
ISIT
Wei Cheng, Yi Liu, Sylvain Guilley, Olivier Rioul
2022 C conf
DSD
Julien Béguinot, Wei Cheng, Sylvain Guilley, Olivier Rioul
2022 J jnl
IACR Cryptol. ePrint Arch.
Julien Béguinot, Wei Cheng, Sylvain Guilley, Yi Liu, Loïc Masure, Olivier Rioul, François-Xavier Standaert
2022 J jnl
IACR Trans. Cryptogr. Hardw. Embed. Syst.
Julien Béguinot, Wei Cheng, Sylvain Guilley, Olivier Rioul
2022 conf
CWIT
Wei Cheng, Olivier Rioul, Yi Liu, Julien Béguinot, Sylvain Guilley
2022 J jnl
IEEE Trans. Inf. Theory
Olivier Rioul
2021 conf
GSI
Olivier Rioul
2021 J jnl
CoRR
Andrei Tanasescu, Marios O. Choudary, Olivier Rioul, Pantelimon George Popescu
2021 J jnl
CoRR
Wei Cheng, Yi Liu, Sylvain Guilley, Olivier Rioul
2021 B conf
ISIT
Patrick Solé, Wei Cheng, Sylvain Guilley, Olivier Rioul
2021 B conf
ISIT
Olivier Rioul, Wei Cheng, Sylvain Guilley
2021 J jnl
CoRR
Olivier Rioul, Wei Cheng, Sylvain Guilley
2021 J jnl
Graphs Comb.
Minjia Shi, Olivier Rioul, Patrick Solé
2021 J jnl
CoRR
Minjia Shi, Olivier Rioul, Patrick Solé
2021 B conf
ITW
Patrick Solé, Yi Liu, Wei Cheng, Sylvain Guilley, Olivier Rioul
2021 B conf
ITW
Yi Liu, Wei Cheng, Sylvain Guilley, Olivier Rioul
2021 J jnl
CoRR
Yi Liu, Wei Cheng, Sylvain Guilley, Olivier Rioul
2021 J jnl
Entropy
Andrei Tanasescu, Marios O. Choudary, Olivier Rioul, Pantelimon George Popescu
2021 J jnl
CoRR
Olivier Rioul
2020 J jnl
Biol. Cybern.
Julien Gori, Olivier Rioul
2020 J jnl
Adv. Math. Commun.
Alexander Schaub, Olivier Rioul, Jean-Luc Danger, Sylvain Guilley, Joseph Boutros
2020 A* conf
CHI
Wanyu Liu, Julien Gori, Olivier Rioul, Michel Beaudouin-Lafon, Yves Guiard
2020 J jnl
IACR Cryptol. ePrint Arch.
Sébastien Carré, Sylvain Guilley, Olivier Rioul
2020 conf
COSADE
Sébastien Carré, Sylvain Guilley, Olivier Rioul
2020 C conf
ISITA
Olivier Rioul
2020 conf
ECCTD
Alexander Schaub, Jean-Luc Danger, Olivier Rioul, Sylvain Guilley
2019 B conf
ISIT
Éloi de Chérisey, Sylvain Guilley, Olivier Rioul, Pablo Piantanida
2019 J jnl
IEEE Commun. Lett.
Minjia Shi, Olivier Rioul, Patrick Solé
2019 J jnl
IACR Trans. Cryptogr. Hardw. Embed. Syst.
Eloi de Chérisey, Sylvain Guilley, Olivier Rioul, Pablo Piantanida
2019 J jnl
IACR Cryptol. ePrint Arch.
Eloi de Chérisey, Sylvain Guilley, Olivier Rioul, Pablo Piantanida
2019 conf
Allerton
Alexander Schaub, Olivier Rioul, Joseph J. Boutros
2019 J jnl
CoRR
Alexander Schaub, Olivier Rioul, Joseph J. Boutros
2019 B conf
ISIT
Olivier Rioul, Ram Zamir
2019 J jnl
CoRR
Olivier Rioul, Ram Zamir
2019 J jnl
CoRR
Quentin Roy, Yves Guiard, Gilles Bailly, Eric Lecolinet, Olivier Rioul
2019 conf
EUSIPCO
Julien Gori, Olivier Rioul
2019 J jnl
CoRR
Olivier Rioul
2018 J jnl
CoRR
Julien Gori, Olivier Rioul
2018 C conf
DSD
Alexander Schaub, Jean-Luc Danger, Sylvain Guilley, Olivier Rioul
2018 A* conf
CHI
Wanyu Liu, Olivier Rioul, Joanna McGrenere, Wendy E. Mackay, Michel Beaudouin-Lafon
2018 Misc conf
Inscrypt
Eloi de Chérisey, Sylvain Guilley, Olivier Rioul
2018 B conf
SMC
Julien Gori, Olivier Rioul
2018 J jnl
Cryptogr. Commun.
Eloi de Chérisey, Sylvain Guilley, Annelie Heuser, Olivier Rioul
2018 J jnl
CoRR
Olivier Rioul
2018 J jnl
Entropy
Olivier Rioul
2018 J jnl
ACM Trans. Comput. Hum. Interact.
Julien Gori, Olivier Rioul, Yves Guiard
2018 A* conf
CHI
Julien Gori, Olivier Rioul, Yves Guiard, Michel Beaudouin-Lafon
2018 J jnl
IEEE Trans. Broadcast.
Tarak Arbi, Benoit Geller, Jianxiao Yang, Charbel Abdel Nour, Olivier Rioul
2017 conf
ICC
Olivier Rioul
2017 A* conf
CHI
Wanyu Liu, Rafael Gregorio Lucas D'Oliveira, Michel Beaudouin-Lafon, Olivier Rioul
2017 conf
C2SI
Sylvain Guilley, Annelie Heuser, Olivier Rioul
2017 conf
INTERACT (3)
Wanyu Liu, Olivier Rioul, Michel Beaudouin-Lafon, Yves Guiard
2017 conf
INTERACT (3)
Julien Gori, Olivier Rioul, Yves Guiard, Michel Beaudouin-Lafon
2017 conf
GSI
Olivier Rioul
2017 J jnl
CoRR
Olivier Rioul
2017 J jnl
J. Cryptogr. Eng.
Nicolas Bruneau, Sylvain Guilley, Annelie Heuser, Damien Marion, Olivier Rioul
2017 Misc conf
ITA
Olivier Rioul
2017 J jnl
IEEE Trans. Inf. Forensics Secur.
Nicolas Bruneau, Claude Carlet, Sylvain Guilley, Annelie Heuser, Emmanuel Prouff, Olivier Rioul
2017 conf
SECITC
Sylvain Guilley, Annelie Heuser, Ming Tang, Olivier Rioul
2017 J jnl
IEEE Trans. Inf. Theory
Olivier Rioul
2016 J jnl
IACR Cryptol. ePrint Arch.
Sylvain Guilley, Annelie Heuser, Olivier Rioul
2016 J jnl
CoRR
Olivier Rioul
2016 J jnl
IACR Cryptol. ePrint Arch.
Margaux Dugardin, Sylvain Guilley, Jean-Luc Danger, Zakaria Najm, Olivier Rioul
2016 A conf
CHES
Margaux Dugardin, Sylvain Guilley, Jean-Luc Danger, Zakaria Najm, Olivier Rioul
2016 B conf
ISIT
Olivier Rioul, Annelie Heuser, Sylvain Guilley, Jean-Luc Danger
2016 J jnl
IACR Cryptol. ePrint Arch.
Nicolas Bruneau, Sylvain Guilley, Annelie Heuser, Damien Marion, Olivier Rioul
2016 Misc conf
ITA
Olivier Rioul, Max H. M. Costa
2016 B conf
ISIT
Olivier Rioul, Patrick Solé, Sylvain Guilley, Jean-Luc Danger
2016 conf
ASIACRYPT (1)
Nicolas Bruneau, Sylvain Guilley, Annelie Heuser, Olivier Rioul, François-Xavier Standaert, Yannick Teglia
2016 conf
HASP@ISCA
Eloi de Chérisey, Sylvain Guilley, Olivier Rioul, Darshana Jayasinghe
2016 J jnl
IACR Cryptol. ePrint Arch.
Pierre Belgarric, Shivam Bhasin, Nicolas Bruneau, Jean-Luc Danger, Nicolas Debande, Sylvain Guilley, Annelie Heuser, Zakaria Najm, Olivier Rioul
2016 J jnl
CoRR
Olivier Rioul
2015 Misc conf
INDOCRYPT
Sylvain Guilley, Annelie Heuser, Olivier Rioul
2015 conf
ICC
Jianxiao Yang, Kai Wan, Benoit Geller, Charbel Abdel Nour, Olivier Rioul, Catherine Douillard
2015 J jnl
CoRR
Jianxiao Yang, Kai Wan, Benoit Geller, Charbel Abdel Nour, Olivier Rioul, Catherine Douillard
2015 conf
BCS HCI
Yves Guiard, Olivier Rioul
2015 Misc conf
ITA
Olivier Rioul, Max H. M. Costa
2015 conf
INTERACT (4)
Quentin Roy, Yves Guiard, Gilles Bailly, Eric Lecolinet, Olivier Rioul
2015 A conf
CHES
Nicolas Bruneau, Sylvain Guilley, Annelie Heuser, Damien Marion, Olivier Rioul
2015 J jnl
IACR Cryptol. ePrint Arch.
Nicolas Bruneau, Sylvain Guilley, Annelie Heuser, Olivier Rioul
2014 conf
COSADE
Annelie Heuser, Olivier Rioul, Sylvain Guilley
2014 J jnl
IACR Cryptol. ePrint Arch.
Annelie Heuser, Sylvain Guilley, Olivier Rioul
2014 C conf
CRiSIS
Alexander Schaub, Emmanuel Schneider, Alexandros Hollender, Vinicius Calasans, Laurent Jolie, Robin Touillon, Annelie Heuser, Sylvain Guilley, Olivier Rioul
2014 J jnl
IACR Cryptol. ePrint Arch.
Alexander Schaub, Emmanuel Schneider, Alexandros Hollender, Vinicius Calasans, Laurent Jolie, Robin Touillon, Annelie Heuser, Sylvain Guilley, Olivier Rioul
2014 A conf
CHES
Annelie Heuser, Olivier Rioul, Sylvain Guilley
2014 J jnl
IACR Cryptol. ePrint Arch.
Annelie Heuser, Olivier Rioul, Sylvain Guilley
2014 conf
ASIACRYPT (2)
Nicolas Bruneau, Sylvain Guilley, Annelie Heuser, Olivier Rioul
2014 J jnl
Entropy
Olivier Rioul, José Carlos Magossi
2013 B conf
GLOBECOM
Zijian Wang, Wen Chen, Benoit Geller, Olivier Rioul
2013 J jnl
Electron. Notes Discret. Math.
Olivier Rioul, Yves Guiard
2013 C conf
CARDIS
Pierre Belgarric, Shivam Bhasin, Nicolas Bruneau, Jean-Luc Danger, Nicolas Debande, Sylvain Guilley, Annelie Heuser, Zakaria Najm, Olivier Rioul
2012 conf
BCS HCI
Halla B. Olafsdottir, Yves Guiard, Olivier Rioul, Simon T. Perrault
2012 C conf
ICICS
Houssem Maghrebi, Olivier Rioul, Sylvain Guilley, Jean-Luc Danger
2011 J jnl
IEEE Trans. Inf. Theory
Olivier Rioul
2009 book
Olivier Rioul
2007 J jnl
CoRR
Olivier Rioul
2007 B conf
ISIT
Olivier Rioul
2007 J jnl
CoRR
Olivier Rioul
2005 conf
ICECS
Riadh Abdelfattah, Olivier Rioul, Pierre Duhamel
2001 Misc conf
ICASSP
Abraham Gabay, Olivier Rioul, Pierre Duhamel
2000 B conf
GLOBECOM
Abraham Gabay, Pierre Duhamel, Olivier Rioul
2000 conf
EUSIPCO
Abraham Gabay, Pierre Duhamel, Olivier Rioul
1998 J jnl
IEEE Trans. Image Process.
Lamia Karray, Pierre Duhamel, Olivier Rioul
1994 conf
ICASSP (3)
François Déprez, Olivier Rioul, Pierre Duhamel
1994 conf
ICIP (2)
Lamia Karray, Olivier Rioul, Pierre Duhamel
1993 J jnl
IEEE Trans. Signal Process.
Olivier Rioul
1993 conf
ICASSP (5)
Olivier Rioul
1993 J jnl
IEEE Trans. Signal Process.
Olivier Rioul
1993 conf
ICASSP (3)
Thierry Blu, Olivier Rioul
1992 J jnl
IEEE Trans. Inf. Theory
Olivier Rioul, Pierre Duhamel
1992 J jnl
IEEE Trans. Signal Process.
Olivier Rioul, Patrick Flandrin
1991 Misc conf
ICASSP
Olivier Rioul
1991 J jnl
IEEE Signal Process. Mag.
Olivier Rioul, Martin Vetterli
1990 Misc conf
ICASSP
Patrick Flandrin, Olivier Rioul
tests/unit/test_decompile_medium_level.py
← Index tests/unit/test_decompile_medium_level.py python
# tests/unit/test_decompile_medium_level.py
"""Unit tests (mocked BN) for bninja/analysis/medium_level.py
   and bninja/analysis/medium_level_normalization.py."""
# tests/unit/test_decompile_medium_level.py
import sys
from unittest.mock import MagicMock, patch

# Installa gli stubs BN
from tests.unit.conftest_binja_stubs import install_binja_stubs
install_binja_stubs()

# ── Definisci MockMLILInstruction PRIMA di importare il modulo ──
class MockMLILInstruction:
    def __init__(self, operation, address=0, operands=None):
        self.operation = operation
        self.address = address
        self.operands = operands or []

# ── Patcha il modulo BN in modo che isinstance() funzioni ──
sys.modules["binaryninja"].MediumLevelILInstruction = MockMLILInstruction
sys.modules["binaryninja"].SSAVariable = type("SSAVariable", (), {})
sys.modules["binaryninja"].Variable = type("Variable", (), {})
sys.modules["binaryninja"].ILIntrinsic = type("ILIntrinsic", (), {})

# Ora importa il modulo — vede già i tipi corretti
from redb.extractors.decompiler.bninja.analysis.medium_level_normalization import (
    MediumLevelNormalization,
)	

class MockMLILFunction:
    def __init__(self, instructions):
        self._instructions = instructions

    @property
    def instructions(self):
        return iter(self._instructions)

    @property
    def basic_blocks(self):
        # one block containing all instructions, good enough for MinHasher
        block = MagicMock()
        block.__iter__ = lambda self_: iter([])  # not used by MediumLevelAnalysis
        return [block]


class MockFunction:
    def __init__(self, name="func", start=0x1000, mlil=None):
        self.name = name
        self.start = start
        self.mlil = mlil



class TestMediumLevelNormalization:
    def setup_method(self):
        from redb.extractors.decompiler.bninja.analysis.medium_level_normalization import (
            MediumLevelNormalization,
        )
        self.norm = MediumLevelNormalization()

    def test_normalize_skeleton_single_instruction(self):
        il = MockMLILInstruction(operation=42, operands=[])
        result = self.norm.normalize_instruction_all_levels(il)
        assert result == [42]

    def test_normalize_skeleton_nested(self):
        inner = MockMLILInstruction(operation=7, operands=[])
        outer = MockMLILInstruction(operation=1, operands=[inner])
        result = self.norm.normalize_instruction_all_levels(outer)
        assert result == [1, 7]

    def test_normalize_skeleton_with_list_operand(self):
        inner_a = MockMLILInstruction(operation=10, operands=[])
        inner_b = MockMLILInstruction(operation=11, operands=[])
        outer = MockMLILInstruction(operation=2, operands=[[inner_a, inner_b]])
        result = self.norm.normalize_instruction_all_levels(outer)
        assert result == [2, 10, 11]

    def test_normalize_skeleton_none(self):
        result = self.norm.normalize_instruction_all_levels(None)
        # collect on None should leave ops empty
        assert result == []

    def test_normalize_typed_appends_leaf_types(self):
        # operand is a plain int -> "CONST"
        il = MockMLILInstruction(operation=3, operands=[42])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [3, "CONST"]

    def test_normalize_typed_bool_before_int(self):
        # bool must be detected before int (since bool is an int subclass)
        il = MockMLILInstruction(operation=4, operands=[True])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [4, "BOOL"]

    def test_normalize_typed_float(self):
        il = MockMLILInstruction(operation=5, operands=[1.5])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [5, "FLOAT_CONST"]

    def test_normalize_typed_str(self):
        il = MockMLILInstruction(operation=6, operands=["hello"])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [6, "STR"]

    def test_normalize_typed_unknown_falls_back_to_typename(self):
        class Weird:
            pass
        il = MockMLILInstruction(operation=8, operands=[Weird()])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [8, "WEIRD"]

    def test_normalize_typed_nested_mlil(self):
        inner = MockMLILInstruction(operation=99, operands=[7])
        outer = MockMLILInstruction(operation=1, operands=[inner])
        result = self.norm.normalize_instr_with_operands(outer)
        assert result == [1, 99, "CONST"]

    def test_normalize_typed_list_mixed(self):
        inner = MockMLILInstruction(operation=50, operands=[])
        il = MockMLILInstruction(operation=2, operands=[[inner, 99]])
        result = self.norm.normalize_instr_with_operands(il)
        assert result == [2, 50, "CONST"]


class TestMediumLevelAnalysis:
    def _make_analysis(self, instructions=None, mlil=True, start=0x1000):
        from redb.extractors.decompiler.bninja.analysis.medium_level import (
            MediumLevelAnalysis,
        )
        mlil_func = MockMLILFunction(instructions or []) if mlil else None
        func = MockFunction(name="testfunc", start=start, mlil=mlil_func)
        bv = MagicMock()
        return MediumLevelAnalysis(func, bv, MagicMock())

    def test_collect_returns_empty_when_no_mlil(self):
        a = self._make_analysis(mlil=False)
        sk, sk_addr, ty, ty_addr = a._collect_mlil_skeleton_and_typed()
        assert sk == [] and sk_addr == [] and ty == [] and ty_addr == []

    def test_collect_skeleton_and_typed_basic(self):
        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[]),
            MockMLILInstruction(operation=2, address=0x1004, operands=[42]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        sk, sk_addr, ty, ty_addr = a._collect_mlil_skeleton_and_typed()

        assert sk == [[1], [2]]
        assert ty == [[1], [2, "CONST"]]
        assert sk_addr == [(0, [1]), (4, [2])]
        assert ty_addr == [(0, [1]), (4, [2, "CONST"])]

    def test_collect_negative_offset_clamped_to_zero(self):
        instrs = [
            MockMLILInstruction(operation=1, address=0x900, operands=[]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        _, sk_addr, _, ty_addr = a._collect_mlil_skeleton_and_typed()
        assert sk_addr[0][0] == 0
        assert ty_addr[0][0] == 0

    def test_log_error_records_entry(self):
        a = self._make_analysis()
        a.log_error("boom", "fname", 0x1234, ValueError("x"), "loc")
        assert len(a.errors) == 1
        err = a.errors[0]
        assert err["function_name"] == "fname"
        assert err["function_address"] == "4660"  # hex 0x1234
        assert err["error_location"] == "loc"
        assert err["error_message"] == "boom"
        assert err["error_type"] == "ValueError"
        assert "timestamp" in err

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_returns_expected_keys(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = [1, 2, 3]

        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[]),
            MockMLILInstruction(operation=2, address=0x1004, operands=[42]),
            MockMLILInstruction(operation=3, address=0x1008, operands=[]),
        ]
        a = self._make_analysis(instructions=instrs, start=0x1000)
        result, errors = a.analyze()

        expected_keys = {
            "function_address",
            "body_mlil_skeleton_vector",
            "sha256_mlil_skeleton",
            "tlsh_mlil_skeleton",
            "minhash_mlil_skeleton",
            "body_mlil_typed_vector",
            "sha256_mlil_typed",
            "tlsh_mlil_typed",
            "minhash_mlil_typed",
        }
        assert set(result.keys()) == expected_keys
        assert result["function_address"] == 0x1000
        assert result["minhash_mlil_skeleton"] == [1, 2, 3]
        assert result["minhash_mlil_typed"] == [1, 2, 3]
        assert errors == []

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_empty_mlil(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = []
        a = self._make_analysis(mlil=False)
        result, errors = a.analyze()
        assert result["body_mlil_skeleton_vector"] == []
        assert result["body_mlil_typed_vector"] == []
        assert errors == []

    @patch(
        "redb.extractors.decompiler.bninja.analysis.medium_level.MinHasher"
    )
    def test_analyze_sha256_differs_skeleton_vs_typed(self, mock_minhasher):
        mock_minhasher.return_value.calculateMinHash.return_value = []

        instrs = [
            MockMLILInstruction(operation=1, address=0x1000, operands=[42]),
            MockMLILInstruction(operation=2, address=0x1004, operands=["foo"]),
            MockMLILInstruction(operation=3, address=0x1008, operands=[True]),
        ]
        a = self._make_analysis(instructions=instrs)
        result, _ = a.analyze()
        # skeleton ignores operand leaves, typed includes them -> different hashes
        assert result["sha256_mlil_skeleton"] != result["sha256_mlil_typed"]


class TestMinHasherMLILKinds:
    def _make_func(self, instrs):
        # MinHasher iterates basic_blocks then over each block
        block = MagicMock()
        block.__iter__ = lambda self_: iter(instrs)
        f = MagicMock()
        f.basic_blocks = [block]
        return f

    def test_mlil_skeleton_uses_medium_normalizer(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [
            MockMLILInstruction(operation=i, operands=[]) for i in range(5)
        ]
        func = self._make_func(instrs)
        hasher = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL)
        result = hasher.calculateMinHash()
        # 5 instructions -> 3 trigrams -> non-empty signature
        assert result != []

    def test_typed_mlil_differs_from_skeleton(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [
            MockMLILInstruction(operation=1, operands=[42]),
            MockMLILInstruction(operation=2, operands=["s"]),
            MockMLILInstruction(operation=3, operands=[True]),
            MockMLILInstruction(operation=4, operands=[1.5]),
        ]
        func = self._make_func(instrs)
        skel = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL).calculateMinHash()
        typed = MinHasher(seed=42, il_function=func, kind=TokenKind.TYPED_MLIL).calculateMinHash()
        # Same seed, same instructions, but typed has extra leaf tokens
        # -> hashes should generally differ
        assert skel != typed

    def test_mlil_too_few_instructions(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import (
            MinHasher, TokenKind,
        )
        instrs = [MockMLILInstruction(operation=1, operands=[])] * 2
        func = self._make_func(instrs)
        hasher = MinHasher(seed=42, il_function=func, kind=TokenKind.MLIL)
        assert hasher.calculateMinHash() == []

    def test_unsupported_kind_raises(self):
        from redb.extractors.decompiler.bninja.similarity.minhasher import MinHasher
        func = self._make_func([])
        hasher = MinHasher(seed=42, il_function=func, kind="bogus")
        with pytest.raises(ValueError):
            hasher.calculateMinHash()