Kanjian Zhang

97 papers A* 1A 1B 2C 3Misc 1Journal 74Unranked 15
YearRankTypeTitle / Venue / Authors
2026 J jnl
Adv. Eng. Informatics
Shuyue Zhang, Shuo Shan, Yu Shen, Chenxi Li, Kanjian Zhang, Haikun Wei
2026 J jnl
Adv. Eng. Informatics
Zewen Hu, Kanjian Zhang, Haikun Wei
2026 J jnl
Fuzzy Sets Syst.
Yixuan Yuan, Liping Xie, Junsheng Zhao, Kanjian Zhang
2026 J jnl
Fuzzy Sets Syst.
Mengqing Cheng, Shuo Shan, Junsheng Zhao, Shixiong Fang, Haikun Wei, Kanjian Zhang
2026 J jnl
CoRR
Qingyu Lu, Liang Ding, Kanjian Zhang, Jinxia Zhang, Dacheng Tao
2025 J jnl
Appl. Soft Comput.
Xiang Wu, Haozheng Meng, Xiaolan Yuan, Qunxian Zheng, Jinxing Lin, Kanjian Zhang
2025 B conf
IJCNN
Fei Gong, Weiyi Ge, Ke Xie, Zhouwei Lou, Kanjian Zhang, Shuo Shan
2025 J jnl
Neurocomputing
Jingxin Zhang, Haikun Wei, Kanjian Zhang, James Xiao, Xia Hong
2025 J jnl
CoRR
Ming Gao, Ruichen Qiu, Zeng Hui Chang, Kanjian Zhang, Haikun Wei, Hong Cai Chen
2025 J jnl
Neurocomputing
Jinxia Zhang, Xinchao Zhu, Min Huang, Haikun Wei, Shixiong Fang, Kanjian Zhang
2025 J jnl
IEEE Trans Autom. Sci. Eng.
Yixuan Yuan, Liping Xie, Junsheng Zhao, Kanjian Zhang, Xiangpeng Xie
2025 J jnl
IEEE Trans. Syst. Man Cybern. Syst.
Liping Xie, Yihao Zhang, Kanjian Zhang, Zong-Yao Sun, Xiangpeng Xie
2025 B conf
COLING
Qingyu Lu, Liang Ding, Kanjian Zhang, Jinxia Zhang, Dacheng Tao
2025 J jnl
IEEE Trans. Instrum. Meas.
Zewen Hu, Hong Cai Chen, Kanjian Zhang, Haikun Wei
2025 J jnl
J. Frankl. Inst.
Liping Xie, Yefeng Xu, Shixiong Fang, Jian Ge, Kanjian Zhang
2025 J jnl
J. Frankl. Inst.
Shixiong Fang, Yixuan Yuan, Mengqing Cheng, Kanjian Zhang, Junsheng Zhao
2025 J jnl
IEEE Trans. Multim.
Liping Xie, Yang Tan, Shicheng Jing, Huimin Lu, Kanjian Zhang
2025 J jnl
CoRR
Liping Xie, Yang Tan, Shicheng Jing, Huimin Lu, Kanjian Zhang
2025 conf
EMNLP (Findings)
Qingyu Lu, Liang Ding, Siyi Cao, Xuebo Liu, Kanjian Zhang, Jinxia Zhang, Dacheng Tao
2025 J jnl
CoRR
Qingyu Lu, Liang Ding, Siyi Cao, Xuebo Liu, Kanjian Zhang, Jinxia Zhang, Dacheng Tao
2025 J jnl
IEEE Trans. Instrum. Meas.
Weijie Zhu, Shuo Shan, Chaoliu Tong, Kanjian Zhang, Haikun Wei
2024 conf
ICMLCA
Junyao Lu, Shuo Shan, Kanjian Zhang, Haikun Wei
2024 J jnl
Expert Syst. Appl.
Shuo Shan, Chenxi Li, Yiye Wang, Shixiong Fang, Kanjian Zhang, Haikun Wei
2024 J jnl
Int. J. Fuzzy Syst.
Yefeng Xu, Yihao Zhang, Sijia Chen, Kanjian Zhang, Liping Xie
2024 J jnl
Knowl. Based Syst.
Yang Tan, Liping Xie, Shicheng Jing, Shixiong Fang, Kanjian Zhang
2024 J jnl
Neural Comput. Appl.
Zhouwei Lou, Yiye Wang, Shuo Shan, Kanjian Zhang, Haikun Wei
2024 conf
ACL (Findings)
Qingyu Lu, Baopu Qiu, Liang Ding, Kanjian Zhang, Tom Kocmi, Dacheng Tao
2024 J jnl
IEEE Trans. Fuzzy Syst.
Yihao Zhang, Liping Xie, Xiangpeng Xie, Zong-Yao Sun, Kanjian Zhang
2024 J jnl
IEEE Trans. Ind. Electron.
Yang Zhang, Hong Cai Chen, Zhe Li, Chuanzhen Jia, Yaping Du, Kanjian Zhang, Haikun Wei
2024 J jnl
CoRR
Qingyu Lu, Liang Ding, Kanjian Zhang, Jinxia Zhang, Dacheng Tao
2024 conf
CMLDS
Kai Lang, Yu Shen, Chaoliu Tong, Kanjian Zhang, Haikun Wei
2024 J jnl
IEEE Trans. Vis. Comput. Graph.
Ziyao Wang, Yiye Wang, Shiqi Yan, Zhongzheng Zhu, Kanjian Zhang, Haikun Wei
2024 conf
ICMLCA
Sheng Zhu, Shuyue Zhang, Kanjian Zhang, Haikun Wei
2024 Misc conf
ICMLC
Xiao Ge, Tao Wang, Kanjian Zhang
2023 J jnl
CoRR
Jinxia Zhang, Xinyi Chen, Haikun Wei, Kanjian Zhang
2023 J jnl
Numer. Algorithms
Xiang Wu, Kanjian Zhang
2023 J jnl
Neural Comput. Appl.
Shuo Shan, Yiye Wang, Xiangying Xie, Tao Fan, Yushun Xiao, Kanjian Zhang, Haikun Wei
2023 J jnl
IEEE Trans. Ind. Informatics
Jinxia Zhang, Yu Shen, Jiacheng Jiang, Shixiong Fang, Liping Chen, Tingting Yan, Zuoyong Li, Kanjian Zhang, Haikun Wei, Weili Guo
2023 J jnl
Inf. Sci.
Junlong Tong, Liping Xie, Wankou Yang, Kanjian Zhang, Junsheng Zhao
2023 J jnl
Int. J. Fuzzy Syst.
Yihao Zhang, Liping Xie, Kanjian Zhang
2023 A conf
SDM
Junlong Tong, Liping Xie, Kanjian Zhang
2023 J jnl
IEEE Trans. Vis. Comput. Graph.
Ziyao Wang, Chiyi Liu, Jialiang Chen, Yao Yao, Dazheng Fang, Zhiyi Shi, Rui Yan, Yiye Wang, Kanjian Zhang, Hai Wang, Haikun Wei
2023 conf
ACL (1)
Qingyu Lu, Liang Ding, Liping Xie, Kanjian Zhang, Derek F. Wong, Dacheng Tao
2022 J jnl
J. Comput. Appl. Math.
Xiang Wu, Kanjian Zhang, Ming Chen
2022 J jnl
Eng. Appl. Artif. Intell.
Xiang Wu, Kanjian Zhang
2022 J jnl
Biomed. Signal Process. Control.
Peizhen Peng, Liping Xie, Kanjian Zhang, Jinxia Zhang, Lu Yang, Haikun Wei
2022 J jnl
Appl. Soft Comput.
Xiang Wu, Jinxing Lin, Kanjian Zhang, Ming Cheng
2022 J jnl
CoRR
Junlong Tong, Liping Xie, Wankou Yang, Kanjian Zhang
2022 conf
IVSP
Peizhen Peng, Kanjian Zhang, Haikun Wei
2022 J jnl
CoRR
Ziyao Wang, Chiyi Liu, Jialiang Chen, Yao Yao, Dazheng Fang, Zhiyi Shi, Rui Yan, Yiye Wang, Kanjian Zhang, Hai Wang, Haikun Wei
2022 J jnl
Biomed. Signal Process. Control.
Xiang Wu, Yuzhou Hou, Kanjian Zhang
2022 J jnl
CoRR
Qingyu Lu, Liang Ding, Liping Xie, Kanjian Zhang, Derek F. Wong, Dacheng Tao
2021 conf
ACAI
Chao Tan, Chenxi Li, Kanjian Zhang, Haikun Wei
2020 conf
PRIS
Bichen Hua, Kanjian Zhang, Haikun Wei, Jinxia Zhang, Liping Xie
2020 conf
PRCV (1)
Yu Shen, Xinyi Chen, Jinxia Zhang, Liping Xie, Kanjian Zhang, Haikun Wei
2020 conf
ICSSE
Weijing Dou, Shuo Shan, Nawei Zhang, Jinxia Zhang, Kanjian Zhang, Haikun Wei
2020 J jnl
Entropy
Chenglong Zhu, Chenxi Li, Xinyi Chen, Kanjian Zhang, Xin Xin, Haikun Wei
2020 J jnl
Soft Comput.
Tianhong Liu, Haikun Wei, Sixing Liu, Kanjian Zhang
2020 conf
VR Workshops
Ziyao Wang, Liping Xie, Haikun Wei, Kanjian Zhang, Jinxia Zhang
2020 A* conf
VR
Ziyao Wang, Haikun Wei, Kanjian Zhang, Liping Xie
2019 J jnl
IEEE Trans. Ind. Informatics
Tian Liang Guo, Zhenxing Sun, Xiangyu Wang, Shihua Li, Kanjian Zhang
2019 J jnl
J. Syst. Sci. Complex.
Xiang Wu, Kanjian Zhang, Ming Chen
2019 J jnl
Eur. J. Control
Xiang Wu, Kanjian Zhang, Xin Xin, Ming Chen
2019 J jnl
IEEE Signal Process. Lett.
Liping Xie, Junsheng Zhao, Haikun Wei, Kanjian Zhang, Guochen Pang
2019 J jnl
Trans. Inst. Meas. Control
Xiang Wu, Jinxing Lin, Kanjian Zhang, Ming Cheng
2018 J jnl
Comput. Chem. Eng.
Xiang Wu, Jinxing Lin, Kanjian Zhang, Ming Cheng
2018 C conf
ACC
Xin Xin, Makoto Ono, Shinsaku Izumi, Taiga Yamasaki, Kanjian Zhang
2018 J jnl
IEEE Access
Jinxia Zhang, Shixiong Fang, Krista A. Ehinger, Haikun Wei, Wankou Yang, Kanjian Zhang, Jingyu Yang
2018 conf
CDC
Xin Xin, Kanjian Zhang, Haikun Wei
2018 J jnl
J. Electronic Imaging
Jinxia Zhang, Shixiong Fang, Haifeng Zhao, Guang-Hai Liu, Haikun Wei, Lihuan Chen, Kanjian Zhang
2018 J jnl
J. Mach. Learn. Res.
Weili Guo, Haikun Wei, Yew-Soon Ong, Jaime Rubio Hervas, Junsheng Zhao, Hai Wang, Kanjian Zhang
2018 J jnl
J. Frankl. Inst.
Xiang Wu, Qiaodan Liu, Kanjian Zhang, Xin Xin
2018 J jnl
Neurocomputing
Weili Guo, Junsheng Zhao, Jinxia Zhang, Haikun Wei, Aiguo Song, Kanjian Zhang
2018 J jnl
Appl. Soft Comput.
Tianhong Liu, Haikun Wei, Kanjian Zhang
2017 J jnl
Pattern Recognit.
Jinxia Zhang, Krista A. Ehinger, Haikun Wei, Kanjian Zhang, Jingyu Yang
2017 J jnl
Int. J. Prod. Res.
Xiang Wu, Kanjian Zhang, Ming Cheng
2017 J jnl
Pattern Recognit.
Jinxia Zhang, Krista A. Ehinger, Haikun Wei, Kanjian Zhang, Jingyu Yang
2017 J jnl
IMA J. Math. Control. Inf.
Guochen Pang, Jinjin Liu, Kanjian Zhang, Haikun Wei
2017 J jnl
Int. J. Control
Xiaomei Liu, Shengtao Li, Kanjian Zhang
2017 J jnl
Neural Comput. Appl.
Tianhong Liu, Haikun Wei, Chi Zhang, Kanjian Zhang
2016 J jnl
Neurocomputing
Liping Xie, Haikun Wei, Junsheng Zhao, Kanjian Zhang
2016 C conf
EANN
Tianhong Liu, Haikun Wei, Chi Zhang, Kanjian Zhang
2016 J jnl
J. Optim. Theory Appl.
Kang Cheng, Kanjian Zhang, Shumin Fei, Haikun Wei
2016 J jnl
IMA J. Math. Control. Inf.
Jinjin Liu, Kanjian Zhang, Changyin Sun, Haikun Wei
2015 J jnl
Neurocomputing
Liping Xie, Haikun Wei, Kanjian Zhang
2015 J jnl
Int. J. Control
Guochen Pang, Kanjian Zhang
2015 J jnl
Appl. Math. Comput.
Tian Liang Guo, Kanjian Zhang
2015 conf
ASCC
Guochen Pang, Kanjian Zhang, Weiwei Sun
2015 C conf
ISNN
Chi Zhang, Haikun Wei, Tianhong Liu, Tingting Zhu, Kanjian Zhang
2015 J jnl
Entropy
Jinjin Liu, Kanjian Zhang
2015 J jnl
Neurocomputing
Weili Guo, Haikun Wei, Junsheng Zhao, Kanjian Zhang
2014 J jnl
Neural Comput. Appl.
Weili Guo, Haikun Wei, Junsheng Zhao, Kanjian Zhang
2014 J jnl
Neurocomputing
Junsheng Zhao, Haikun Wei, Weili Guo, Kanjian Zhang
2014 J jnl
J. Optim. Theory Appl.
Kang Cheng, Shumin Fei, Kanjian Zhang, Xiaomei Liu, Haikun Wei
2013 J jnl
J. Optim. Theory Appl.
Xiang Wu, Kanjian Zhang, Changyin Sun
2012 J jnl
Circuits Syst. Signal Process.
Yonggang Chen, Shumin Fei, Kanjian Zhang, Zhumu Fu
2007 conf
ISNN (3)
Kanjian Zhang, Chunbo Feng
redb/extractors/decompiler/bninja/analysis/disassembly.py
← Index redb/extractors/decompiler/bninja/analysis/disassembly.py python
import re
import time

import binaryninja
from binaryninja.enums import (
    InstructionTextTokenType,
)

# Support both package and standalone imports
try:
    from ..function_type import FunctionTypeAnalysis
    from ..utils.hashes import calculate_sha256
except ImportError:
    # Fallback to absolute imports (for multiprocessing spawned processes)
    from redb.extractors.decompiler.bninja.function_type import FunctionTypeAnalysis
    from redb.extractors.decompiler.bninja.utils.hashes import calculate_sha256


class DisassemblyAnalysis:
    INVALID_STACK_SIZE = -1

    def __init__(self, arch, function, bv, logger):
        self.arch = arch
        self.function = function
        self.bv = bv
        self.logger = logger
        if self.function is not None and hasattr(self.function, "instructions"):
            self.instructions = self.function.instructions
        else:
            self.instructions = []
        self.errors = []
        return

    def log_error(
        self, message, function_name, address, exception=None, error_location="unknown"
    ):
        """Log an error during processing."""
        error_msg = f"Error in function {function_name} at {address}: {message}"
        if exception:
            error_msg += f" - {str(exception)}"
        self.logger.error(error_msg)

        # Add to errors list
        error = {
            "function_name": function_name,
            "function_address": str(address),
            "error_location": error_location,
            "error_message": message,
            "error_details": str(exception) if exception else "",
            "error_type": type(exception).__name__ if exception else "Unknown",
            "timestamp": int(time.time() * 1000),
        }
        self.errors.append(error)

    def get_json(self):
        try:
            # Build disassembly string and normalized versions
            disassembly_builder = [[], []]  # Address and instruction text

            # Create a dictionary mapping addresses to instruction tokens
            instr_tokens_by_addr = {}
            for instr_tokens, addr in self.instructions:
                instr_tokens_by_addr[addr] = instr_tokens

            addresses = sorted(instr_tokens_by_addr.keys())
            for address in addresses:
                # Original disassembly with addresses
                # instr_tokens, address = instruction
                instr_tokens = instr_tokens_by_addr[address]
                disassembly_builder[0].append(address)
                disassembly_builder[1].append("".join(map(str, instr_tokens)))

            # Join with newlines
            disassembly_str = "\n".join(disassembly_builder[1])
            disassembly_with_addresses = "\n".join(
                f"{hex(address)}: {instr_text}"
                for address, instr_text in zip(
                    disassembly_builder[0], disassembly_builder[1], strict=False
                )
            )

            disassembly_json = {
                "disassembled_function_hash": calculate_sha256(disassembly_str),
                "disassembled_function": disassembly_with_addresses,
                "disassembled_function_no_addresses": disassembly_str,
                "disassembled_function_name": self.function.name,
                "disassembled_function_address": self.function.start,
                "instructions_count": len(instr_tokens_by_addr.keys()),
                "function_type": FunctionTypeAnalysis(self.function)
                .get_function_type()
                .name,
            }

            # Add additional metrics
            type_frequencies = self.collect_instruction_types()
            disassembly_json["instructions_types"] = list(type_frequencies.keys())
            disassembly_json["control_flow_count"] = (
                self.count_control_flow_instructions()
            )
            disassembly_json["memory_access_pattern"] = self.collect_memory_patterns()
            disassembly_json["register_usage"] = self.collect_register_usage()
            disassembly_json["data_references_count"] = self.count_data_references()
            disassembly_json["max_block_size"] = self.compute_max_block_size()
            disassembly_json["num_calls"] = self.compute_num_calls()
            disassembly_json["stack_size"] = self.estimate_stack_size()

            return disassembly_json, self.errors

        except Exception as e:
            self.log_error(
                "Failed to collect instruction types",
                self.function.name,
                self.function.start,
                e,
                "collect_instruction_types",
            )
            raise ValueError(e) from e

    def collect_instruction_types(self):
        """Collect instruction type frequencies from a function."""
        type_frequencies = {}

        try:
            # Iterate through all instructions in the function
            for instruction in self.instructions:
                instr_tokens = instruction[0]  # Get the instruction tokens

                # Extract the mnemonic from the instruction tokens
                mnemonic = None
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.InstructionToken:
                        mnemonic = token.text
                        break

                if not mnemonic:
                    continue

                # Use normalize_opcode to get standardized opcode
                normalized = self.normalize_opcode(mnemonic)

                # Get category from opcode_categories or use the instruction type directly
                category = self.arch.opcode_categories.get(normalized)
                if category:
                    self._increment_frequency(type_frequencies, category)

        except Exception as e:
            self.log_error(
                "Failed to collect instruction types",
                self.function.name,
                self.function.start,
                e,
                "collect_instruction_types",
            )

        return type_frequencies

    def normalize_opcode(self, opcode):
        return opcode.upper()

    def collect_memory_patterns(self):
        """Collect memory access patterns from a function."""
        patterns = []
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]

                # We need to capture memory operands between BeginMemoryOperandToken and EndMemoryOperandToken
                in_memory_operand = False
                memory_operand_text = ""

                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.BeginMemoryOperandToken:
                        in_memory_operand = True
                        memory_operand_text = ""
                    elif token.type == InstructionTextTokenType.EndMemoryOperandToken:
                        in_memory_operand = False

                        # Process the captured memory operand text
                        if memory_operand_text:
                            # Categorize memory access pattern
                            if (
                                "+" in memory_operand_text
                                and "*" in memory_operand_text
                            ):
                                if "MEM_SCALED_INDEX" not in patterns:
                                    patterns.append("MEM_SCALED_INDEX")
                            elif (
                                "+" in memory_operand_text or "-" in memory_operand_text
                            ):
                                if "MEM_BASE_OFFSET" not in patterns:
                                    patterns.append("MEM_BASE_OFFSET")
                            else:
                                if "MEM_DIRECT" not in patterns:
                                    patterns.append("MEM_DIRECT")

                            # Check for stack accesses
                            if any(
                                reg in memory_operand_text
                                for reg in ["SP", "BP", "ESP", "EBP", "RSP", "RBP"]
                            ):
                                if "MEM_STACK" not in patterns:
                                    patterns.append("MEM_STACK")
                            # Check for string operations
                            elif (
                                any(
                                    reg in memory_operand_text
                                    for reg in ["SI", "DI", "ESI", "EDI", "RSI", "RDI"]
                                )
                                and "MEM_STRING" not in patterns
                            ):
                                patterns.append("MEM_STRING")
                    elif in_memory_operand:
                        # Accumulate token text while inside a memory operand
                        memory_operand_text += token.text
        except Exception as e:
            self.log_error(
                "Failed to collect memory patterns",
                self.function.name,
                self.function.start,
                e,
                "collect_memory_patterns",
            )
        return patterns

    def collect_register_usage(self):
        """Collect register usage from a function."""
        registers = []
        try:
            # Define register groups we're interested in tracking
            register_groups = {
                "GPR": [
                    "RAX",
                    "RBX",
                    "RCX",
                    "RDX",
                    "R9",
                    "R10",
                    "R11",
                    "R12",
                    "R13",
                    "R14",
                    "R15",
                    "EAX",
                    "EBX",
                    "ECX",
                    "EDX",
                    "R9D",
                    "R10D",
                    "R11D",
                    "R12D",
                    "R13D",
                    "R14D",
                    "AX",
                    "BX",
                    "CX",
                    "DX",
                ],
                "GPR_INDEX": ["RSI", "RDI", "ESI", "EDI", "SI", "DI"],
                "GPR_STACK": ["RSP", "RBP", "ESP", "EBP", "SP", "BP"],
                "SIMD": ["XMM", "YMM", "ZMM"],
                "FPU": ["ST", "ST0", "ST1", "ST2", "ST3", "ST4", "ST5", "ST6", "ST7"],
                "FLAGS": ["FLAGS", "EFLAGS", "RFLAGS"],
                "CONTROL_REGISTER": ["CR0", "CR2", "CR3", "CR4", "CR8"],
                "DEBUG_REGISTER": ["DR0", "DR1", "DR2", "DR3", "DR6", "DR7"],
            }

            # Extract registers from instructions
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.RegisterToken:
                        reg = token.text.upper()
                        # Check which group this register belongs to
                        for group, regs in register_groups.items():
                            # if any(r in reg for r in regs) or any(reg.startswith(r) for r in regs):
                            if any(reg == r or reg.startswith(r) for r in regs):
                                if group not in registers:
                                    registers.append(group)
                                break
        except Exception as e:
            self.log_error(
                "Failed to collect register usage",
                self.function.name,
                self.function.start,
                e,
                "collect_register_usage",
            )
        return registers

    def count_data_references(self):
        """Count the number of data references in a function."""
        count = 0
        try:

            if self.function.mlil is None:
                return 0

            for block in self.function.mlil:
                for instr in block:
                    instr_str = str(instr)
                    logged = False
                    src = None

                    # Check for constant dereferencing or symbolic refs
                    if hasattr(instr, "src"):
                        src = instr.src
                        if isinstance(
                            src,
                            (
                                binaryninja.mediumlevelil.MediumLevelILConstPtr,
                                binaryninja.mediumlevelil.MediumLevelILConst,
                            ),
                        ):
                            count += 1
                            logged = True

                    # Check full string for hardcoded addresses or symbol-like tokens
                    if re.search(r"\b0x[0-9A-Fa-f]{3,}\b", instr_str) and not logged:
                        count += 1
                        logged = True

                    if "_" in instr_str and not logged:
                        count += 1
                        logged = True

                    # Only check for MediumLevelILConstPtr if src exists
                    if src is not None and isinstance(
                        src, binaryninja.mediumlevelil.MediumLevelILConstPtr
                    ):
                        addr = src.constant
                        # Check if address is in data sections
                        segment = self.bv.get_segment_at(addr)
                        if segment and segment.writable:
                            # print(f"[{function.name}] Matched data section reference in: {instr_str}")
                            count += 1
                            logged = True
        except Exception as e:
            self.logger.warning(
                f"Failed to use MLIL for counting data references in {self.function.name} at {self.function.start}: {e}"
            )
        return count

    def compute_max_block_size(self):
        """Compute the maximum basic block size in a function."""
        max_size = 0
        if self.function is None:
            return 0

        for block in self.function.basic_blocks:
            try:
                # Count instructions in this block using the direct length approach
                # This avoids UTF-8 decoding issues entirely
                block_size = block.instruction_count
                max_size = max(max_size, block_size)
            except Exception as e:
                self.log_error(
                    f"[HandledError] computing max block size: {e}",
                    self.function.name,
                    self.function.start,
                    e,
                    "compute_max_block_size",
                )
        return max_size

    def count_control_flow_instructions(self):
        """Count the number of control flow instructions in a function."""
        count = 0
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                if self.arch.is_control_flow_instruction(instr_tokens):
                    count += 1
        except Exception as e:
            self.log_error(
                "Failed to count control flow instructions",
                self.function.name,
                self.function.start,
                e,
                "count_control_flow_instructions",
            )
        return count

    def compute_num_calls(self) -> int:
        """Compute the number of call instructions in a function."""
        num_calls = 0
        try:
            for instruction in self.instructions:
                instr_tokens = instruction[0]
                # Extract the mnemonic
                for token in instr_tokens:
                    if token.type == InstructionTextTokenType.InstructionToken:
                        if token.text.upper() == "CALL":
                            num_calls += 1
                        break
        except Exception as e:
            self.log_error(
                "Failed to compute number of calls",
                self.function.name,
                self.function.start,
                e,
                "compute_num_calls",
            )
        return num_calls

    def _increment_frequency(self, frequencies, type_name):
        """Increment the frequency count for an instruction type."""
        if type_name in frequencies:
            frequencies[type_name] += 1
        else:
            frequencies[type_name] = 1

    def estimate_stack_size(self):
        """Estimate the stack size used by a function."""
        try:
            # Binary Ninja provides a stack adjustment value for functions
            # Need to convert OffsetWithConfidence to a plain integer
            stack_adjust = self.function.stack_adjustment
            if hasattr(stack_adjust, "value"):  # Handle OffsetWithConfidence objects
                return stack_adjust.value
            return stack_adjust
        except Exception as e:
            self.log_error(
                "Failed to estimate stack size",
                self.function.name,
                self.function.start,
                e,
                "estimate_stack_size",
            )
            return self.INVALID_STACK_SIZE