Naoki Kitamura

36 papers A* 2A 3B 6Misc 1Journal 21Unranked 3
YearRankTypeTitle / Venue / Authors
2026 J jnl
Theor. Comput. Sci.
Hiroki Hatano, Naoki Kitamura, Taisuke Izumi, Takehiro Ito, Toshimitsu Masuzawa
2025 J jnl
Theor. Comput. Sci.
Po Yuan Wang, Naoki Kitamura, Taisuke Izumi, Toshimitsu Masuzawa
2025 B conf
SIROCCO
Yuki Kawashima, Naoki Kitamura, Taisuke Izumi, Toshimitsu Masuzawa
2025 J jnl
CoRR
Taisuke Izumi, Naoki Kitamura, Yutaro Yamaguchi
2025 B conf
WALCOM
Hiroki Hatano, Naoki Kitamura, Taisuke Izumi, Takehiro Ito, Toshimitsu Masuzawa
2025 J jnl
Comput. J.
Masahiro Shibata, Naoki Kitamura, Ryota Eguchi, Yuichi Sudo, Junya Nakamura, Yonghwan Kim
2025 J jnl
CoRR
Naoki Kitamura, Yuichi Sudo, Koichi Wada
2025 B conf
OPODIS
Masahiro Shibata, Naoki Kitamura, Ryota Eguchi, Yuichi Sudo, Junya Nakamura, Yonghwan Kim, Yoshiaki Katayama, Toshimitsu Masuzawa, Quentin Bramas, Sébastien Tixeuil
2024 A conf
ESA
Kaito Harada, Naoki Kitamura, Taisuke Izumi, Toshimitsu Masuzawa
2024 A* conf
SODA
Taisuke Izumi, Naoki Kitamura, Yutaro Yamaguchi
2024 J jnl
CoRR
Kaito Harada, Naoki Kitamura, Taisuke Izumi, Toshimitsu Masuzawa
2024 B conf
OPODIS
Fukuhito Ooshita, Naoki Kitamura, Ryota Eguchi, Michiko Inoue, Hirotsugu Kakugawa, Sayaka Kamei, Masahiro Shibata, Yuichi Sudo
2024 J jnl
CoRR
Hiroki Hatano, Naoki Kitamura, Taisuke Izumi, Takehiro Ito, Toshimitsu Masuzawa
2023 J jnl
CoRR
Taisuke Izumi, Naoki Kitamura, Yutaro Yamaguchi
2023 J jnl
IEICE Trans. Inf. Syst.
Rongcheng Dong, Taisuke Izumi, Naoki Kitamura, Yuichi Sudo, Toshimitsu Masuzawa
2023 conf
SAND
Masahiro Shibata, Naoki Kitamura, Ryota Eguchi, Yuichi Sudo, Junya Nakamura, Yonghwan Kim
2022 J jnl
IEICE Trans. Inf. Syst.
Naoki Kitamura, Taisuke Izumi
2022 B conf
OPODIS
Taichi Inoue, Naoki Kitamura, Taisuke Izumi, Toshimitsu Masuzawa
2022 J jnl
CoRR
Taichi Inoue, Naoki Kitamura, Taisuke Izumi, Toshimitsu Masuzawa
2022 J jnl
CoRR
Taisuke Izumi, Kazuki Kakizawa, Yuya Kawabata, Naoki Kitamura, Toshimitsu Masuzawa
2022 J jnl
IEICE Trans. Inf. Syst.
Ryota Eguchi, Naoki Kitamura, Taisuke Izumi
2022 B conf
SPAA
Taisuke Izumi, Naoki Kitamura, Takamasa Naruse, Gregory Schwartzman
2022 J jnl
CoRR
Taisuke Izumi, Naoki Kitamura, Takamasa Naruse, Gregory Schwartzman
2021 J jnl
CoRR
Naoki Kitamura, Taisuke Izumi
2021 J jnl
CoRR
Ryota Eguchi, Naoki Kitamura, Taisuke Izumi
2021 J jnl
Distributed Comput.
Naoki Kitamura, Hirotaka Kitagawa, Yota Otachi, Taisuke Izumi
2020 A conf
ICDCS
Ryota Eguchi, Naoki Kitamura, Taisuke Izumi
2020 J jnl
Theor. Comput. Sci.
Naoki Kitamura, Yuya Kawabata, Taisuke Izumi
2019 J jnl
Int. J. Netw. Comput.
Hiroto Yasumi, Naoki Kitamura, Fukuhito Ooshita, Taisuke Izumi, Michiko Inoue
2019 A conf
DISC
Naoki Kitamura, Hirotaka Kitagawa, Yota Otachi, Taisuke Izumi
2019 J jnl
CoRR
Naoki Kitamura, Hirotaka Kitagawa, Yota Otachi, Taisuke Izumi
2018 conf
IPDPS Workshops
Hiroto Yasumi, Naoki Kitamura, Fukuhito Ooshita, Taisuke Izumi, Michiko Inoue
2018 A* conf
PODC
Naoki Kitamura, Kazuki Kakizawa, Yuya Kawabata, Taisuke Izumi
2018 J jnl
ICGA J.
Kiminori Matsuzaki, Naoki Kitamura
2018 Misc conf
FUN
Naoki Kitamura, Yuya Kawabata, Taisuke Izumi
2015 conf
ECOC
Morio Takahashi, Takashi Matsumoto, Shinya Watanabe, Kazuhiro Shiba, Taro Kaneko, Mamoru Oguro, Tadayuki Chikuma, Naoki Kitamura, Hiroyuki Yamazaki
tests/unit/test_decompile_similarity.py
← Index tests/unit/test_decompile_similarity.py python
"""Unit tests for similarity modules:
- bninja/similarity/minhashcustom.py
- bninja/similarity/minhasher.py
"""
import numpy as np
import pytest

from redb.extractors.decompiler.bninja.similarity.minhashcustom import MinHashCustom
from redb.extractors.decompiler.bninja.analysis.low_level_normalization import LowLevelNormalization


# ============================================================================
# 2a. MinHashCustom
# ============================================================================

class TestMinHashCustomInit:
    def test_init_empty(self):
        mh = MinHashCustom()
        assert not mh.hasMinHash()
        assert mh.minhash == b""
        assert mh.minhash_int == []

    def test_init_from_signature(self):
        sig = [10, 20, 30, 40]
        mh = MinHashCustom(minhash_signature=sig)
        assert mh.hasMinHash()
        assert mh.minhash_int == sig

    def test_init_from_bytes_uint32(self):
        """Verify round-trip: ints -> bytes -> MinHashCustom -> ints."""
        sig = [100, 200, 300]
        packed = np.array(sig, dtype=np.uint32).tobytes()
        # np.frombuffer returns numpy scalars; setMinHash does % 2**32 which
        # overflows numpy uint32, so verify the raw bytes round-trip instead.
        raw_arr = np.frombuffer(packed, dtype=np.uint32)
        assert list(raw_arr) == sig

    def test_init_from_bytes_uint8(self):
        """Verify round-trip: ints -> bytes -> back."""
        sig = [10, 20, 30]
        packed = np.array(sig, dtype=np.uint8).tobytes()
        raw_arr = np.frombuffer(packed, dtype=np.uint8)
        assert list(raw_arr) == sig

    def test_init_both_raises(self):
        sig = [1, 2, 3]
        packed = np.array(sig, dtype=np.uint32).tobytes()
        with pytest.raises(ValueError, match="only one"):
            MinHashCustom(minhash_bytes=packed, minhash_signature=sig)


class TestMinHashCustomSetGet:
    def test_set_and_get_minhash(self):
        mh = MinHashCustom()
        sig = [5, 10, 15]
        mh.setMinHash(sig)
        raw = mh.getMinHash()
        assert raw == np.array(sig, dtype=np.uint32).tobytes()
        assert mh.getMinHashInt() == sig

    def test_minhash_int_truncation(self):
        mh = MinHashCustom(minhash_bits=8)
        # Values > 256 should be truncated mod 2^8
        mh.setMinHash([300, 500, 256])
        for val in mh.minhash_int:
            assert 0 <= val < 256


class TestMinHashCustomHashData:
    def test_hash_data_string(self):
        result = MinHashCustom.hashData("hello", 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_bytes(self):
        result = MinHashCustom.hashData(b"bytes", 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_list(self):
        result = MinHashCustom.hashData([1, 2, 3], 42)
        assert isinstance(result, int)
        assert 0 <= result <= 0xFFFFFFFF

    def test_hash_data_unsupported_type(self):
        with pytest.raises(NotImplementedError, match="Type not supported"):
            MinHashCustom.hashData(123, 42)

    def test_hash_data_deterministic(self):
        assert MinHashCustom.hashData("test", 7) == MinHashCustom.hashData("test", 7)


class TestMinHashCustomScore:
    def test_score_identical(self):
        sig = [1, 2, 3, 4, 5]
        mh1 = MinHashCustom(minhash_signature=sig)
        mh2 = MinHashCustom(minhash_signature=sig)
        score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert score == 100.0

    def test_score_different(self):
        mh1 = MinHashCustom(minhash_signature=[1, 2, 3, 4, 5])
        mh2 = MinHashCustom(minhash_signature=[6, 7, 8, 9, 10])
        score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert score < 100.0

    def test_score_against(self):
        sig1 = [1, 2, 3, 4, 5]
        sig2 = [1, 2, 99, 4, 5]
        mh1 = MinHashCustom(minhash_signature=sig1)
        mh2 = MinHashCustom(minhash_signature=sig2)
        instance_score = mh1.scoreAgainst(mh2)
        static_score = MinHashCustom.calculateMinHashScore(
            mh1.getMinHash(), mh2.getMinHash()
        )
        assert instance_score == static_score


class TestMinHashCustomBitModes:
    def test_8bit_mode(self):
        mh = MinHashCustom(minhash_bits=8)
        mh.setMinHash([10, 20, 30])
        raw = mh.getMinHash()
        arr = np.frombuffer(raw, dtype=np.uint8)
        assert list(arr) == [10, 20, 30]

    def test_32bit_mode(self):
        mh = MinHashCustom(minhash_bits=32)
        mh.setMinHash([10, 20, 30])
        raw = mh.getMinHash()
        arr = np.frombuffer(raw, dtype=np.uint32)
        assert list(arr) == [10, 20, 30]


# ============================================================================
# 2b. MinHasher
# ============================================================================


class MockILNode:
    """Mock IL node with operation and operands for normalization."""
    def __init__(self, operation, operands=None):
        self.operation = operation
        self.operands = operands or []


class MockLLILBasicBlock:
    """Mock LLIL basic block that yields IL instructions."""
    def __init__(self, instructions):
        self._instructions = instructions

    def __iter__(self):
        return iter(self._instructions)


class MockLLILFunction:
    """Mock LLIL function with basic blocks."""
    def __init__(self, basic_blocks):
        self.basic_blocks = basic_blocks


# Import MinHasher after we know the module can handle the import
from redb.extractors.decompiler.bninja.similarity.minhasher import (
    MinHasher,
    MINHASH_SIGNATURE_LENGTH,
    MINHASH_SIGNATURE_BITS,
)


class TestMinHasherMakeNgrams:
    def setup_method(self):
        # Create a minimal minhasher with a mock LLIL function
        empty_func = MockLLILFunction([])
        self.hasher = MinHasher(seed=42, il_function=empty_func)

    def test_make_ngrams_basic(self):
        result = self.hasher.make_ngrams(["a", "b", "c", "d"], n=3)
        assert result == [("a", "b", "c"), ("b", "c", "d")]

    def test_make_ngrams_short_input(self):
        result = self.hasher.make_ngrams(["a", "b"], n=3)
        assert result == []

    def test_make_ngrams_exact_n(self):
        result = self.hasher.make_ngrams(["a", "b", "c"], n=3)
        assert result == [("a", "b", "c")]


class TestMinHasherCalculate:
    def _make_llil_function(self, num_instructions=10):
        """Create a mock LLIL function with enough instructions."""
        instructions = [
            MockILNode(operation=i % 20) for i in range(num_instructions)
        ]
        bb = MockLLILBasicBlock(instructions)
        return MockLLILFunction([bb])

    def test_calculate_minhash_empty_function(self):
        # Function with < 3 LLIL instructions -> empty list
        func = self._make_llil_function(num_instructions=2)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        assert result == []

    def test_calculate_minhash_deterministic(self):
        func = self._make_llil_function(num_instructions=20)
        h1 = MinHasher(seed=42, il_function=func)
        h2 = MinHasher(seed=42, il_function=func)
        assert h1.calculateMinHash() == h2.calculateMinHash()

    def test_calculate_minhash_length(self):
        func = self._make_llil_function(num_instructions=20)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        assert len(result) == MINHASH_SIGNATURE_LENGTH

    def test_calculate_minhash_value_range(self):
        func = self._make_llil_function(num_instructions=20)
        hasher = MinHasher(seed=42, il_function=func)
        result = hasher.calculateMinHash()
        for val in result:
            assert 0 <= val < 2 ** MINHASH_SIGNATURE_BITS

    def test_shingle_hash_deterministic(self):
        func = self._make_llil_function(num_instructions=5)
        hasher = MinHasher(seed=42, il_function=func)
        shingle = ([1, 2], [3, 4], [5, 6])
        assert hasher.shingle_hash(shingle, 99) == hasher.shingle_hash(shingle, 99)

    def test_seed_reproducibility(self):
        func = self._make_llil_function(num_instructions=20)
        h1 = MinHasher(seed=1, il_function=func)
        h2 = MinHasher(seed=2, il_function=func)
        r1 = h1.calculateMinHash()
        r2 = h2.calculateMinHash()
        # Different seeds should (very likely) produce different results
        assert r1 != r2