Chang Su

26 papers A* 1A 1B 1Misc 2Journal 20Unranked 1
YearRankTypeTitle / Venue / Authors
2024 J jnl
npj Digit. Medicine
Chang Su, Yu Hou, Jielin Xu, Zhenxing Xu, Manqi Zhou, Alison Ke, Haoyang Li, Jie Xu, Matthew Brendel, Jacqueline R. M. A. Maasch, Zilong Bai, Haotan Zhang, Yingying Zhu, Molly C. Cincotta, Xinghua Shi, Claire Henchcliffe, James B. Leverenz, Jeffrey Cummings, Michael S. Okun, Jiang Bian, Feixiong Cheng, Fei Wang
2023 J jnl
CoRR
Xinyue Hu, Lin Gu, Kazuma Kobayashi, Qiyuan An, Qingyu Chen, Zhiyong Lu, Chang Su, Tatsuya Harada, Yingying Zhu
2022 J jnl
CoRR
Matthew Brendel, Chang Su, Zilong Bai, Hao Zhang, Olivier Elemento, Fei Wang
2022 J jnl
Genom. Proteom. Bioinform.
Matthew Brendel, Chang Su, Zilong Bai, Hao Zhang, Olivier Elemento, Fei Wang
2022 Misc conf
AMIA
Chang Su, Yu Hou, Jielin Xu, Matthew Brendel, Jacqueline R. M. A. Maasch, Zilong Bai, Yingying Zhu, Claire Henchcliffe, Feixiong Cheng, Fei Wang
2022 J jnl
J. Am. Medical Informatics Assoc.
Wanwan Xu, Chang Su, Yan Li, Steven Rogers, Fei Wang, Kun Chen, Robert H. Aseltine
2022 J jnl
CoRR
Xinyue Hu, Lin Gu, Liangchen Liu, Ruijiang Li, Chang Su, Tatsuya Harada, Yingying Zhu
2022 Misc conf
AMIA
Yunyu Xiao, Haotan Zhang, Yu Hou, Chang Su, Fei Wang
2021 J jnl
npj Digit. Medicine
Chang Su, Yongkang Zhang, James H. Flory, Mark G. Weiner, Rainu Kaushal, Edward J. Schenck, Fei Wang
2021 J jnl
J. Heal. Informatics Res.
Jie Xu, Benjamin S. Glicksberg, Chang Su, Peter B. Walker, Jiang Bian, Fei Wang
2021 J jnl
IEEE Trans. Multim.
Hang Wang, Youtian Du, Guangxun Zhang, Zhongmin Cai, Chang Su
2021 J jnl
IET Image Process.
Yunbo Cui, Youtian Du, Xue Wang, Hang Wang, Chang Su
2021 J jnl
Briefings Bioinform.
Sendong Zhao, Chang Su, Zhiyong Lu, Fei Wang
2020 A* conf
ICDM
Sendong Zhao, Yong Huang, Chang Su, Yuantong Li, Fei Wang
2020 J jnl
IEEE Trans. Multim.
Youtian Du, Xue Wang, Yunbo Cui, Hang Wang, Chang Su
2020 J jnl
Health Informatics J.
Yongjun Zhu, Chao Che, Bo Jin, Ningrui Zhang, Chang Su, Fei Wang
2020 J jnl
Briefings Bioinform.
Chang Su, Jie Tong, Yongjun Zhu, Peng Cui, Fei Wang
2019 conf
IRC
Xue Wang, Youtian Du, Xuelian Li, Fuyuan Cao, Chang Su
2019 A conf
CIKM
Sendong Zhao, Chang Su, Andrea Sboner, Fei Wang
2019 J jnl
CoRR
Sendong Zhao, Chang Su, Andrea Sboner, Fei Wang
2019 J jnl
CoRR
Sendong Zhao, Yong Huang, Chang Su, Yuantong Li, Fei Wang
2018 J jnl
J. Inf. Sci.
Chang Su, Xiaohong Guan, Youtian Du, Qian Wang, Fei Wang
2018 J jnl
CoRR
Xi Zhang, Dandi Chen, Yongjun Zhu, Chao Che, Chang Su, Sendong Zhao, Xu Min, Fei Wang
2018 J jnl
Knowl. Based Syst.
Chang Su, Xiaohong Guan, Youtian Du, Xin Huang, Minhua Zhang
2013 B conf
LCN
Chang Su, Youtian Du, Xiaohong Guan, Chenhe Wu
2013 J jnl
J. Inf. Sci.
Youtian Du, Chang Su, Zhongmin Cai, Xiaohong Guan
tests/unit/test_apk_method_extractor.py
← Index tests/unit/test_apk_method_extractor.py python
"""
Unit tests for APK method-level content extraction, hashing, and similarity.

Tests SHA-256 normalization, ssdeep/TLSH computation, obfuscation detection,
and Dalvik-to-Java type conversion.
"""
import pytest

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


class TestHashingFunctions:
    """Tests for hashing utility functions."""

    def test_sha256_deterministic(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_sha256
        h1 = compute_sha256("invoke-virtual {p0}, Lcom/Foo;->bar()V")
        h2 = compute_sha256("invoke-virtual {p0}, Lcom/Foo;->bar()V")
        assert h1 == h2

    def test_sha256_hex_length(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_sha256
        assert len(compute_sha256("test")) == 64

    def test_sha256_different_inputs(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_sha256
        assert compute_sha256("aaa") != compute_sha256("bbb")

    def test_ssdeep_none_for_short(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_ssdeep
        assert compute_ssdeep("short") is None

    def test_tlsh_none_for_short(self):
        from redb.extractors.decompiler.apk.method_extractor import compute_tlsh
        assert compute_tlsh("x") is None


class TestObfuscationDetection:
    """Tests for obfuscation indicator detection."""

    def test_short_method_name_single_char(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        r = detect_obfuscation_indicators("a", "Lcom/Foo;", "", 10)
        assert r["short_method_name"] is True

    def test_short_method_name_two_chars(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        r = detect_obfuscation_indicators("ab", "Lcom/Foo;", "", 10)
        assert r["short_method_name"] is True

    def test_normal_method_name(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        r = detect_obfuscation_indicators("onCreate", "Lcom/Foo;", "", 10)
        assert r["short_method_name"] is False

    def test_short_class_name(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        r = detect_obfuscation_indicators("foo", "Lcom/a;", "", 10)
        assert r["short_class_name"] is True

    def test_normal_class_name(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        r = detect_obfuscation_indicators("foo", "Lcom/example/MainActivity;", "", 10)
        assert r["short_class_name"] is False

    def test_string_encryption_detected(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = (
            'const-string v0, "xyz"\n'
            'invoke-static {v0}, Lcom/Enc;->decrypt(Ljava/lang/String;)Ljava/lang/String;\n'
        )
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 10)
        assert r["has_string_encryption"] is True

    def test_no_string_encryption(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = 'const-string v0, "hello"\ninvoke-virtual {v0}, Ljava/lang/String;->length()I'
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 10)
        assert r["has_string_encryption"] is False

    def test_reflection_detected(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = 'invoke-virtual {v0, v1}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;'
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 10)
        assert r["has_reflection_calls"] is True

    def test_no_reflection(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = 'invoke-virtual {p0}, Lcom/Foo;->bar()V'
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 10)
        assert r["has_reflection_calls"] is False

    def test_excessive_goto_detected(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = "\n".join(["goto :label"] * 10)
        # threshold = max(5, 20*0.15=3) = 5, 10 > 5
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 20)
        assert r["excessive_goto_count"] is True

    def test_no_excessive_goto(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = "goto :label\nreturn-void"
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 100)
        assert r["excessive_goto_count"] is False

    def test_goto_16_counted(self):
        from redb.extractors.decompiler.apk.method_extractor import detect_obfuscation_indicators
        smali = "\n".join(["goto/16 :label"] * 10)
        r = detect_obfuscation_indicators("m", "Lcom/Foo;", smali, 20)
        assert r["excessive_goto_count"] is True


class TestDalvikTypeConversion:
    """Tests for Dalvik-to-Java type conversion."""

    def test_void(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_type_to_java
        assert dalvik_type_to_java("V") == "void"

    def test_primitives(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_type_to_java
        assert dalvik_type_to_java("I") == "int"
        assert dalvik_type_to_java("Z") == "boolean"
        assert dalvik_type_to_java("J") == "long"
        assert dalvik_type_to_java("F") == "float"
        assert dalvik_type_to_java("D") == "double"
        assert dalvik_type_to_java("B") == "byte"
        assert dalvik_type_to_java("S") == "short"
        assert dalvik_type_to_java("C") == "char"

    def test_object_type(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_type_to_java
        assert dalvik_type_to_java("Ljava/lang/String;") == "String"
        assert dalvik_type_to_java("Lcom/example/Foo;") == "Foo"

    def test_array_type(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_type_to_java
        assert dalvik_type_to_java("[I") == "int[]"
        assert dalvik_type_to_java("[Ljava/lang/String;") == "String[]"

    def test_empty_returns_void(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_type_to_java
        assert dalvik_type_to_java("") == "void"


class TestJavaPrototypeConversion:
    """Tests for method signature to Java prototype conversion."""

    def test_simple_method(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_to_java_prototype
        assert dalvik_to_java_prototype("foo", "()V") == "void foo()"

    def test_method_with_params(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_to_java_prototype
        result = dalvik_to_java_prototype("bar", "(ILjava/lang/String;)Z")
        assert result == "boolean bar(int, String)"

    def test_method_returning_object(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_to_java_prototype
        result = dalvik_to_java_prototype("create", "()Lcom/example/Foo;")
        assert result == "Foo create()"

    def test_empty_signature(self):
        from redb.extractors.decompiler.apk.method_extractor import dalvik_to_java_prototype
        result = dalvik_to_java_prototype("m", "")
        assert "m()" in result


class TestDalvikParamParsing:
    """Tests for parsing Dalvik parameter descriptors."""

    def test_empty(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        assert _parse_dalvik_params("") == []

    def test_single_primitive(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        assert _parse_dalvik_params("I") == ["I"]

    def test_multiple_primitives(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        assert _parse_dalvik_params("IZJ") == ["I", "Z", "J"]

    def test_single_object(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        assert _parse_dalvik_params("Ljava/lang/String;") == ["Ljava/lang/String;"]

    def test_mixed(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        result = _parse_dalvik_params("ILjava/lang/String;Z")
        assert result == ["I", "Ljava/lang/String;", "Z"]

    def test_arrays(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        result = _parse_dalvik_params("[I[Ljava/lang/String;")
        assert result == ["[I", "[Ljava/lang/String;"]

    def test_two_objects(self):
        from redb.extractors.decompiler.apk.method_extractor import _parse_dalvik_params
        result = _parse_dalvik_params("Landroid/os/Bundle;Ljava/lang/String;")
        assert len(result) == 2