Haixia Yan

36 papers C 2Journal 16Unranked 18
YearRankTypeTitle / Venue / Authors
2026 J jnl
Biomed. Signal Process. Control.
Jingdong Yang, Qiwei Wu, Wenhao Weng, Siman Wang, Haixia Yan
2024 J jnl
J. Biomed. Informatics
Jingdong Yang, Han Wang, Peng Liu, Yuhang Lu, Minghui Yao, Haixia Yan
2023 J jnl
IEEE Instrum. Meas. Mag.
Jiabo Zhao, Jiasong Wang, Weihuang Yang, Yuanbin Mu, Jiagen Cheng, Mengyi Hu, Haixia Yan, Chaoran Liu, Linxi Dong
2023 J jnl
Biomed. Signal Process. Control.
Jingdong Yang, Shuchen Cai, Chenhao Qi, Tianxiao Xie, Haixia Yan
2023 J jnl
Comput. Methods Programs Biomed.
Jianjun Yan, Shiyu Cai, Xianglei Cai, Guangyao Zhu, Wei Zhou, Rui Guo, Haixia Yan, Yiqin Wang
2022 J jnl
Biomed. Signal Process. Control.
Jianjun Yan, Xianglei Cai, Guangyao Zhu, Rui Guo, Haixia Yan, Yiqin Wang
2022 J jnl
Biomed. Signal Process. Control.
Jingdong Yang, Lei Chen, Shuchen Cai, Tianxiao Xie, Haixia Yan
2021 J jnl
Comput. Math. Methods Medicine
Xiaodong Ding, Yiqin Wang, Yiming Hao, Yi Lv, Rui Chen, Haixia Yan
2021 C conf
BIBE
Jianjun Yan, Guangyao Zhu, Rui Guo, Yiqin Wang, Haixia Yan
2020 J jnl
IEEE Trans. Ind. Informatics
Linxi Dong, Zhongren Xu, Weipeng Xuan, Haixia Yan, Chaoran Liu, Wen-Sheng Zhao, Gaofeng Wang, Kwok Siong Teh
2019 J jnl
Sensors
Chenling Jin, Chunming Xia, Shiyu Zhang, Liren Wang, Yiqin Wang, Haixia Yan
2019 J jnl
IEEE Trans. Ind. Informatics
Linxi Dong, Zhiyuan Qiao, Haonan Wang, Weihuang Yang, Wen-Sheng Zhao, Kuiwen Xu, Gaofeng Wang, Libo Zhao, Haixia Yan
2019 J jnl
Grey Syst. Theory Appl.
Qiuping Wang, Subing Liu, Haixia Yan
2018 J jnl
Sensors
Xiang Fang, Linxi Dong, Wen-Sheng Zhao, Haixia Yan, Kwok Siong Teh, Gaofeng Wang
2014 conf
ICCA
Wenjie Xu, Haixia Yan, Jin Xu, Yiqin Wang, Zhaoxia Xu, Youwen Wang, Rui Guo
2014 conf
ICCA
Xin Shan, Jinlian Wu, Xiaofeng Yang, Peng Qian, Yaming Jin, Haixia Yan
2014 conf
ICCA
Rui Guo, Haixia Yan, Yiqin Wang, Jianjun Yan
2014 conf
ICCA
Jin Xu, Zhaoxia Xu, Haixia Yan, Rui Guo, Youwen Wang, Wenjie Xu, Yiqin Wang
2012 J jnl
Photonic Netw. Commun.
Xiaolong Yang, Sheng Huang, Haixia Yan, Keping Long
2011 conf
BMEI
Jianjun Yan, Qingwei Shen, Jintao Ren, Yiqin Wang, Chunfeng Chen, Rui Guo, Haixia Yan
2011 conf
BMEI
Chang Ma, Chunming Xia, Yiqin Wang, Haixia Yan, Fufeng Li
2011 J jnl
Int. J. Data Min. Bioinform.
Yiqin Wang, Haixia Yan, Rui Guo, Fufeng Li, Chunming Xia, Jianjun Yan, Zhaoxia Xu, Guoping Liu, Jin Xu
2010 conf
BIBM Workshops
Jianjun Yan, Siyuan Mao, Chunming Xia, Chao Wang, Yiqin Wang, Fufeng Li, Rui Guo, Chunfeng Chen, Haixia Yan
2010 conf
BIBM Workshops
Connie Yukkin Hung, Zhaoxia Xu, Yiqin Wang, Fufeng Li, Haixia Yan, Yuci Yang
2010 conf
BIBM Workshops
Zhaoxia Xu, Yiqin Wang, Guo-Ping Liu, Jin Xu, Rui Guo, Haixia Yan, Fufeng Li, Yu-jian Hong, Jianjun Yan, Chunming Xia
2010 conf
ICCA
Haixia Yan, Yiqin Wang, Rui Guo, Zhaorong Liu, Fufeng Li, Fengying Run, Yujian Hong, Jianjun Yan
2010 conf
ICCA
Zhongyan Gu, Jianjun Yan, Siyuan Mao, Yiqin Wang, Fufeng Li, Chunming Xia, Rui Guo, Qingwei Shen, Haixia Yan
2010 conf
BIBM Workshops
Haixia Yan, Yiqin Wang, Rui Guo, Fufeng Li, Yujian Hong, Fengying Yun, Yuci Yang, Yiming Hao, Jianjun Yan
2010 conf
BIBM Workshops
Rui Guo, Yiqin Wang, Haixia Yan, Fufeng Li, Zhaoxia Xu, Jianjun Yan
2010 conf
BIBM Workshops
Yiqin Wang, Rui Guo, Haixia Yan, Fufeng Li, Chunming Xia, Zhaoxia Xu, Jin Xu
2009 conf
CAD/Graphics
Yun Huang, Qiang Zhou, Yici Cai, Haixia Yan
2009 conf
BIBM
Haixia Yan, Yiqin Wang, Zhaorong Liu, Rui Guo, Fufeng Li, Fengying Run, Yujian Hong
2009 J jnl
Integr.
Haixia Yan, Qiang Zhou, Xianlong Hong
2008 conf
BMEI (2)
Chunming Xia, Yan Li, Jianjun Yan, Yiqin Wang, Haixia Yan, Rui Guo, Fufeng Li
2008 conf
ISQED
Haixia Yan, Qiang Zhou, Xianlong Hong
2007 C conf
ISCAS
Haixia Yan, Zhuoyuan Li, Xianlong Hong, Qiang Zhou
tests/unit/test_smali_normalization.py
← Index tests/unit/test_smali_normalization.py python
"""Unit tests for smali semantic normalization.

Tests the three normalization levels (category, opcode, opcode_api),
opcode categorization, ACFG feature index mapping, and integration
with MinHash computation.
"""
import pytest

pytestmark = [pytest.mark.unit, pytest.mark.apk, pytest.mark.decompile]


class TestCategorizeOpcode:
    """Tests for opcode -> semantic category mapping."""

    def test_arithmetic(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("add-int") == "ALU"
        assert categorize_opcode("mul-long/2addr") == "ALU"
        assert categorize_opcode("neg-int") == "ALU"

    def test_data_movement(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("move-result") == "MOV"
        assert categorize_opcode("const/4") == "CONST"
        assert categorize_opcode("const-string") == "CONST"

    def test_memory_access(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("iget-object") == "LOAD"
        assert categorize_opcode("sput-wide") == "STORE"
        assert categorize_opcode("aget-byte") == "LOAD"

    def test_invocation(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("invoke-virtual") == "CALL"
        assert categorize_opcode("invoke-static") == "CALL"
        assert categorize_opcode("invoke-direct") == "CALL"

    def test_control_flow(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("if-eqz") == "BRANCH"
        assert categorize_opcode("goto") == "JMP"
        assert categorize_opcode("goto/16") == "JMP"
        assert categorize_opcode("return-void") == "RET"

    def test_comparison(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("cmp-long") == "CMP"
        assert categorize_opcode("cmpl-float") == "CMP"
        assert categorize_opcode("cmpg-double") == "CMP"

    def test_conversion(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("int-to-long") == "CONV"
        assert categorize_opcode("float-to-int") == "CONV"

    def test_object_type(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("new-instance") == "ALLOC"
        assert categorize_opcode("check-cast") == "TYPE"
        assert categorize_opcode("instance-of") == "TYPE"

    def test_exception_sync(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("throw") == "EXC"
        assert categorize_opcode("monitor-enter") == "SYNC"

    def test_unknown(self):
        from redb.extractors.decompiler.apk.smali_normalization import categorize_opcode
        assert categorize_opcode("nop") == "OTHER"


class TestNormalizeInstruction:
    """Tests for single instruction normalization at various levels."""

    def test_category_level(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("add-int v0, v1, v2", "category") == "ALU"
        assert normalize_instruction("invoke-virtual {p0}, Lcom/Foo;->bar()V", "category") == "CALL"
        assert normalize_instruction("return-void", "category") == "RET"

    def test_opcode_level_strips_width(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Width variants collapse to same base
        assert normalize_instruction("add-int v0, v1, v2", "opcode") == "add"
        assert normalize_instruction("add-long v0, v2, v4", "opcode") == "add"
        assert normalize_instruction("add-float v0, v1, v2", "opcode") == "add"
        # Addressing modes collapse too
        assert normalize_instruction("add-int/2addr v0, v1", "opcode") == "add"

    def test_opcode_api_invoke(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "invoke-virtual {p0, v0}, Lcom/example/Foo;->bar(I)V"
        )
        assert result == "CALL Lcom/example/Foo;->bar(I)V"

    def test_opcode_api_invoke_no_ref(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # If somehow no method ref is found, fallback to CALL
        assert normalize_instruction("invoke-virtual {v0}") == "CALL"

    def test_opcode_api_field_load(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "LOAD Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_field_store(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iput-object v0, p0, Lcom/Foo;->mField:Ljava/lang/String;"
        )
        assert result == "STORE Lcom/Foo;->mField:Ljava/lang/String;"

    def test_opcode_api_androguard_field_format(self):
        """androguard uses space instead of colon in field references."""
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "iget-object v0, p0, Lcom/Foo;->mField Ljava/lang/String;"
        )
        assert result.startswith("LOAD")
        assert "Lcom/Foo;->mField" in result

    def test_opcode_api_new_instance(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            "new-instance v0, Lcom/example/MyClass;"
        )
        assert result == "ALLOC Lcom/example/MyClass;"

    def test_opcode_api_const_string(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string v0, "hello world"'
        )
        assert result == 'CONST_STR "hello world"'

    def test_opcode_api_const_string_jumbo(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        result = normalize_instruction(
            'const-string/jumbo v0, "large string"'
        )
        assert result == 'CONST_STR "large string"'

    def test_opcode_api_fallback_to_category(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        # Non-special instructions fall back to category
        assert normalize_instruction("add-int v0, v1, v2") == "ALU"
        assert normalize_instruction("return-void") == "RET"
        assert normalize_instruction("nop") == "OTHER"

    def test_empty_input(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_instruction
        assert normalize_instruction("") == ""
        assert normalize_instruction("   ") == ""


class TestNormalizeMethodBody:
    """Tests for full method body normalization."""

    def test_filters_directives_labels_comments(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
.locals 2
# comment
:label_0
add-int v0, v1, v2
.line 42
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        result = normalize_method_body(body, "category")
        assert result == ["ALU", "CALL", "RET"]

    def test_opcode_api_preserves_api_refs(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->setX(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
return-void
"""
        result = normalize_method_body(body, "opcode_api")
        assert result[0] == "CONST"
        assert result[1] == "CALL Lcom/Foo;->setX(I)V"
        assert result[2] == "LOAD Lcom/Foo;->name:Ljava/lang/String;"
        assert result[3] == "RET"

    def test_empty_body(self):
        from redb.extractors.decompiler.apk.smali_normalization import normalize_method_body
        assert normalize_method_body("") == []
        assert normalize_method_body("\n\n") == []


class TestNormalizationWithMinHash:
    """Integration tests: normalization + MinHash computation."""

    def test_minhash_returns_signature(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        sig = compute_minhash(body)
        assert sig is not None
        assert len(sig) == 64
        assert all(0 <= v < 256 for v in sig)

    def test_minhash_register_invariance(self):
        """Same operations with different registers should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/Foo;->bar(I)V
iget-object v1, p0, Lcom/Foo;->name:Ljava/lang/String;
add-int v2, v0, v1
return-void
"""
        body_b = """\
const/4 v3, 0x0
invoke-virtual {p1, v3}, Lcom/Foo;->bar(I)V
iget-object v4, p1, Lcom/Foo;->name:Ljava/lang/String;
add-int v5, v3, v4
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a == sig_b

    def test_minhash_width_invariance(self):
        """Width variants of same operations should produce identical signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_int = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        body_long = """\
add-long v0, v2, v4
sub-long v6, v0, v2
mul-long v8, v0, v6
return-wide v8
"""
        sig_int = compute_minhash(body_int)
        sig_long = compute_minhash(body_long)
        # Both normalize to ALU, ALU, ALU, RET -> identical
        assert sig_int == sig_long

    def test_minhash_different_apis_differ(self):
        """Methods calling different APIs should produce different signatures."""
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        body_a = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Lcom/crypto/AES;->encrypt([B)[B
invoke-virtual {v0}, Ljava/io/OutputStream;->write([B)V
return-void
"""
        body_b = """\
const/4 v0, 0x0
invoke-virtual {p0, v0}, Ljava/lang/String;->length()I
invoke-virtual {v0}, Ljava/io/PrintStream;->println(I)V
return-void
"""
        sig_a = compute_minhash(body_a)
        sig_b = compute_minhash(body_b)
        assert sig_a != sig_b

    def test_minhash_too_few_instructions(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_minhash
        assert compute_minhash("return-void\nnop") is None


class TestACFGBlockFeatures:
    """Tests for per-block ACFG feature extraction via smali_cfg."""

    def test_simple_linear_method(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
invoke-virtual {p0}, Lcom/Foo;->bar()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 1
        assert len(metrics.block_features) == metrics.block_count
        # Each feature vector has 8 elements
        for feat in metrics.block_features:
            assert len(feat) == 8

    def test_branching_method_has_multiple_blocks(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
const/4 v0, 0x0
if-eqz v0, :cond_0
invoke-virtual {p0}, Lcom/Foo;->a()V
goto :goto_0
:cond_0
invoke-virtual {p0}, Lcom/Foo;->b()V
:goto_0
return-void
"""
        metrics = compute_cfg_metrics(body)
        assert metrics.block_count >= 3
        assert len(metrics.block_features) == metrics.block_count

    def test_feature_vector_arithmetic_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
add-int v0, v1, v2
sub-int v3, v0, v1
mul-int v4, v0, v3
return v4
"""
        metrics = compute_cfg_metrics(body)
        assert len(metrics.block_features) == 1
        feat = metrics.block_features[0]
        # feat[0] = instr_count (4), feat[1] = arithmetic (3)
        assert feat[0] == 4
        assert feat[1] >= 3  # 3 ALU ops

    def test_feature_vector_call_count(self):
        from redb.extractors.decompiler.apk.smali_cfg import compute_cfg_metrics
        body = """\
invoke-virtual {p0}, Lcom/A;->a()V
invoke-static {v0}, Lcom/B;->b()V
return-void
"""
        metrics = compute_cfg_metrics(body)
        feat = metrics.block_features[0]
        # feat[4] = call count
        assert feat[4] == 2