Kaicong Sun

63 papers A* 1Journal 28Unranked 30
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Trans. Biomed. Eng.
Shijie Huang, Kaicong Sun, Kai Zhang, Lingnan Kong, Fangmei Zhu, Zhongxiang Ding, Geng Chen, Dinggang Shen
2026 J jnl
Medical Image Anal.
Zixin Tang, Caiwen Jiang, Kaicong Sun, Zhiming Cui, Dinggang Shen
2026 ed.
MLMI@MICCAI
Zhiming Cui, Islem Rekik, Heung-Il Suk, Xi Ouyang, Kaicong Sun, Sheng Wang
2025 J jnl
IEEE Trans. Medical Imaging
Haoshen Wang, Zhentao Liu, Kaicong Sun, Xiaodong Wang, Dinggang Shen, Zhiming Cui
2025 conf
MLMI@MICCAI
Zhongjian Jiang, Kaicong Sun, Dinggang Shen
2025 J jnl
IEEE J. Biomed. Health Informatics
Yuanwang Zhang, Kaicong Sun, Yuxiao Liu, Fang Xie, Qihao Guo, Dinggang Shen
2025 J jnl
IEEE Trans. Biomed. Eng.
Runqi Meng, Jingli Chen, Kaicong Sun, Qianqian Chen, Xiao Zhang, Ling Dai, Yuning Gu, Guangyu Wu, Dinggang Shen
2025 conf
MICCAI (8)
Haoyuan Chen, Yonghao Li, Long Yang, Han Wu, Lin Zhou, Kaicong Sun, Dinggang Shen
2025 conf
MICCAI (15)
Fan Li, Shilun Zhao, Shuwei Bai, Yuxiao Liu, Kai Zhang, Yin Xu, Ya Zhang, Kaicong Sun, Dinggang Shen
2025 conf
MLMI@MICCAI
Siyu Cheng, Lanzhuju Mei, Minjiao Wang, Min Zhu, Kaicong Sun, Zhiming Cui, Dinggang Shen
2025 conf
IPMI (2)
Mingyang Yu, Yaozong Gao, Yiran Shu, Yanbo Chen, Jingyu Liu, Caiwen Jiang, Kaicong Sun, Weifang Zhang, Yiqiang Zhan, Xiang Sean Zhou, Shaonan Zhong, Xinlu Wang, Meixin Zhao, Dinggang Shen
2025 J jnl
Medical Image Anal.
Honglin Xiong, Yulin Wang, Zhenrong Shen, Kaicong Sun, Yu Fang, Yan Chen, Dinggang Shen, Qian Wang
2025 conf
MICCAI (5)
Mingyang Yu, Yaozong Gao, Yiran Shu, Yanbo Chen, Jingyu Liu, Caiwen Jiang, Kaicong Sun, Zhiming Cui, Weifang Zhang, Yiqiang Zhan, Xiang Sean Zhou, Shaonan Zhong, Xinlu Wang, Meixin Zhao, Dinggang Shen
2025 J jnl
IEEE Trans. Medical Imaging
Kaicong Sun, Caohui Duan, Xin Lou, Dinggang Shen
2025 ed.
MLMI@MICCAI (1)
Xuanang Xu, Zhiming Cui, Islem Rekik, Xi Ouyang, Kaicong Sun
2025 ed.
MLMI@MICCAI (2)
Xuanang Xu, Zhiming Cui, Islem Rekik, Xi Ouyang, Kaicong Sun
2025 J jnl
IEEE Trans. Biomed. Eng.
Yuxuan Liu, Kaicong Sun, Haikun Qi, Junwei Yang, Xiaopeng Zong, Yongsheng Pan, Yuning Gu, Sifan He, Han Zhang, Yu Zhang, Dinggang Shen
2025 conf
AMAI@MICCAI
Weilin Zhou, Yuxiao Liu, Yuanwang Zhang, Kaicong Sun, Fan Li, Shilun Zhao, Yuanbo Wang, Dinggang Shen
2025 conf
MLMI@MICCAI
Zhouxin Xue, Fan Yang, Kaicong Sun, Zhiming Cui, Dinggang Shen
2025 conf
BIBM
Zhichao Liang, Fan Li, Dengqiang Jia, Yaofei Duan, Xinyu Xie, Kaicong Sun, Zhiming Cui, Tao Tan, Dinggang Shen
2025 conf
DGM4MICCAI@MICCAI
Zaixin Ou, Caiwen Jiang, Yuxiao Liu, Kaicong Sun, Dinggang Shen
2025 conf
MICCAI (3)
Yulin Wang, Honglin Xiong, Kaicong Sun, Jiameng Liu, Xin Lin, Ziyi Chen, Yuanzhe He, Qian Wang, Dinggang Shen
2025 conf
MICCAI (1)
Ruilong Dan, Kaicong Sun, Yichen Zhou, Minqiang Jia, Yuxuan Liu, Han Zhang, Xiaopeng Zong, Dinggang Shen
2024 J jnl
CoRR
Haoshen Wang, Zhentao Liu, Kaicong Sun, Xiaodong Wang, Dinggang Shen, Zhiming Cui
2024 J jnl
CoRR
Yuxiao Liu, Mianxin Liu, Yuanwang Zhang, Kaicong Sun, Dinggang Shen
2024 conf
MLCN@MICCAI
Yuxiao Liu, Mianxin Liu, Yuanwang Zhang, Kaicong Sun, Dinggang Shen
2024 conf
EMBC
Ye Liu, Kaicong Sun, Chong Li, Qingneng Li, Zhuoxu Cui, Jing Cheng, Dong Liang
2024 J jnl
IEEE Trans. Medical Imaging
Xiao Zhang, Kaicong Sun, Dijia Wu, Xiaosong Xiong, Jiameng Liu, Linlin Yao, Shufang Li, Yining Wang, Jun Feng, Dinggang Shen
2024 conf
MICCAI (7)
Honglin Xiong, Yu Fang, Kaicong Sun, Yulin Wang, Xiaopeng Zong, Weijun Zhang, Qian Wang
2024 conf
GRAIL@MICCAI
Dengqiang Jia, Xinnian Yang, Xiaosong Xiong, Shijie Huang, Feiyu Hou, Li Qin, Kaicong Sun, Kannie W. Y. Chan, Dinggang Shen
2024 J jnl
CoRR
Dengqiang Jia, Xinnian Yang, Xiaosong Xiong, Shijie Huang, Feiyu Hou, Li Qin, Kaicong Sun, Kannie W. Y. Chan, Dinggang Shen
2024 J jnl
Neural Networks
Qingrui Sha, Kaicong Sun, Caiwen Jiang, Mingze Xu, Zhong Xue, Xiaohuan Cao, Dinggang Shen
2024 J jnl
CoRR
Caiwen Jiang, Mianxin Liu, Kaicong Sun, Dinggang Shen
2024 conf
MICCAI (2)
Qingrui Sha, Kaicong Sun, Mingze Xu, Yonghao Li, Zhong Xue, Xiaohuan Cao, Dinggang Shen
2024 J jnl
IEEE Trans. Medical Imaging
Kaicong Sun, Qian Wang, Dinggang Shen
2024 conf
MICCAI (9)
Anglin Liu, Dengqiang Jia, Kaicong Sun, Runqi Meng, Meixin Zhao, Yongluo Jiang, Zhijian Dong, Yaozong Gao, Dinggang Shen
2024 J jnl
IEEE Trans. Medical Imaging
Xiangxi Meng, Kaicong Sun, Jun Xu, Xuming He, Dinggang Shen
2024 A* conf
AAAI
Runqi Meng, Xiao Zhang, Shijie Huang, Yuning Gu, Guiqin Liu, Guangyu Wu, Nizhuan Wang, Kaicong Sun, Dinggang Shen
2024 conf
CaPTion@MICCAI
Runqi Meng, Zonglin Liu, Yiqun Sun, Dengqiang Jia, Lin Teng, Qiong Ma, Tong Tong, Kaicong Sun, Dinggang Shen
2024 J jnl
CoRR
Yulin Wang, Honglin Xiong, Kaicong Sun, Shuwei Bai, Ling Dai, Zhongxiang Ding, Jiameng Liu, Qian Wang, Qian Liu, Dinggang Shen
2024 conf
MICCAI (2)
Jiameng Liu, Feihong Liu, Kaicong Sun, Yuhang Sun, Jiawei Huang, Caiwen Jiang, Islem Rekik, Dinggang Shen
2024 conf
MICCAI (7)
Ye Liu, Zhuo-Xu Cui, Kaicong Sun, Ting Zhao, Jing Cheng, Yuliang Zhu, Dinggang Shen, Dong Liang
2023 J jnl
Biomed. Signal Process. Control.
Kaicong Sun, Sven Simon
2023 conf
MICCAI (4)
Jiameng Liu, Feihong Liu, Kaicong Sun, Mianxin Liu, Yuhang Sun, Yuyan Ge, Dinggang Shen
2023 conf
MLMI@MICCAI (1)
Yuhang Sun, Jiameng Liu, Feihong Liu, Kaicong Sun, Han Zhang, Feng Shi, Qianjin Feng, Dinggang Shen
2023 conf
MICCAI (7)
Meiyu Li, Kaicong Sun, Yuning Gu, Kai Zhang, Yiqun Sun, Zhenhui Li, Dinggang Shen
2023 conf
MLMI@MICCAI (2)
Nan Zhao, Yongsheng Pan, Kaicong Sun, Yuning Gu, Mianxin Liu, Zhong Xue, Han Zhang, Qing Yang, Fei Gao, Feng Shi, Dinggang Shen
2023 J jnl
J. Real Time Image Process.
Ammar Alsaffar, Kaicong Sun, Sven Simon
2023 conf
IPMI
Shijie Huang, Geng Chen, Kaicong Sun, Zhiming Cui, Xukun Zhang, Peng Xue, Xuan Zhang, He Zhang, Dinggang Shen
2023 conf
ISBI
Yuanwang Zhang, Kaicong Sun, Yuxiao Liu, Dinggang Shen
2023 conf
MLMI@MICCAI (1)
Yuanwang Zhang, Kaicong Sun, Yuxiao Liu, Zaixin Ou, Dinggang Shen
2022 J jnl
CoRR
Trung-Hieu Tran, Kaicong Sun, Sven Simon
2022 J jnl
J. Real Time Image Process.
Trung-Hieu Tran, Kaicong Sun, Sven Simon
2022 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Kaicong Sun, Maurice Koch, Zhe Wang, Slavisa Jovanovic, Hassan Rabah, Sven Simon
2022 J jnl
J. Real Time Image Process.
Ammar Alsaffar, Steffen Kieß, Kaicong Sun, Sven Simon
2022 conf
MLMIR@MICCAI
Temitope Emmanuel Komolafe, Yuhang Sun, Nizhuan Wang, Kaicong Sun, Guohua Cao, Dinggang Shen
2022 J jnl
J. Real Time Image Process.
Kaicong Sun, Trung-Hieu Tran, Guhathakurta Jajnabalkya, Sven Simon
2021 J jnl
CoRR
Kaicong Sun, Sven Simon
2021 J jnl
IEEE Trans. Signal Process.
Kaicong Sun, Sven Simon
2021
Kaicong Sun
2020 J jnl
CoRR
Kaicong Sun, Sven Simon
2020 J jnl
Signal Process. Image Commun.
Kaicong Sun, Trung-Hieu Tran, Roman Krawtschenko, Sven Simon
2018 conf
ACOMP
Trung-Hieu Tran, Gasim Mammadov, Kaicong Sun, Sven Simon
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