Xi Yang

72 papers B 2C 4Journal 55Unranked 11
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Internet Things J.
Xi Yang, Dahong Du, Ting Liu, Binggui Zhou, Shaodan Ma
2026 J jnl
IEEE Trans. Commun.
Ting Liu, Xi Yang, Xiaoming Wang, Ji Wang, Xingwang Li
2026 J jnl
IEEE J. Sel. Areas Commun.
Jiachen Tian, Yu Han, Zhengtao Jin, Xi Yang, Jie Yang, Wankai Tang, Xiao Li, Wenjin Wang, Shi Jin
2025 J jnl
IEEE Internet Things J.
Ting Liu, Hao Jiang, Xiaoming Wang, Xi Yang, Zhen Chen
2025 J jnl
IEEE Trans. Commun.
Jiajia Guo, Xi Yang, Chao-Kai Wen, Shi Jin, Geoffrey Ye Li
2025 J jnl
IEEE Trans. Wirel. Commun.
Binggui Zhou, Xi Yang, Shaodan Ma, Feifei Gao, Guanghua Yang
2025 J jnl
CoRR
Jiachen Tian, Yu Han, Zhengtao Jin, Xi Yang, Jie Yang, Wankai Tang, Xiao Li, Wenjin Wang, Shi Jin
2024 J jnl
IEEE Trans. Wirel. Commun.
Binggui Zhou, Xi Yang, Jintao Wang, Shaodan Ma, Feifei Gao, Guanghua Yang
2024 J jnl
IEEE Wirel. Commun. Lett.
Xi Yang, Fuqiang Zhu, Binggui Zhou, Ting Liu, Shaodan Ma
2024 J jnl
IEEE Trans. Wirel. Commun.
Jintao Wang, Chengzhi Ma, Shiqi Gong, Xi Yang, Shaodan Ma
2024 J jnl
CoRR
Jintao Wang, Chengzhi Ma, Shiqi Gong, Xi Yang, Shaodan Ma
2024 J jnl
CoRR
Binggui Zhou, Xi Yang, Shaodan Ma, Feifei Gao, Guanghua Yang
2024 J jnl
IEEE Trans. Wirel. Commun.
Binggui Zhou, Xi Yang, Shaodan Ma, Feifei Gao, Guanghua Yang
2024 J jnl
IEEE Trans. Wirel. Commun.
Chengzhi Ma, Jintao Wang, Xi Yang, Guanghua Yang, Wei Zhang, Shaodan Ma
2024 J jnl
IEEE Trans. Commun.
Chengzhi Ma, Xi Yang, Jintao Wang, Guanghua Yang, Wei Zhang, Shaodan Ma
2024 conf
VTC Spring
Kehui Li, Binggui Zhou, Jiajia Guo, Xi Yang, Qing Xue, Feifei Gao, Shaodan Ma
2023 J jnl
CoRR
Binggui Zhou, Xi Yang, Jintao Wang, Shaodan Ma, Feifei Gao, Guanghua Yang
2023 J jnl
IEEE Trans. Wirel. Commun.
Xi Yang, Shaodan Ma, Shi Jin
2023 J jnl
IEEE Commun. Lett.
Ting Liu, Hao Jiang, Xi Yang, Zhaohui Yang
2023 J jnl
IEEE Wirel. Commun.
Jie Yang, Chao-Kai Wen, Xi Yang, Jing Xu, Tao Du, Shi Jin
2023 J jnl
IEEE Commun. Lett.
Ting Liu, Hao Jiang, Zhen Chen, Hongming Zhang, Xi Yang, Feng Shu
2023 J jnl
CoRR
Binggui Zhou, Xi Yang, Shaodan Ma, Feifei Gao, Guanghua Yang
2023 J jnl
CoRR
Chengzhi Ma, Jintao Wang, Xi Yang, Guanghua Yang, Wei Zhang, Shaodan Ma
2023 J jnl
CoRR
Chengzhi Ma, Xi Yang, Jintao Wang, Guanghua Yang, Shaodan Ma
2023 J jnl
IEEE Trans. Commun.
Ting Liu, Xi Yang, Hao Jiang, Hongming Zhang, Zhen Chen
2022 J jnl
IEEE Trans. Veh. Technol.
Xianda Wu, Shaodan Ma, Xi Yang, Guanghua Yang
2022 J jnl
IEEE Internet Things J.
Xianda Wu, Xi Yang, Shaodan Ma, Binggui Zhou, Guanghua Yang
2022 J jnl
IEEE Wirel. Commun. Lett.
Chengzhi Ma, Huan Zhang, Xi Yang, Shaodan Ma
2022 J jnl
CoRR
Jie Yang, Chao-Kai Wen, Xi Yang, Jing Xu, Tao Du, Shi Jin
2022 J jnl
IEEE Trans. Signal Process.
Xi Yang, Chao-Kai Wen, Yu Han, Shi Jin, A. Lee Swindlehurst
2022 J jnl
IEEE Wirel. Commun. Lett.
Weiqiang Tan, Xi Yang, Shaodan Ma
2021 J jnl
CoRR
Xi Yang, Shi Jin, Geoffrey Ye Li, Xiao Li
2021 J jnl
IEEE Trans. Veh. Technol.
Xi Yang, Shi Jin, Geoffrey Ye Li, Xiao Li
2021 J jnl
CoRR
Jie Yang, Xi Yang, Chao-Kai Wen, Shi Jin
2021 J jnl
IEEE Trans. Commun.
Kaizhe Xu, Jun Zhang, Xi Yang, Shaodan Ma, Guanghua Yang
2020 J jnl
IEEE Trans. Signal Process.
Xi Yang, Chao-Kai Wen, Shi Jin, A. Lee Swindlehurst
2020 J jnl
CoRR
Jiajia Guo, Xi Yang, Chao-Kai Wen, Shi Jin, Geoffrey Ye Li
2020 J jnl
IEEE Trans. Veh. Technol.
Jie Yang, Shi Jin, Chao-Kai Wen, Xi Yang, Michail Matthaiou
2020 conf
SPAWC
Xi Yang, Chao-Kai Wen, Shi Jin, A. Lee Swindlehurst, Jing Zhang
2020 J jnl
CoRR
Xi Yang, Chao-Kai Wen, Shi Jin
2020 J jnl
IEEE J. Sel. Areas Commun.
Xi Yang, Chao-Kai Wen, Shi Jin
2020 conf
SPAWC
Jing Zhang, Hengtao He, Xi Yang, Chao-Kai Wen, Shi Jin, Xiaoli Ma
2020 J jnl
IEEE Trans. Veh. Technol.
Xi Yang, Fan Cao, Michail Matthaiou, Shi Jin
2020 B conf
GLOBECOM
Weicong Chen, Xi Yang, Shi Jin, Pingping Xu
2020 J jnl
CoRR
Weicong Chen, Xi Yang, Shi Jin, Pingping Xu
2020 J jnl
Digit. Commun. Networks
Weicong Chen, Xi Yang, Shi Jin, Pingping Xu
2020 J jnl
J. Commun. Inf. Networks
Xianda Wu, Shaodan Ma, Xi Yang
2019 C conf
ICCC
Xi Yang, Jing Zhang, Binqi Yang, Kang Wang, Xiao Li, Shi Jin
2019 C conf
ICCC
Xiaoxiang Yu, Xi Yang, Xiao Li, Shi Jin
2019 J jnl
IEEE Commun. Mag.
Xi Yang, Michail Matthaiou, Jie Yang, Chao-Kai Wen, Feifei Gao, Shi Jin
2019 C conf
ICCC
Jing Zhang, Xi Yang, Chao-Kai Wen, Xiao Li, Shi Jin
2019 conf
WCSP
Xi Yang, Shi Jin, Chao-Kai Wen, Xiao Li, Jiang Xue
2019 B conf
WCNC
Xi Yang, Wan-Ting Shih, Chao-Kai Wen, Xiao Li, Shi Jin
2019 J jnl
IEEE Trans. Wirel. Commun.
Xi Yang, Xiao Li, Shengli Zhang, Shi Jin
2019 J jnl
CoRR
Xi Yang, Fan Cao, Michail Matthaiou, Shi Jin
2019 conf
WCSP
Kang Wang, Xi Yang, Xiao Li, Chao-Kai Wen, Shi Jin
2019 J jnl
IEEE Signal Process. Lett.
Xi Yang, Shi Jin, Chao-Kai Wen
2018 J jnl
CoRR
Jie Yang, Xi Yang, Shi Jin, Chao-Kai Wen, Michalis Matthaiou
2018 J jnl
CoRR
Jie Zhao, Xi Yang, Jun Yan Dai, Qiang Cheng, Xiang Li, Ning Hua Qi, Jun Chen Ke, Guo Dong Bai, Shuo Liu, Shi Jin, Tie Jun Cui
2018 J jnl
CoRR
Xi Yang, Michail Matthaiou, Jie Yang, Chao-Kai Wen, Feifei Gao, Shi Jin
2018 conf
WCSP
Xi Yang, Xiao Li, Shengli Zhang, Shi Jin
2018 J jnl
J. Commun. Inf. Networks
Dan Qiao, Xi Yang, Weiqiang Tan, Chao-Kai Wen, Shi Jin
2018 J jnl
IEEE Access
Xi Yang, Xuesong Liang, Tiecheng Song, Wei Xu, Shi Jin
2017 conf
WCSP
Mengjiao Zhang, Weiqiang Tan, Junhui Gao, Xi Yang, Shi Jin
2017 J jnl
CoRR
Xi Yang, Zhichao Huang, Bin Han, Senjie Zhang, Chao-Kai Wen, Feifei Gao, Shi Jin
2017 J jnl
IEEE Wirel. Commun. Lett.
Xi Yang, Zhichao Huang, Bin Han, Senjie Zhang, Chao-Kai Wen, Feifei Gao, Shi Jin
2017 C conf
APCC
Xintong Lu, Xi Yang, Shi Jin, Chao-Kai Wen, Wen-Jun Lu
2016 J jnl
CoRR
Xi Yang, Wen-Jun Lu, Ning Wang, Karl Nieman, Shi Jin, Hongbo Zhu, Xiaomin Mu, Ian C. Wong, Yongming Huang, Xiaohu You
2016 conf
WCSP
Feng Ji, Xi Yang, Dan Qiao, Shi Jin
2016 conf
WCSP
Yu Yu, Peng-Fei Cui, Jun She, Yang Liu, Xi Yang, Wen-Jun Lu, Shi Jin, Hongbo Zhu
2015 conf
GlobalSIP
Xi Yang, Xuesong Liang, Xinlin Zhang, Shi Jin, Tiecheng Song
2010 conf
VTC Fall
Yaqin Xie, Yan Wang, Bo Wu, Xi Yang, Pengcheng Zhu, Xiaohu You
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