Wei Guo

39 papers Journal 23Unranked 16
YearRankTypeTitle / Venue / Authors
2026 J jnl
Biomed. Signal Process. Control.
Wei Guo, Shengjian Wang, Guodong Zhang, Chi Dong, Shuailin You, Yundi Cui, Wenyan Jiang
2025 J jnl
J. Imaging Inform. Medicine
Guodong Zhang, Wenwen Gu, Tingyu Liang, Yanlin Li, Wei Guo, Zhaoxuan Gong, Ronghui Ju
2025 J jnl
Comput. Secur.
Hanxun Zhou, Zhihui Liu, Yufeng Hu, Shuo Zhang, Longyu Kang, Yong Feng, Yan Wang, Wei Guo, Cliff C. Zou
2025 J jnl
Int. J. Imaging Syst. Technol.
Guodong Zhang, He Li, Wanying Xie, Bin Yang, Zhaoxuan Gong, Wei Guo, Ronghui Ju
2025 J jnl
Biomed. Signal Process. Control.
Wei Guo, Man Yan, Zhaoxuan Gong, Guodong Zhang, Hanxun Zhou
2025 J jnl
Medical Biol. Eng. Comput.
Wei Guo, Jiayi Bo, Shilin Chen, Zhaoxuan Gong, Guodong Zhang, Hanxun Zhou, Zekun Wang, Peng Zhao, Wenyan Jiang
2025 J jnl
J. Imaging Inform. Medicine
Wenwen Gu, Guodong Zhang, Ronghui Ju, Suran Wang, Yanlin Li, Tingyu Liang, Wei Guo, Zhaoxuan Gong
2024 J jnl
Int. J. Imaging Syst. Technol.
Wei Guo, Xiaomin Li, Zhaoxuan Gong, Guodong Zhang, Xiran Jiang
2024 J jnl
Int. J. Imaging Syst. Technol.
Guodong Zhang, Tingyu Liang, Yanlin Li, Kaichao Liang, Zhaoxuan Gong, Wei Guo, Zhuoning Zhang, Ronghui Ju
2023 J jnl
Int. J. Inf. Sec.
Hanxun Zhou, Longyu Kang, Hong Pan, Wei Guo, Yong Feng
2023 J jnl
Int. J. Imaging Syst. Technol.
Wei Guo, Shijie Liu, Zhaoxuan Gong, Guodong Zhang, Xiran Jiang
2023 J jnl
Biomed. Signal Process. Control.
Tao Jiang, Xinyan Sun, Yue Dong, Wei Guo, Hongbo Wang, Zhibin Yue, Yahong Luo, Xiran Jiang
2023 J jnl
Biomed. Signal Process. Control.
Wei Guo, Shijie Liu, Zhaoxuan Gong, Guodong Zhang, Xiran Jiang
2022 J jnl
Int. J. Intell. Syst.
Wenle Wang, Wei Zhou, Jianhang Ji, Jikun Yang, Wei Guo, Zhaoxuan Gong, Yugen Yi, Jianzhong Wang
2022 J jnl
Comput. Biol. Medicine
Chongwei Wu, Langyuan Fu, Zhiying Tian, Jiao Liu, Jiangdian Song, Wei Guo, Yu Zhao, Duo Zheng, Ying Jin, Dongxu Yi, Xiran Jiang
2021 J jnl
IEEE Access
Wei Guo, Hanxun Zhou, Zhaoxuan Gong, Guodong Zhang
2021 J jnl
Comput. Methods Programs Biomed.
Wei Guo, Guodong Zhang, Zhaoxuan Gong, Qiang Li
2021 J jnl
Wirel. Commun. Mob. Comput.
Wei Zhou, Zhaoxuan Gong, Wei Guo, Nan Han, Shaojie Qiao
2020 J jnl
J. Medical Imaging Health Informatics
Zhaoxuan Gong, Wei Guo, Wei Zhou, Dazhe Zhao, Wenjun Tan, Guodong Zhang
2020 J jnl
J. Medical Imaging Health Informatics
Zhaoxuan Gong, Wei Guo, Wei Zhou, Dazhe Zhao, Wenjun Tan, Guodong Zhang
2020 J jnl
IEEE Access
Hanxun Zhou, Yeshuai Hu, Xinlin Yang, Hong Pan, Wei Guo, Cliff C. Zou
2020 J jnl
IEEE Access
Hanxun Zhou, Xinlin Yang, Hong Pan, Wei Guo
2020 conf
ISICDM
Guodong Zhang, Zhaoxuan Gong, Rui Xu, Wei Guo, Dazhe Zhao, Wenjun Tan, Wei Zhou
2020 conf
ISICDM
Zhaoxuan Gong, Zhi Liu, Wei Guo, Dazhe Zhao, Chong He, Yu Liu, Guodong Zhang
2020 conf
ISICDM
Guodong Zhang, Wei Guo, Lingyu Kong, Zhaoxuan Gong, Dazhe Zhao, Chong He, Cui Guo
2019 conf
ISICDM
Zhaoxuan Gong, Zhenyu Zhu, Guodong Zhang, Dazhe Zhao, Wei Guo
2019 conf
ISICDM
Wei Guo, AdevianFairuz Pratama, Zhaoxuan Gong, Wei Zhou, Dazhe Zhao, Guodong Zhang
2018 conf
ELM
Dayu Jia, Junchang Xin, Zhiqiong Wang, Wei Guo, Guoren Wang
2018 conf
ICIGP
Wei Guo, Qiang Chen, Zhaoxuan Gong, Jing Bi, Yoohwan Kim, Guodong Zhang
2018 conf
APWeb/WAIM (2)
Dayu Jia, Junchang Xin, Zhiqiong Wang, Wei Guo, Guoren Wang
2018 conf
ISICDM
Guodong Zhang, Lingchuang Kong, Wei Guo, Jia Guo, Zhenyu Zhu, Yoohwan Kim, Zhaoxuan Gong
2018 conf
ISICDM
Zhaoxuan Gong, Wei Guo, Jia Guo, Zhenyu Zhu, Yoohwan Kim, Guodong Zhang
2017 J jnl
Telecommun. Syst.
Hanxun Zhou, Wei Guo
2016 conf
Computer-Aided Diagnosis
Wei Guo, Qiang Chen, Hanxun Zhou, Guodong Zhang, Lin Cong, Qiang Li
2016 conf
Biomedical Applications in Molecular, Structural, and Functional Imaging
Lin Cong, Wei Guo, Qiang Li
2016 conf
IGTA
Guodong Zhang, Ying Shao, Yoohwan Kim, Wei Guo
2014 conf
IGTA
Guodong Zhang, Lin Cong, Liu Wang, Wei Guo
2012 conf
Computer-Aided Diagnosis
Wei Guo, Qiang Li, Sarah J. Boyce, H. Page McAdams, Junji Shiraishi, Kunio Doi, Ehsan Samei
2011 conf
Computer-Aided Diagnosis
Jorge Juan Suárez-Cuenca, Wei Guo, Qiang Li
tests/unit/test_decompile_decompiler.py
← Index tests/unit/test_decompile_decompiler.py python
"""Unit tests (mocked BN) for bninja/decompiler.py — BinaryNinjaDecompiler."""
import sys
import json
import time
import pytest
from unittest.mock import MagicMock, patch, mock_open

from tests.unit.conftest_binja_stubs import (
    install_binja_stubs,
    MockFunction,
    MockBasicBlock,
    MockDisassemblyLine,
    MockToken,
    MockSymbol,
    MockBinaryView,
    MockEdge,
    SymbolType,
    InstructionTextTokenType,
    BranchType,
)

install_binja_stubs()

from redb.extractors.decompiler.bninja.decompiler import (
    BinaryNinjaDecompiler,
    is_lib_or_thunk,
)
from redb.extractors.decompiler.bninja.function_type import FunctionType


# ============================================================================
# 10a. BinaryNinjaDecompiler
# ============================================================================


class TestBinaryNinjaDecompilerLogError:
    def _make_decompiler(self):
        with patch.object(BinaryNinjaDecompiler, "__init__", lambda self, *a, **kw: None):
            d = BinaryNinjaDecompiler.__new__(BinaryNinjaDecompiler)
            d.log = MagicMock()
            d.errors = []
            d.filepath = "/fake/binary"
            d.bv = None
            d.analysis_results = None
            d.exporters = []
            d.index_prefix = None
            d.filetype = None
            d.goresym = None
            d.BNINJA_TIMEOUT = 60
            return d

    def test_log_error_appends(self):
        d = self._make_decompiler()
        d.log_error("test error", "func1", 0x1000, Exception("boom"), "extract")
        assert len(d.errors) == 1

    def test_log_error_schema(self):
        d = self._make_decompiler()
        d.log_error("test error", "func1", 0x1000, Exception("boom"), "extract")
        error = d.errors[0]
        expected_keys = [
            "function_name",
            "function_address",
            "error_location",
            "error_message",
            "error_details",
            "error_type",
            "timestamp",
        ]
        for key in expected_keys:
            assert key in error, f"Missing key: {key}"


class TestBinaryNinjaDecompilerIsTooFewBlocks:
    def _make_decompiler(self):
        with patch.object(BinaryNinjaDecompiler, "__init__", lambda self, *a, **kw: None):
            d = BinaryNinjaDecompiler.__new__(BinaryNinjaDecompiler)
            d.log = MagicMock()
            d.errors = []
            d.MIN_FUNCTION_SIZE = 10
            return d

    def test_is_too_few_blocks_none(self):
        d = self._make_decompiler()
        func = MagicMock()
        func.basic_blocks = None
        assert d.is_too_few_blocks(func) is False

    def test_is_too_few_blocks_empty(self):
        # Empty basic_blocks now returns True because Binja creates function
        # stubs with empty blocks before analysis completes — we no longer
        # skip these so they get filtered downstream instead.
        d = self._make_decompiler()
        func = MagicMock()
        func.basic_blocks = []
        assert d.is_too_few_blocks(func) is True

    def test_is_too_few_blocks_small_single(self):
        d = self._make_decompiler()
        block = MagicMock()
        block.disassembly_text = [MagicMock() for _ in range(5)]  # < 10
        func = MagicMock()
        func.basic_blocks = [block]
        assert d.is_too_few_blocks(func) is False

    def test_is_too_few_blocks_large_single(self):
        d = self._make_decompiler()
        block = MagicMock()
        block.disassembly_text = [MagicMock() for _ in range(15)]  # >= 10
        func = MagicMock()
        func.basic_blocks = [block]
        assert d.is_too_few_blocks(func) is True

    def test_is_too_few_blocks_multiple(self):
        d = self._make_decompiler()
        func = MagicMock()
        func.basic_blocks = [MagicMock(), MagicMock()]
        assert d.is_too_few_blocks(func) is True


class TestIsLibOrThunk:
    def test_is_lib_or_thunk_user(self):
        func = MagicMock()
        func.symbol.type = SymbolType.FunctionSymbol
        func.is_thunk = False
        assert is_lib_or_thunk(func) is True  # NOT filtered

    def test_is_lib_or_thunk_thunk(self):
        func = MagicMock()
        func.symbol.type = SymbolType.FunctionSymbol
        func.is_thunk = True
        assert is_lib_or_thunk(func) is False  # Filtered out

    def test_is_lib_or_thunk_external(self):
        func = MagicMock()
        func.symbol.type = SymbolType.ImportedFunctionSymbol
        func.is_thunk = False
        assert is_lib_or_thunk(func) is False  # Filtered out


class TestBinaryNinjaDecompilerExtract:
    def _make_decompiler(self):
        with patch.object(BinaryNinjaDecompiler, "__init__", lambda self, *a, **kw: None):
            d = BinaryNinjaDecompiler.__new__(BinaryNinjaDecompiler)
            d.log = MagicMock()
            d.errors = []
            d.filepath = "/fake/binary"
            d.bv = MagicMock()
            d.analysis_results = None
            d.exporters = []
            d.index_prefix = None
            d.filetype = None
            d.goresym = None
            d.BNINJA_TIMEOUT = 60
            d.arch = MagicMock()
            return d

    def test_extract_success(self):
        d = self._make_decompiler()
        mock_results = {
            "decompiled": [{"test": True}],
            "disassembled": [],
            "cfg": [],
            "llil": [],
            "errors": [],
            "strings": [],
            "mlil": [],
        }
        with patch.object(d, "analyze_binary", return_value=mock_results):
            result = d.extract()
            assert result is True
            assert d.analysis_results == mock_results

    def test_extract_failure(self):
        d = self._make_decompiler()
        with patch.object(d, "analyze_binary", return_value=None):
            result = d.extract()
            assert result is False

    def test_tag(self):
        d = self._make_decompiler()
        assert d.tag() == "DECOMPILED"


class TestBinaryNinjaDecompilerAnalyzeBinary:
    def _make_decompiler(self):
        with patch.object(BinaryNinjaDecompiler, "__init__", lambda self, *a, **kw: None):
            d = BinaryNinjaDecompiler.__new__(BinaryNinjaDecompiler)
            d.log = MagicMock()
            d.errors = []
            d.filepath = "/fake/binary"
            d.analysis_results = None
            d.exporters = []
            d.index_prefix = None
            d.filetype = None
            d.goresym = None
            d.BNINJA_TIMEOUT = 60
            d.arch = MagicMock()
            d.MIN_FUNCTION_SIZE = 10
            return d

    def test_analyze_binary_links_hlil_disasm(self):
        """Bi-directional hash linkage between decompiled and disassembled."""
        d = self._make_decompiler()
        d.bv = MagicMock()
        d.bv.functions = []
        # Mock methods to return controlled data
        with patch.object(d, "extract_hlil") as mock_hlil, \
             patch.object(d, "extract_disasm") as mock_disasm, \
             patch.object(d, "extract_cfg", return_value=None), \
             patch.object(d, "extract_lowlevel", return_value=None):

            mock_hlil.return_value = {
                "decompiled_function_hash": "HLIL_HASH",
                "decompiled_function_name": "test",
                "decompiled_function": "code",
            }
            mock_disasm.return_value = {
                "disassembled_function_hash": "DISASM_HASH",
                "disassembled_function_no_addresses": "asm",
            }

            # Manually feed one function
            mock_func = MagicMock()
            mock_func.symbol.type = SymbolType.FunctionSymbol
            mock_func.is_thunk = False
            mock_func.basic_blocks = [MagicMock(), MagicMock()]
            d.bv.functions = [mock_func]

            results = d.analyze_binary()
            if results and results["decompiled"]:
                hlil_r = results["decompiled"][0]
                disasm_r = results["disassembled"][0]
                assert hlil_r["disassembled_function_hash"] == "DISASM_HASH"
                assert disasm_r["decompiled_function_hash"] == "HLIL_HASH"

    def test_analyze_binary_links_llil_disasm(self):
        """Bi-directional linkage between LLIL and disassembly."""
        d = self._make_decompiler()
        d.bv = MagicMock()

        with patch.object(d, "extract_hlil", return_value=None), \
             patch.object(d, "extract_disasm") as mock_disasm, \
             patch.object(d, "extract_cfg", return_value=None), \
             patch.object(d, "extract_lowlevel") as mock_llil:

            mock_disasm.return_value = {
                "disassembled_function_hash": "DISASM_HASH",
                "disassembled_function_no_addresses": "asm",
            }
            mock_llil.return_value = {
                "sha256_llil": "LLIL_HASH",
                "tlsh_llil": "tlsh_val",
            }

            mock_func = MagicMock()
            mock_func.symbol.type = SymbolType.FunctionSymbol
            mock_func.is_thunk = False
            mock_func.basic_blocks = [MagicMock(), MagicMock()]
            d.bv.functions = [mock_func]

            results = d.analyze_binary()
            if results and results["llil"]:
                llil_r = results["llil"][0]
                assert llil_r["disassembled_function_hash"] == "DISASM_HASH"

    def test_analyze_binary_links_cfg_disasm(self):
        """CFG gets disassembled_function_hash."""
        d = self._make_decompiler()
        d.bv = MagicMock()

        with patch.object(d, "extract_hlil", return_value=None), \
             patch.object(d, "extract_disasm") as mock_disasm, \
             patch.object(d, "extract_cfg") as mock_cfg, \
             patch.object(d, "extract_lowlevel", return_value=None):

            mock_disasm.return_value = {
                "disassembled_function_hash": "DISASM_HASH",
                "disassembled_function_no_addresses": "asm",
            }
            mock_cfg.return_value = {
                "function_address": 0x1000,
                "cyclomatic_complexity": 3,
            }

            mock_func = MagicMock()
            mock_func.symbol.type = SymbolType.FunctionSymbol
            mock_func.is_thunk = False
            mock_func.basic_blocks = [MagicMock(), MagicMock()]
            d.bv.functions = [mock_func]

            results = d.analyze_binary()
            if results and results["cfg"]:
                cfg_r = results["cfg"][0]
                assert cfg_r["disassembled_function_hash"] == "DISASM_HASH"

    def test_analyze_binary_sets_cyclomatic(self):
        """cyclomatic_complexity set on disasm from CFG."""
        d = self._make_decompiler()
        d.bv = MagicMock()

        with patch.object(d, "extract_hlil", return_value=None), \
             patch.object(d, "extract_disasm") as mock_disasm, \
             patch.object(d, "extract_cfg") as mock_cfg, \
             patch.object(d, "extract_lowlevel", return_value=None):

            mock_disasm.return_value = {
                "disassembled_function_hash": "HASH",
                "disassembled_function_no_addresses": "asm",
            }
            mock_cfg.return_value = {
                "function_address": 0x1000,
                "cyclomatic_complexity": 7,
            }

            mock_func = MagicMock()
            mock_func.symbol.type = SymbolType.FunctionSymbol
            mock_func.is_thunk = False
            mock_func.basic_blocks = [MagicMock(), MagicMock()]
            d.bv.functions = [mock_func]

            results = d.analyze_binary()
            if results and results["disassembled"]:
                disasm_r = results["disassembled"][0]
                assert disasm_r.get("cyclomatic_complexity") == 7


class TestApplyGoReSym:
    def _make_decompiler(self):
        with patch.object(BinaryNinjaDecompiler, "__init__", lambda self, *a, **kw: None):
            d = BinaryNinjaDecompiler.__new__(BinaryNinjaDecompiler)
            d.log = MagicMock()
            d.errors = []
            d.bv = MagicMock()
            return d

    def test_apply_goresym_user_functions(self):
        d = self._make_decompiler()
        d.goresym = "/tmp/goresym.json"
        data = {
            "UserFunctions": [{"Start": 0x1000, "FullName": "main.main"}],
        }
        with patch("builtins.open", mock_open(read_data=json.dumps(data))):
            d._BinaryNinjaDecompiler__apply_goresym()
            d.bv.define_user_symbol.assert_called()

    def test_apply_goresym_std_functions(self):
        d = self._make_decompiler()
        d.goresym = "/tmp/goresym.json"
        data = {
            "StdFunctions": [{"Start": 0x2000, "FullName": "runtime.main"}],
        }
        with patch("builtins.open", mock_open(read_data=json.dumps(data))):
            d._BinaryNinjaDecompiler__apply_goresym()
            d.bv.define_user_symbol.assert_called()

    def test_apply_goresym_invalid_json(self):
        d = self._make_decompiler()
        d.goresym = "/tmp/goresym.json"
        with patch("builtins.open", mock_open(read_data="not json {")):
            d._BinaryNinjaDecompiler__apply_goresym()
            # Should log error but not crash
            d.log.log_error if hasattr(d.log, 'log_error') else None
            # Just verify no exception raised