James K. Russell

14 papers Journal 2Unranked 12
YearRankTypeTitle / Venue / Authors
2023 J jnl
Comput. Methods Programs Biomed.
Sofía Ruiz de Gauna, José Julio Gutiérrez, Camilo Leonardo Sandoval, James K. Russell, Izaskun Azcarate, Jose Antonio Urigüen, Digna M. González-Otero, Mohamud Ramzan Daya
2020 J jnl
Remote. Sens.
Daniele Giordano, James K. Russell, Diego González-García, Danilo Bersani, Donald B. Dingwell, Ciro Del Negro
2018 conf
CinC
Mikel Leturiondo, José Julio Gutiérrez, Sofía Ruiz de Gauna, Jesús Ruiz, Luis A. Leturiondo, James K. Russell, Mohamud Daya
2017 conf
CinC
Sofía Ruiz de Gauna, Digna M. González-Otero, James K. Russell, Jesús Ruiz, Sara Pelayo, Purificación Sáiz
2017 conf
CinC
Mikel Leturiondo, Jesús Ruiz, J. Julio Gutiérrez, Luis A. Leturiondo, Jose F. Veintemillas, James K. Russell, Mohamud Daya
2016 conf
CinC
Digna M. González-Otero, Jesús Ruiz, Sofía Ruiz de Gauna, James K. Russell, Luis A. Leturiondo, Purificación Sáiz
2016 conf
CinC
Sofía Ruiz de Gauna, Digna M. González-Otero, Jesús Ruiz, Stefano De Nigris, Purificación Sáiz, José Julio Gutiérrez, James K. Russell, Elena De Momi
2016 conf
CinC
James K. Russell, Dana M. Zive, Mohamud Daya
2016 conf
CinC
Jesús Ruiz, Sofía Ruiz de Gauna, Digna M. González-Otero, Mohamud Daya, James K. Russell, José Julio Gutiérrez, Mikel Leturiondo
2016 conf
EMBC
Kiran H. J. Dellimore, Ralph W. C. G. R. Wijshoff, Christoph Haarburger, Vincent Aarts, Rene Derkx, Jakob van de Laar, Krishnakant Nammi, James K. Russell, Pia Hubner, Fritz Sterz, Jens Muehlsteff
2015 conf
CinC
Andoni Elola, Beatriz Chicote, Elisabete Aramendi, Erik Alonso, Unai Irusta, Mohamud Daya, James K. Russell
2014 conf
CinC
Digna M. González-Otero, Erik Alonso, Jesús Ruiz, Sofía Ruiz de Gauna, Elisabete Aramendi, Unai Ayala, James K. Russell, Mohamud Daya
2014 conf
CinC
Erik Alonso, Elisabete Aramendi, Digna M. González-Otero, Unai Ayala, Mohamud Daya, James K. Russell
2013 conf
CinC
Erik Alonso, Digna M. González-Otero, Elisabete Aramendi, Sofía Ruiz de Gauna, Jesús Ruiz, Unai Ayala, James K. Russell
tests/unit/test_decompile_strings.py
← Index tests/unit/test_decompile_strings.py python
"""Unit tests for bninja/analysis/strings.py — StringAnalysis."""
import pytest
import math
from unittest.mock import MagicMock


# StringAnalysis has no binaryninja imports, just collections and math
from redb.extractors.decompiler.bninja.analysis.strings import StringAnalysis


# ============================================================================
# Helper mocks
# ============================================================================

class MockStringEntry:
    """Mock for a Binary Ninja string reference."""
    def __init__(self, value, raw=None, start=0, length=0, type_name="Utf8String"):
        self.value = value
        self.raw = raw if raw is not None else (value.encode("utf-8") if isinstance(value, str) else value)
        self.start = start
        self.length = length if length else len(self.raw)
        self.type = MagicMock()
        self.type.name = type_name


class MockBinaryView:
    """Mock binary view with a strings list."""
    def __init__(self, strings=None):
        self.strings = strings or []


# ============================================================================
# 6a. StringAnalysis
# ============================================================================


class TestStringAnalysisEntropy:
    def setup_method(self):
        self.sa = StringAnalysis(bv=MockBinaryView(), functions=[])

    def test_entropy_empty_string(self):
        assert self.sa.entropy("") == 0.0

    def test_entropy_single_char(self):
        assert self.sa.entropy("aaaa") == 0.0

    def test_entropy_uniform_distribution(self):
        # "abcd" -> 4 unique chars, each p=1/4, entropy = log2(4) = 2.0
        result = self.sa.entropy("abcd")
        assert result == pytest.approx(2.0)

    def test_entropy_binary_string(self):
        # "ab" -> 2 unique chars, each p=1/2, entropy = log2(2) = 1.0
        result = self.sa.entropy("ab")
        assert result == pytest.approx(1.0)


class TestStringAnalysisAnalyze:
    def test_analyze_deduplication(self):
        """Duplicate (string, encoding) pairs -> only first kept."""
        entries = [
            MockStringEntry("hello", start=100, type_name="Utf8String"),
            MockStringEntry("hello", start=200, type_name="Utf8String"),
        ]
        bv = MockBinaryView(strings=entries)
        sa = StringAnalysis(bv=bv, functions=[])
        result = sa.analyze()
        assert len(result) == 1
        assert result[0]["string_offset"] == 100

    def test_analyze_sorted_by_address(self):
        """First occurrence (lowest offset) is the one kept."""
        entries = [
            MockStringEntry("world", start=500, type_name="Utf8String"),
            MockStringEntry("world", start=100, type_name="Utf8String"),
        ]
        bv = MockBinaryView(strings=entries)
        sa = StringAnalysis(bv=bv, functions=[])
        result = sa.analyze()
        assert len(result) == 1
        # The analyze() sorts by start, so 100 comes first
        assert result[0]["string_offset"] == 100

    def test_analyze_empty_bv(self):
        bv = MockBinaryView(strings=[])
        sa = StringAnalysis(bv=bv, functions=[])
        result = sa.analyze()
        assert result == []

    def test_analyze_output_schema(self):
        entries = [MockStringEntry("test_string", start=0, type_name="Utf8String")]
        bv = MockBinaryView(strings=entries)
        sa = StringAnalysis(bv=bv, functions=[])
        result = sa.analyze()
        assert len(result) == 1
        r = result[0]
        required_keys = [
            "string",
            "string_raw",
            "string_encoding",
            "string_offset",
            "string_length",
            "string_raw_length",
            "string_entropy",
        ]
        for key in required_keys:
            assert key in r, f"Missing key: {key}"