Walid Bousselham

17 papers A* 3A 1Journal 12Unranked 1
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Walid Bousselham, Angie W. Boggust, Hendrik Strobelt, Hilde Kuehne
2026 J jnl
CoRR
Soumya Jahagirdar, Walid Bousselham, Anna Kukleva, Hilde Kuehne
2025 J jnl
CoRR
Sofian Chaybouti, Walid Bousselham, Moritz Wolter, Hilde Kuehne
2025 J jnl
CoRR
Walid Bousselham, Hilde Kuehne, Cordelia Schmid
2025 A* conf
CVPR
Felix Vogel, Walid Bousselham, Anna Kukleva, Nina Shvetsova, Hilde Kuehne
2025 J jnl
CoRR
Felix Vogel, Walid Bousselham, Anna Kukleva, Nina Shvetsova, Hilde Kuehne
2024 A* conf
CVPR
Walid Bousselham, Felix Petersen, Vittorio Ferrari, Hilde Kuehne
2024 J jnl
CoRR
Walid Bousselham, Angie W. Boggust, Sofian Chaybouti, Hendrik Strobelt, Hilde Kuehne
2024 J jnl
CoRR
Walid Bousselham, Sofian Chaybouti, Christian Rupprecht, Vittorio Ferrari, Hilde Kuehne
2023 J jnl
Frontiers Bioinform.
Lucas Pagano, Guillaume Thibault, Walid Bousselham, Jessica L. Riesterer, Xubo Song, Joe W. Gray
2023 J jnl
CoRR
Walid Bousselham, Felix Petersen, Vittorio Ferrari, Hilde Kuehne
2023 A* conf
CVPR
Aisha Urooj Khan, Hilde Kuehne, Bo Wu, Kim Chheu, Walid Bousselham, Chuang Gan, Niels da Vitoria Lobo, Mubarak Shah
2023 J jnl
CoRR
Aisha Urooj Khan, Hilde Kuehne, Bo Wu, Kim Chheu, Walid Bousselham, Chuang Gan, Niels da Vitoria Lobo, Mubarak Shah
2022 A conf
BMVC
Walid Bousselham, Guillaume Thibault, Lucas Pagano, Archana Machireddy, Joe W. Gray, Young Hwan Chang, Xubo Song
2021 J jnl
CoRR
Walid Bousselham, Guillaume Thibault, Lucas Pagano, Archana Machireddy, Joe W. Gray, Young Hwan Chang, Xubo Song
2020 conf
VISIGRAPP (4: VISAPP)
Kazuki Nishiguchi, Walid Bousselham, Hideaki Uchiyama, Diego Thomas, Atsushi Shimada, Rin-Ichiro Taniguchi
2020 J jnl
IEEE Access
Francesco Potortì, Sangjoon Park, Antonino Crivello, Filippo Palumbo, Michele Girolami, Paolo Barsocchi, Soyeon Lee, Joaquín Torres-Sospedra, Antonio Ramón Jiménez Ruiz, Antoni Pérez-Navarro, Germán Martín Mendoza-Silva, Fernando Seco, Miguel Ortiz, Johan Perul, Valérie Renaudin, Hyunwoong Kang, Soyoung Park, Jae Hong Lee, Chan Gook Park, Jisu Ha, Jaeseung Han, Changjun Park, Keunhye Kim, Yonghyun Lee, Seunghun Gye, Keumryeol Lee, Eun-Jee Kim, Jeongsik Choi, Yang-Seok Choi, Shilpa Talwar, Seong Yun Cho, Boaz Ben-Moshe, Alex Scherbakov, Leonid Antsfeld, Emilio Sansano-Sansano, Boris Chidlovskii, Nikolai Kronenwett, Silvia Prophet, Yael Landay, Revital Marbel, Lingxiang Zheng, Ao Peng, Zhichao Lin, Bang Wu, Chengqi Ma, Stefan Poslad, David R. Selviah, Wei Wu, Zixiang Ma, Wenchao Zhang, Dongyan Wei, Hong Yuan, Jun-Bang Jiang, Shao-Yung Huang, Jing-Wen Liu, Kuan-Wu Su, Jenq-Shiou Leu, Kazuki Nishiguchi, Walid Bousselham, Hideaki Uchiyama, Diego Thomas, Atsushi Shimada, Rin-Ichiro Taniguchi, Vicente Cortés Puschel, Tomás Lungenstrass Poulsen, Imran Ashraf, Chanseok Lee, Muhammad Usman Ali, Yeongjun Im, Gunzung Kim, Jeongsook Eom, Soojung Hur, Yongwan Park, Miroslav Opiela, Adriano J. C. Moreira, Maria João Nicolau, Cristiano G. Pendão, Ivo Silva, Filipe Meneses, António Costa, Jens Trogh, David Plets, Ying-Ren Chien, Tzu-Yu Chang, Shih-Hau Fang, Yu Tsao
redb/extractors/decompiler/bninja/similarity/minhasher.py
← Index redb/extractors/decompiler/bninja/similarity/minhasher.py python
import logging
import random
from enum import Enum

from ..analysis.medium_level_normalization import MediumLevelNormalization

try:
    from .minhashcustom import MinHashCustom
    from ..analysis.low_level_normalization import LowLevelNormalization
except ImportError:
    # Fallback to absolute imports (for multiprocessing spawned processes)
    from redb.extractors.decompiler.bninja.similarity.minhashcustom import MinHashCustom
    from redb.extractors.decompiler.bninja.analysis.low_level_normalization import LowLevelNormalization

## Values for this configuration were extracted from https://github.com/danielplohmann/mcrit/blob/main/mcrit/config/MinHashConfig.py#L10
# Length in number of Shingles of which a minhash consists
# this value represents the length of sha256sum hash truncated
MINHASH_SIGNATURE_LENGTH: int = 64
# Number of bits per signature element (1-32 bits)
MINHASH_SIGNATURE_BITS: int = 8


class TokenKind(Enum):
    LLIL = "llil"
    TYPED_LLIL = "typed_llil"
    MLIL = "mlil"
    TYPED_MLIL = "typed_mlil"


class MinHasher:
    # stick to the default method
    MINHASH_STRATEGY_HASH_ALL = 1

    def __init__(self, seed, il_function, kind: TokenKind = TokenKind.LLIL):
        self._minhash_seeds = []
        self.il_func = il_function
        self.kind = kind
        self._minhash_permutation = []
        self._signature_segments = []
        self._initMinhashing(seed)

    def _initMinhashing(self, MINHASH_SEED=None):
        random.seed(MINHASH_SEED)
        # init sequence of seeds
        self._minhash_seeds = [
            random.randint(0, MinHashCustom.getHashMax()) for _ in range(MINHASH_SIGNATURE_LENGTH)
        ]

    def make_ngrams(self, tokens, n=3):
        """Take the ngrams of the IL we try to pass into the functions"""
        return [tuple(tokens[i:i+n]) for i in range(len(tokens) - n + 1)]

    def _extract_tokens(self):
        """Extract the IL tokens from the IL function, picking the right
        normalizer (LLIL/MLIL) and the right normalization mode
        (skeleton/typed) based on self.kind."""
        if self.kind in (TokenKind.LLIL, TokenKind.TYPED_LLIL):
            normalizer = LowLevelNormalization()
        elif self.kind in (TokenKind.MLIL, TokenKind.TYPED_MLIL):
            normalizer = MediumLevelNormalization()
        else:
            raise ValueError(f"Unsupported token kind: {self.kind}")

        # typed variants include operand type info, skeleton variants don't
        if self.kind in (TokenKind.TYPED_LLIL, TokenKind.TYPED_MLIL):
            normalize = normalizer.normalize_instr_with_operands
        else:
            normalize = normalizer.normalize_instruction_all_levels

        instructions = []
        for basic_block in self.il_func.basic_blocks:
            for il in basic_block:
                instructions.append(normalize(il))

        return instructions

    def calculateMinHash(self):
        """Calculate hash function every time, then take minimum shingle per shingler"""
        minhash_result = MinHashCustom(minhash_bits=MINHASH_SIGNATURE_BITS)
        minhash_signature = []

        tokens = self._extract_tokens()
        shingles = self.make_ngrams(tokens, n=3)

        # Functions with fewer than 3 IL instructions can't produce n-grams
        # Return empty minhash for such small functions (thunks, stubs, etc.)
        # Triggered by 39d8ad95b0323c37bd3134ab93ac4af44c66a1a8443a41c1ac02cec19bb2816a
        if not shingles:
            return []

        # Generate the MinHash
        for seed in self._minhash_seeds:
            hashed_shingles = [
                self.shingle_hash(shingle, seed) for shingle in shingles
            ]
            min_value = min(hashed_shingles)

            if MINHASH_SIGNATURE_BITS < 32:
                min_value %= (2 ** MINHASH_SIGNATURE_BITS)

            minhash_signature.append(min_value)

        minhash_result.setMinHash(minhash_signature)
        return minhash_result.getMinHashInt()

    def shingle_hash(self, shingle, hash_seed=0):
        """Produce a single 32bit UINT hash for a given shingle"""
        return MinHashCustom.hashData(shingle, hash_seed)