Kaspar Beelen

32 papers A* 1A 1B 2Misc 1Journal 11Unranked 16
YearRankTypeTitle / Venue / Authors
2024 J jnl
J. Open Source Softw.
Rosie Wood, Kasra Hosseini, Kalle Westerling, Andrew Smith, Kaspar Beelen, Daniel C. S. Wilson, Katherine McDonough
2024 conf
DHd
Estelle Bunout, Marten Düring, Simon Clematide, Maud Ehrmann, Daniele Guido, Rapahëlle Ruppen Coutaz, Kaspar Beelen
2024 conf
DHd
Estelle Bunout, Marten Düring, Simon Clematide, Maud Ehrmann, Daniele Guido, Rapahëlle Ruppen Coutaz, Kaspar Beelen
2024 J jnl
Frontiers Big Data
Marten Düring, Matteo Romanello, Maud Ehrmann, Kaspar Beelen, Daniele Guido, Brecht Deseure, Estelle Bunout, Jana Keck, Petros Apostolopoulos
2023 J jnl
Digit. Scholarsh. Humanit.
Kaspar Beelen, Jon Lawrence, Daniel C. S. Wilson, David Beavan
2023 conf
DH
Kalle Westerling, David Beavan, Kaspar Beelen, Mariona Coll Ardanuy, Timothy Hobson, Christina Last, Nilo Pedrazzini, Griffith Reese, Luke Hare
2023 conf
DH
Kaspar Beelen, Jon Lawrence, Katherine McDonough, Kalle Westerling, Daniel C. S. Wilson
2023 conf
CHR
Mariona Coll Ardanuy, Federico Nanni, Kaspar Beelen, Luke Hare
2022 conf
GeoHumanities@SIGSPATIAL
Kasra Hosseini, Daniel C. S. Wilson, Kaspar Beelen, Katherine McDonough
2022 J jnl
CoRR
Kaspar Beelen, Daniel van Strien
2021 J jnl
CoRR
Kasra Hosseini, Daniel C. S. Wilson, Kaspar Beelen, Katherine McDonough
2021 J jnl
CoRR
Kasra Hosseini, Kaspar Beelen, Giovanni Colavizza, Mariona Coll Ardanuy
2021 conf
CHR
Mariona Coll Ardanuy, Kaspar Beelen, Jon Lawrence, Katherine McDonough, Federico Nanni, Joshua Rhodes, Giorgia Tolfo, Daniel C. S. Wilson
2021 conf
ACL/IJCNLP (Findings)
Kaspar Beelen, Federico Nanni, Mariona Coll Ardanuy, Kasra Hosseini, Giorgia Tolfo, Barbara McGillivray
2020 conf
ICAART (1)
Daniel van Strien, Kaspar Beelen, Mariona Coll Ardanuy, Kasra Hosseini, Barbara McGillivray, Giovanni Colavizza
2020 conf
DH
Kaspar Beelen, Ruth Ahnert, David Beavan, Mariona Coll Ardanuy, Kasra Hosseini, Katherine McDonough, Jon Lawrence, Yann Ryan, Giorgia Tolfo, Mia Ridge, Daniel van Strien, Olivia Vane, Daniel C. S. Wilson
2020 B conf
COLING
Mariona Coll Ardanuy, Federico Nanni, Kaspar Beelen, Kasra Hosseini, Ruth Ahnert, Jon Lawrence, Katherine McDonough, Giorgia Tolfo, Daniel C. S. Wilson, Barbara McGillivray
2020 J jnl
CoRR
Mariona Coll Ardanuy, Federico Nanni, Kaspar Beelen, Kasra Hosseini, Ruth Ahnert, Jon Lawrence, Katherine McDonough, Giorgia Tolfo, Daniel C. S. Wilson, Barbara McGillivray
2020 conf
DH
Yann Ryan, Mariona Coll Ardanuy, Daniel van Strien, Kasra Hosseini, Kaspar Beelen, James Hetherington, Katherine McDonough, Barbara McGillivray, Mia Ridge, Olivia Vane, Daniel C. S. Wilson
2019 B conf
CHIIR
Liliana M. Melgar Estrada, Marijn Koolen, Kaspar Beelen, Hugo C. Huurdeman, Mari Wigham, Carlos Martinez-Ortiz, Jaap Blom, Roeland Ordelman
2018 conf
DH
Kaspar Beelen, Ivan Kisjes, Julia Noordegraaf, Harm Nijboer, Thunnis van Oort, Claartje Rasterhoff
2017 conf
DH
Alex Olieman, Kaspar Beelen
2017 conf
SocInfo (2)
Benjamin Timmermans, Tobias Kuhn, Kaspar Beelen, Lora Aroyo
2017 J jnl
CoRR
Benjamin Timmermans, Tobias Kuhn, Kaspar Beelen, Lora Aroyo
2017 A* conf
SIGIR
Kaspar Beelen, Evangelos Kanoulas, Bob van de Velde
2017 conf
SEMANTiCS (Workshops)
Alex Olieman, Kaspar Beelen, Jaap Kamps
2017 J jnl
CoRR
Alex Olieman, Kaspar Beelen, Jaap Kamps
2017 J jnl
CoRR
Alex Olieman, Kaspar Beelen, Milan van Lange, Jaap Kamps, Maarten Marx
2017 Misc conf
SEMANTiCS
Alex Olieman, Kaspar Beelen, Milan van Lange, Jaap Kamps, Maarten Marx
2017 conf
SEMANTiCS (Workshops)
Kaspar Beelen, Alex Olieman, Jaap Kamps
2017 A conf
CIKM
Hosein Azarbonyad, Mostafa Dehghani, Kaspar Beelen, Alexandra Arkut, Maarten Marx, Jaap Kamps
2017 J jnl
CoRR
Hosein Azarbonyad, Mostafa Dehghani, Kaspar Beelen, Alexandra Arkut, Maarten Marx, Jaap Kamps
tests/unit/test_decompile_scores.py
← Index tests/unit/test_decompile_scores.py python
"""Unit tests for bninja/analysis/scores.py — ObfuscationScores."""
import sys
import pytest
from unittest.mock import MagicMock

# Install binaryninja stubs before importing
from tests.unit.conftest_binja_stubs import (
    install_binja_stubs,
    HighLevelILOperation,
)
bn_mock = install_binja_stubs()

from redb.extractors.decompiler.bninja.analysis.scores import (
    ObfuscationScores,
    get_dominated_by,
    uses_mba,
)
import binaryninja.highlevelil as hlil_mod


# ============================================================================
# Helper: Mock HLIL instruction
# ============================================================================

class MockHLILInstruction(hlil_mod.HighLevelILInstruction):
    """Mock HLIL instruction with operation and operands."""
    def __init__(self, operation, operands=None):
        self.operation = operation
        self.operands = operands or []


class MockHLILBasicBlock:
    """Mock HLIL basic block for flattened score testing."""
    def __init__(self, incoming_edges=None, dominator_tree_children=None):
        self.incoming_edges = incoming_edges or []
        self.dominator_tree_children = dominator_tree_children or []


# ============================================================================
# 5a. ObfuscationScores
# ============================================================================


class TestFlattenedScore:
    def test_flattened_score_no_back_edges(self):
        """Linear CFG with no back edges -> score 0.0."""
        block = MockHLILBasicBlock(incoming_edges=[], dominator_tree_children=[])
        func = MagicMock()
        func.basic_blocks = [block]
        scores = ObfuscationScores(func)
        assert scores.flattened_score() == 0.0

    def test_flattened_score_with_loop(self):
        """CFG with a back edge -> score > 0.0."""
        block = MockHLILBasicBlock(dominator_tree_children=[])
        # Create a back edge: an incoming edge whose source is in the dominated set
        edge = MagicMock()
        edge.source = block  # source IS the dominator -> back edge
        block.incoming_edges = [edge]
        func = MagicMock()
        func.basic_blocks = [block]
        scores = ObfuscationScores(func)
        assert scores.flattened_score() > 0.0

    def test_flattened_score_fully_flat(self):
        """Flattened CFG: one block dominates all -> ratio close to 1.0."""
        children = [MockHLILBasicBlock() for _ in range(4)]
        root = MockHLILBasicBlock(dominator_tree_children=children)
        # Back edge from root incoming
        edge = MagicMock()
        edge.source = root
        root.incoming_edges = [edge]
        all_blocks = [root] + children
        func = MagicMock()
        func.basic_blocks = all_blocks
        scores = ObfuscationScores(func)
        assert scores.flattened_score() == pytest.approx(1.0)


class TestMBAScore:
    def test_mba_score_no_mixed_ops(self):
        """Instructions with only arithmetic -> score 0.0."""
        instr = MockHLILInstruction(HighLevelILOperation.HLIL_ADD, operands=[])
        func = MagicMock()
        func.instructions = [instr]
        scores = ObfuscationScores(func)
        assert scores.MBA_score() == 0.0

    def test_mba_score_mixed_ops(self):
        """Instructions with arithmetic + logic -> score > 0.0."""
        inner_logic = MockHLILInstruction(HighLevelILOperation.HLIL_XOR, operands=[])
        outer_arith = MockHLILInstruction(
            HighLevelILOperation.HLIL_ADD, operands=[inner_logic]
        )
        func = MagicMock()
        func.instructions = [outer_arith]
        scores = ObfuscationScores(func)
        assert scores.MBA_score() > 0.0

    def test_mba_score_all_mixed(self):
        """Every instruction has both -> score 1.0."""
        inner_logic = MockHLILInstruction(HighLevelILOperation.HLIL_NOT, operands=[])
        outer_arith = MockHLILInstruction(
            HighLevelILOperation.HLIL_SUB, operands=[inner_logic]
        )
        func = MagicMock()
        func.instructions = [outer_arith]
        scores = ObfuscationScores(func)
        assert scores.MBA_score() == 1.0


class TestGetDominatedBy:
    def test_get_dominated_by(self):
        child1 = MockHLILBasicBlock(dominator_tree_children=[])
        child2 = MockHLILBasicBlock(dominator_tree_children=[])
        root = MockHLILBasicBlock(dominator_tree_children=[child1, child2])
        result = get_dominated_by(root)
        assert root in result
        assert child1 in result
        assert child2 in result
        assert len(result) == 3


class TestUsesMBA:
    def test_uses_mba_arithmetic_only(self):
        instr = MockHLILInstruction(HighLevelILOperation.HLIL_ADD, operands=[])
        assert uses_mba(instr) is False

    def test_uses_mba_logic_only(self):
        instr = MockHLILInstruction(HighLevelILOperation.HLIL_XOR, operands=[])
        assert uses_mba(instr) is False

    def test_uses_mba_mixed(self):
        inner = MockHLILInstruction(HighLevelILOperation.HLIL_AND, operands=[])
        outer = MockHLILInstruction(HighLevelILOperation.HLIL_ADD, operands=[inner])
        assert uses_mba(outer) is True