Haiyun Guo

67 papers A* 7A 2B 3Journal 42Unranked 13
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Jinghan He, Junfeng Fang, Feng Xiong, Zijun Yao, Fei Shen, Haiyun Guo, Jinqiao Wang, Tat-Seng Chua
2026 J jnl
IEEE Trans. Image Process.
Jinghan He, Haiyun Guo, Kuan Zhu, Ming Tang, Jinqiao Wang
2026 J jnl
CoRR
Weiyun Jiang, Haiyun Guo, Christopher A. Metzler, Ashok Veeraraghavan
2026 J jnl
CoRR
ZhiYan Hou, Haiyun Guo, Haokai Ma, Yandu Sun, Yonghui Yang, Jinqiao Wang
2026 J jnl
CoRR
Gengsheng Li, Jinghan He, Shijie Wang, Dan Zhang, Ruiqi Liu, Renrui Zhang, Zijun Yao, Junfeng Fang, Haiyun Guo, Jinqiao Wang
2026 J jnl
CoRR
Tianyu Yang, ChenWei He, Xiangzhao Hao, Tianyue Wang, Jiarui Guo, Haiyun Guo, Leigang Qu, Jinqiao Wang, Tat-Seng Chua
2026 J jnl
CoRR
Yuzhe Zhou, Zhenglin Hua, Haiyun Guo, Yuheng Jia
2026 J jnl
CoRR
Xiangzhao Hao, Shijie Wang, Tianyu Yang, Tianyue Wang, Haiyun Guo, Jinqiao Wang
2026 J jnl
CoRR
Tianyue Wang, Leigang Qu, Tianyu Yang, Xiangzhao Hao, Yifan Xu, Haiyun Guo, Jinqiao Wang
2025 conf
ACL (1)
Jinghan He, Kuan Zhu, Haiyun Guo, Junfeng Fang, Zhenglin Hua, Yuheng Jia, Ming Tang, Tat-Seng Chua, Jinqiao Wang
2025 A conf
ICME
Hongyan An, Kuan Zhu, Xin He, Haiyun Guo, Chaoyang Zhao, Ming Tang, Jinqiao Wang
2025 J jnl
CoRR
Hongyan An, Kuan Zhu, Xin He, Haiyun Guo, Chaoyang Zhao, Ming Tang, Jinqiao Wang
2025 J jnl
CoRR
Haiyun Guo, ZhiYan Hou, Yu Chen, Jinghan He, Yandu Sun, Yuzhe Zhou, Shujing Guo, Kuan Zhu, Jinqiao Wang
2025 conf
PRCV (3)
Xin He, La Zhang, Haiyun Guo, Yiran Wang, Chaoyang Zhao, Jinqiao Wang
2025 A* conf
CVPR
Weijie Zhou, Manli Tao, Chaoyang Zhao, Haiyun Guo, Honghui Dong, Ming Tang, Jinqiao Wang
2025 J jnl
CoRR
Weijie Zhou, Manli Tao, Chaoyang Zhao, Haiyun Guo, Honghui Dong, Ming Tang, Jinqiao Wang
2025 J jnl
CoRR
Yicheng Xiao, Yu Chen, Haoxuan Ma, Jiale Hong, Caorui Li, Lingxiang Wu, Haiyun Guo, Jinqiao Wang
2025 A* conf
ACM Multimedia
Xiangzhao Hao, Kuan Zhu, Hongyu Guo, Haiyun Guo, Ning Jiang, Quan Lu, Ming Tang, Jinqiao Wang
2025 J jnl
CoRR
Xiangzhao Hao, Kuan Zhu, Hongyu Guo, Haiyun Guo, Ning Jiang, Quan Lu, Ming Tang, Jinqiao Wang
2025 A conf
ICME
Wei Li, Kuan Zhu, Haiyun Guo, Honghui Dong, Jinqiao Wang
2025 conf
EMNLP (Findings)
Zhenglin Hua, Jinghan He, Zijun Yao, Tianxu Han, Haiyun Guo, Yuheng Jia, Junfeng Fang
2025 J jnl
CoRR
Zhenglin Hua, Jinghan He, Zijun Yao, Tianxu Han, Haiyun Guo, Yuheng Jia, Junfeng Fang
2025 J jnl
CoRR
Hongyu Guo, Kuan Zhu, Xiangzhao Hao, Haiyun Guo, Ming Tang, Jinqiao Wang
2024 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Kuan Zhu, Haiyun Guo, Shiliang Zhang, Yaowei Wang, Jing Liu, Jinqiao Wang, Ming Tang
2024 conf
ASCC
La Zhang, Haiyun Guo, Xu Zhao, Jian Sun, Jinqiao Wang
2024 J jnl
CoRR
Jinghan He, Kuan Zhu, Haiyun Guo, Junfeng Fang, Zhenglin Hua, Yuheng Jia, Ming Tang, Tat-Seng Chua, Jinqiao Wang
2024 J jnl
CoRR
Xin He, Haiyun Guo, Kuan Zhu, Bingke Zhu, Xu Zhao, Jianwu Fang, Jinqiao Wang
2024 A* conf
EMNLP
Jinghan He, Haiyun Guo, Kuan Zhu, Zihan Zhao, Ming Tang, Jinqiao Wang
2024 J jnl
CoRR
Jinghan He, Haiyun Guo, Kuan Zhu, Zihan Zhao, Ming Tang, Jinqiao Wang
2024 J jnl
Mach. Intell. Res.
Biying Li, Zhiwei Liu, Wei Zhou, Haiyun Guo, Xin Wen, Min Huang, Jinqiao Wang
2024 A* conf
CVPR
Mingyang Xie, Haiyun Guo, Brandon Y. Feng, Lingbo Jin, Ashok Veeraraghavan, Christopher A. Metzler
2024 J jnl
CoRR
Mingyang Xie, Haiyun Guo, Brandon Y. Feng, Lingbo Jin, Ashok Veeraraghavan, Christopher A. Metzler
2023 J jnl
IEEE Trans. Intell. Transp. Syst.
Wei Li, Haiyun Guo, Honghui Dong, Ming Tang, Yue Zhou, Jinqiao Wang
2023 J jnl
CoRR
Jinghan He, Haiyun Guo, Ming Tang, Jinqiao Wang
2023 J jnl
Comput. Hum. Behav.
Haiyun Guo, Huayu Yang, Guojing Yuan, Zhihui Zhu, Kexin Zhang, Xueqing Zhang, Xiaoyan Lu, Jianghui Zhang, Jun Du, Haiyan Shi, Guifang Jin, Jiahu Hao, Ying Sun, Puyu Su, Zhihua Zhang
2023 conf
PRCV (12)
Hongyan Wu, Qinghai Miao, Haiyun Guo, Min Huang, Jinqiao Wang
2023 J jnl
IEEE Trans. Neural Networks Learn. Syst.
Kuan Zhu, Haiyun Guo, Songyan Liu, Jinqiao Wang, Ming Tang
2023 J jnl
IEEE Trans. Intell. Transp. Syst.
Mingyuan Xu, Haiyun Guo, Yuheng Jia, Zhitao Dai, Jinqiao Wang
2023 J jnl
CoRR
Yongqi An, Xu Zhao, Tao Yu, Haiyun Guo, Chaoyang Zhao, Ming Tang, Jinqiao Wang
2022 conf
MMM (2)
Hongyan Wu, Haiyun Guo, Qinghai Miao, Min Huang, Jinqiao Wang
2022 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
La Zhang, Haiyun Guo, Kuan Zhu, Honglin Qiao, Gaopan Huang, Sen Zhang, Huichen Zhang, Jian Sun, Jinqiao Wang
2022 J jnl
IEEE Trans. Intell. Transp. Syst.
Mingfei Tu, Kuan Zhu, Haiyun Guo, Qinghai Miao, Chaoyang Zhao, Guibo Zhu, Honglin Qiao, Gaopan Huang, Ming Tang, Jinqiao Wang
2022 conf
ECCV (14)
Kuan Zhu, Haiyun Guo, Tianyi Yan, Yousong Zhu, Jinqiao Wang, Ming Tang
2022 J jnl
CoRR
Kuan Zhu, Haiyun Guo, Tianyi Yan, Yousong Zhu, Jinqiao Wang, Ming Tang
2022 J jnl
CoRR
Tianyi Yan, Kuan Zhu, Haiyun Guo, Guibo Zhu, Ming Tang, Jinqiao Wang
2021 J jnl
CoRR
Kuan Zhu, Haiyun Guo, Shiliang Zhang, Yaowei Wang, Gaopan Huang, Honglin Qiao, Jing Liu, Jinqiao Wang, Ming Tang
2021 J jnl
Neurocomputing
Songyan Liu, Haiyun Guo, Kuan Zhu, Jinqiao Wang, Ming Tang
2020 J jnl
Neurocomputing
Songyan Liu, Haiyun Guo, Jian-Guo Hu, Xu Zhao, Chaoyang Zhao, Tong Wang, Yousong Zhu, Jinqiao Wang, Ming Tang
2020 conf
ECCV (23)
Xin Wen, Biying Li, Haiyun Guo, Zhiwei Liu, Guosheng Hu, Ming Tang, Jinqiao Wang
2020 J jnl
CoRR
Kuan Zhu, Haiyun Guo, Zhiwei Liu, Ming Tang, Jinqiao Wang
2020 conf
ECCV (3)
Kuan Zhu, Haiyun Guo, Zhiwei Liu, Ming Tang, Jinqiao Wang
2020 conf
ICPR Workshops (4)
Tianyi Yan, Haiyun Guo, Songyan Liu, Chaoyang Zhao, Ming Tang, Jinqiao Wang
2019 J jnl
IEEE Trans. Image Process.
Yousong Zhu, Chaoyang Zhao, Haiyun Guo, Jinqiao Wang, Xu Zhao, Hanqing Lu
2019 B conf
ICIP
Haiyun Guo, Huiyao Wu, Chaoyang Zhao, Huichen Zhang, Jinqiao Wang, Hanqing Lu
2019 J jnl
Neurocomputing
Xu Zhao, Chaoyang Zhao, Haiyun Guo, Yousong Zhu, Ming Tang, Jinqiao Wang
2019 A* conf
CVPR
Zhiwei Liu, Xiangyu Zhu, Guosheng Hu, Haiyun Guo, Ming Tang, Zhen Lei, Neil Martin Robertson, Jinqiao Wang
2019 J jnl
CoRR
Zhiwei Liu, Xiangyu Zhu, Guosheng Hu, Haiyun Guo, Ming Tang, Zhen Lei, Neil Martin Robertson, Jinqiao Wang
2019 J jnl
IEEE Trans. Image Process.
Haiyun Guo, Kuan Zhu, Ming Tang, Jinqiao Wang
2019 conf
ICME Workshops
Xingan Ma, Kuan Zhu, Haiyun Guo, Jinqiao Wang, Min Huang, Qinghai Miao
2018 A* conf
AAAI
Haiyun Guo, Chaoyang Zhao, Zhiwei Liu, Jinqiao Wang, Hanqing Lu
2017 B conf
ICIP
Yating He, Min Huang, Qinghai Miao, Haiyun Guo, Jinqiao Wang
2016 J jnl
IEEE Trans. Image Process.
Haiyun Guo, Jinqiao Wang, Yue Gao, Jianqiang Li, Hanqing Lu
2016 J jnl
IET Comput. Vis.
Haiyun Guo, Jinqiao Wang, Hanqing Lu
2016 conf
ACCV (2)
Yousong Zhu, Jinqiao Wang, Chaoyang Zhao, Haiyun Guo, Hanqing Lu
2015 conf
3DOR@Eurographics
Yue Gao, Anan Liu, Weizhi Nie, Yuting Su, Qionghai Dai, Fuhai Chen, Yingying Chen, Yanhua Cheng, Shuilong Dong, Xingyue Duan, Jianlong Fu, Zan Gao, Haiyun Guo, Xin Guo, Kaiqi Huang, Rongrong Ji, Yingfeng Jiang, Haisheng Li, Hanqing Lu, Jianming Song, Jing Sun, Tieniu Tan, Jinqiao Wang, Huanpu Yin, Chaoli Zhang, Guotai Zhang, Yan Zhang, Chaoyang Zhao, Xin Zhao, Guibo Zhu
2015 A* conf
ACM Multimedia
Haiyun Guo, Jinqiao Wang, Min Xu, Zheng-Jun Zha, Hanqing Lu
2015 B conf
ICIP
Haiyun Guo, Jinqiao Wang, Hanqing Lu
redb/ext/spoof_check.py
← Index redb/ext/spoof_check.py python
import copy
import struct
from enum import Enum

"""
Checks that the metadata within a file's Rich header does not contradict the
other metadata contained within it.

References:
    https://gist.github.com/skochinsky/07c8e95e33d9429d81a75622b5d24c8b
    https://www.sec.in.tum.de/i20/publications/finding-the-needle-a-study-of-
    the-pe32-rich-header-and-respective-malware-triage
"""

KNOWN_PRODUCT_IDS = {
    0: "Unknown",
    1: "Import0",
    2: "Linker510",
    3: "Cvtomf510",
    4: "Linker600",
    5: "Cvtomf600",
    6: "Cvtres500",
    7: "Utc11_Basic",
    8: "Utc11_C",
    9: "Utc12_Basic",
    10: "Utc12_C",
    11: "Utc12_CPP",
    12: "AliasObj60",
    13: "VisualBasic60",
    14: "Masm613",
    15: "Masm710",
    16: "Linker511",
    17: "Cvtomf511",
    18: "Masm614",
    19: "Linker512",
    20: "Cvtomf512",
    21: "Utc12_C_Std",
    22: "Utc12_CPP_Std",
    23: "Utc12_C_Book",
    24: "Utc12_CPP_Book",
    25: "Implib700",
    26: "Cvtomf700",
    27: "Utc13_Basic",
    28: "Utc13_C",
    29: "Utc13_CPP",
    30: "Linker610",
    31: "Cvtomf610",
    32: "Linker601",
    33: "Cvtomf601",
    34: "Utc12_1_Basic",
    35: "Utc12_1_C",
    36: "Utc12_1_CPP",
    37: "Linker620",
    38: "Cvtomf620",
    39: "AliasObj70",
    40: "Linker621",
    41: "Cvtomf621",
    42: "Masm615",
    43: "Utc13_LTCG_C",
    44: "Utc13_LTCG_CPP",
    45: "Masm620",
    46: "ILAsm100",
    47: "Utc12_2_Basic",
    48: "Utc12_2_C",
    49: "Utc12_2_CPP",
    50: "Utc12_2_C_Std",
    51: "Utc12_2_CPP_Std",
    52: "Utc12_2_C_Book",
    53: "Utc12_2_CPP_Book",
    54: "Implib622",
    55: "Cvtomf622",
    56: "Cvtres501",
    57: "Utc13_C_Std",
    58: "Utc13_CPP_Std",
    59: "Cvtpgd1300",
    60: "Linker622",
    61: "Linker700",
    62: "Export622",
    63: "Export700",
    64: "Masm700",
    65: "Utc13_POGO_I_C",
    66: "Utc13_POGO_I_CPP",
    67: "Utc13_POGO_O_C",
    68: "Utc13_POGO_O_CPP",
    69: "Cvtres700",
    70: "Cvtres710p",
    71: "Linker710p",
    72: "Cvtomf710p",
    73: "Export710p",
    74: "Implib710p",
    75: "Masm710p",
    76: "Utc1310p_C",
    77: "Utc1310p_CPP",
    78: "Utc1310p_C_Std",
    79: "Utc1310p_CPP_Std",
    80: "Utc1310p_LTCG_C",
    81: "Utc1310p_LTCG_CPP",
    82: "Utc1310p_POGO_I_C",
    83: "Utc1310p_POGO_I_CPP",
    84: "Utc1310p_POGO_O_C",
    85: "Utc1310p_POGO_O_CPP",
    86: "Linker624",
    87: "Cvtomf624",
    88: "Export624",
    89: "Implib624",
    90: "Linker710",
    91: "Cvtomf710",
    92: "Export710",
    93: "Implib710",
    94: "Cvtres710",
    95: "Utc1310_C",
    96: "Utc1310_CPP",
    97: "Utc1310_C_Std",
    98: "Utc1310_CPP_Std",
    99: "Utc1310_LTCG_C",
    100: "Utc1310_LTCG_CPP",
    101: "Utc1310_POGO_I_C",
    102: "Utc1310_POGO_I_CPP",
    103: "Utc1310_POGO_O_C",
    104: "Utc1310_POGO_O_CPP",
    105: "AliasObj710",
    106: "AliasObj710p",
    107: "Cvtpgd1310",
    108: "Cvtpgd1310p",
    109: "Utc1400_C",
    110: "Utc1400_CPP",
    111: "Utc1400_C_Std",
    112: "Utc1400_CPP_Std",
    113: "Utc1400_LTCG_C",
    114: "Utc1400_LTCG_CPP",
    115: "Utc1400_POGO_I_C",
    116: "Utc1400_POGO_I_CPP",
    117: "Utc1400_POGO_O_C",
    118: "Utc1400_POGO_O_CPP",
    119: "Cvtpgd1400",
    120: "Linker800",
    121: "Cvtomf800",
    122: "Export800",
    123: "Implib800",
    124: "Cvtres800",
    125: "Masm800",
    126: "AliasObj800",
    127: "PhoenixPrerelease",
    128: "Utc1400_CVTCIL_C",
    129: "Utc1400_CVTCIL_CPP",
    130: "Utc1400_LTCG_MSIL",
    131: "Utc1500_C",
    132: "Utc1500_CPP",
    133: "Utc1500_C_Std",
    134: "Utc1500_CPP_Std",
    135: "Utc1500_CVTCIL_C",
    136: "Utc1500_CVTCIL_CPP",
    137: "Utc1500_LTCG_C",
    138: "Utc1500_LTCG_CPP",
    139: "Utc1500_LTCG_MSIL",
    140: "Utc1500_POGO_I_C",
    141: "Utc1500_POGO_I_CPP",
    142: "Utc1500_POGO_O_C",
    143: "Utc1500_POGO_O_CPP",
    144: "Cvtpgd1500",
    145: "Linker900",
    146: "Export900",
    147: "Implib900",
    148: "Cvtres900",
    149: "Masm900",
    150: "AliasObj900",
    151: "Resource900",
    152: "AliasObj1000",
    154: "Cvtres1000",
    155: "Export1000",
    156: "Implib1000",
    157: "Linker1000",
    158: "Masm1000",
    170: "Utc1600_C",
    171: "Utc1600_CPP",
    172: "Utc1600_CVTCIL_C",
    173: "Utc1600_CVTCIL_CPP",
    174: "Utc1600_LTCG_C ",
    175: "Utc1600_LTCG_CPP",
    176: "Utc1600_LTCG_MSIL",
    177: "Utc1600_POGO_I_C",
    178: "Utc1600_POGO_I_CPP",
    179: "Utc1600_POGO_O_C",
    180: "Utc1600_POGO_O_CPP",
    183: "Linker1010",
    184: "Export1010",
    185: "Implib1010",
    186: "Cvtres1010",
    187: "Masm1010",
    188: "AliasObj1010",
    199: "AliasObj1100",
    201: "Cvtres1100",
    202: "Export1100",
    203: "Implib1100",
    204: "Linker1100",
    205: "Masm1100",
    206: "Utc1700_C",
    207: "Utc1700_CPP",
    208: "Utc1700_CVTCIL_C",
    209: "Utc1700_CVTCIL_CPP",
    210: "Utc1700_LTCG_C ",
    211: "Utc1700_LTCG_CPP",
    212: "Utc1700_LTCG_MSIL",
    213: "Utc1700_POGO_I_C",
    214: "Utc1700_POGO_I_CPP",
    215: "Utc1700_POGO_O_C",
    216: "Utc1700_POGO_O_CPP",
    219: "Cvtres1200",
    220: "Export1200",
    221: "Implib1200",
    222: "Linker1200",
    223: "Masm1200",
    # Speculation
    224: "AliasObj1200",
    237: "Cvtres1210",
    238: "Export1210",
    239: "Implib1210",
    240: "Linker1210",
    241: "Masm1210",
    # Speculation
    242: "Utc1810_C",
    243: "Utc1810_CPP",
    244: "Utc1810_CVTCIL_C",
    245: "Utc1810_CVTCIL_CPP",
    246: "Utc1810_LTCG_C ",
    247: "Utc1810_LTCG_CPP",
    248: "Utc1810_LTCG_MSIL",
    249: "Utc1810_POGO_I_C",
    250: "Utc1810_POGO_I_CPP",
    251: "Utc1810_POGO_O_C",
    252: "Utc1810_POGO_O_CPP",
    255: "Cvtres1400",
    256: "Export1400",
    257: "Implib1400",
    258: "Linker1400",
    259: "Masm1400",
    260: "Utc1900_C",
    261: "Utc1900_CPP",
    # Speculation
    262: "Utc1900_CVTCIL_C",
    263: "Utc1900_CVTCIL_CPP",
    264: "Utc1900_LTCG_C ",
    265: "Utc1900_LTCG_CPP",
    266: "Utc1900_LTCG_MSIL",
    267: "Utc1900_POGO_I_C",
    268: "Utc1900_POGO_I_CPP",
    269: "Utc1900_POGO_O_C",
    270: "Utc1900_POGO_O_CPP",
}


class Result(Enum):
    VALID = 0
    INVALID = 1
    UNABLE_TO_PARSE = 2


def _rol(val, num):
    """Rotates val to the left by num bits."""
    return ((val << (num % 32)) & 0xFFFFFFFF) | (val >> (32 - (num % 32)))


def checksum_test(pe, rich_header):
    """Tests that the Rich header checksum is valid.

    Computes what the Rich header checksum should be. If the Rich header
    contains a different checksum value, this function returns INVALID
    This indicates that either the Rich header or MS-DOS stub has been modified

    The Rich header checksum is computed from the following:
        Length of the MS-DOS stub
        Contents of the MS-DOS stub, with e_lfanew zeroed out
        Rich header @Comp.IDs and lowest 5 bits of each count
    """
    if rich_header is None:
        rich_header = {}
    # Checksum stored in Rich header
    rich_checksum = rich_header.get("checksum", None)

    # Get DOS header data
    if pe.DOS_HEADER.e_lfanew > len(pe.__data__):
        return Result.UNABLE_TO_PARSE
    data = pe.__data__[: pe.DOS_HEADER.e_lfanew]

    # Get start marker
    mask = 0x536E6144  # DanS (little-endian)
    start_marker = struct.pack(
        "<LLLL", rich_checksum ^ mask, rich_checksum, rich_checksum, rich_checksum
    )
    if not len(start_marker):
        return Result.UNABLE_TO_PARSE

    # Get index of start marker
    start_index = data.find(start_marker)
    if start_index == -1:
        return Result.UNABLE_TO_PARSE

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.UNABLE_TO_PARSE

    # Compute cd as MS-DOS stub portion of checksum
    # Zero out e_lfanew from 0x3c to 0x3f
    cd = 0
    for i in range(start_index):
        if i >= 0x3C and i <= 0x3F:
            cd += _rol(0, i)
        else:
            cd += _rol(data[i], i)

    # Compute cd as Rich header portion of checksum
    cr = 0
    while len(rich_fields):
        compid = rich_fields.pop(0)
        count = rich_fields.pop(0)
        cr += _rol(compid, count & 0x1F)

    # Compute checksum from MS-DOS stub start index, cd, cr
    # Only keep lowest 32 bits
    checksum = (start_index + cd + cr) & 0xFFFFFFFF

    # Compare computed checksum with the checksum in the Rich header
    if checksum != rich_checksum:
        return Result.INVALID
    else:
        return Result.VALID


def duplicate_test(pe, rich_header):
    """Checks for duplicate @Comp.IDs in the Rich header.

    If the Rich header contains duplicate entries, returns INVALID
    This indicates that the Rich header has been modified
    """
    if rich_header is None:
        rich_header = {}

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.UNABLE_TO_PARSE

    # Get a list of @Comp.IDs in rich_fields
    compids = []
    for i in range(len(rich_fields)):
        if i % 2 == 0:
            compids.append(rich_fields[i])

    # Check if any @Comp.IDs are duplicates
    if len(compids) != len(set(compids)):
        return Result.INVALID

    return Result.VALID


def linker_test(pe, rich_header):
    """Checks that the Rich and PE header linker versions do not conflict.

    Certain Rich Header ProdIDs correspond to linker versions
    Although they are undocumented, we have used prior research as well as our
    own to determine many of them
    There are likely more linker version ProdIDs that we have not identified

    If the linker versions conflict, this function returns INVALID
    This indicates that the Rich header or PE header has been modified
    """
    if rich_header is None:
        rich_header = {}

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.UNABLE_TO_PARSE

    # Get list of ProdIDs from rich_fields
    prodids = []
    for i in range(len(rich_fields)):
        if i % 2 == 0:
            prodids.append(rich_fields[i] >> 16)

    # Parse major and minor linker versions from PE header
    pe_major = pe.OPTIONAL_HEADER.MajorLinkerVersion
    pe_minor = pe.OPTIONAL_HEADER.MinorLinkerVersion

    # Iterate over Rich header ProdIDs
    found_linker = False
    for prodid in prodids:

        # Only interested in ProdIDs that correspond to linker versions
        if KNOWN_PRODUCT_IDS.get(prodid) is None:
            continue
        prodid_name = KNOWN_PRODUCT_IDS[prodid]
        if not prodid_name.startswith("Linker"):
            continue

        found_linker = True

        # Parse major and minor linker version from ProdID
        prodid_name = prodid_name[6:]
        if prodid_name.endswith("p"):
            prodid_name = prodid_name[:-1]
        rich_major = int(prodid_name[:-2])
        rich_minor = int(prodid_name[-2:])

        # Check whether the Rich and PE linker versions match
        if pe_major == rich_major and pe_minor == rich_minor:
            return Result.VALID

    if not found_linker:
        return Result.UNABLE_TO_PARSE

    return Result.INVALID


def import_count_test(pe, rich_header):
    """Checks that import0 does not conflict with the IAT import count.

    The Rich header contains a ProdID called import0
    It is related to the number of imports in the IAT, but we are unsure how
    It is never less than the number of imports in the IAT

    If import0 is less than IAT import count, this function returns INVALID
    This indicates that the Rich header or IAT has been modified
    """
    if rich_header is None:
        rich_header = {}

    # Check whether the file has an IAT
    if not hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
        return Result.UNABLE_TO_PARSE

    # Get the number of imports in the IAT
    iat_count = 0
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
        for imported_function in entry.imports:
            iat_count += 1

    # Get list of @Comp.IDs and counts from Rich header
    # Elements in rich_fields at even indices are @Comp.IDs
    # Elements in rich_fields at odd indices are counts
    rich_fields = copy.deepcopy(rich_header.get("values", None))
    if len(rich_fields) % 2 != 0:
        return Result.INVALID

    # Get @Comp.ID 65536 (ProdID Import0)
    import0_count = None
    while len(rich_fields):
        compid = rich_fields.pop(0)
        count = rich_fields.pop(0)
        if compid == 65536:
            import0_count = count

    # Legitimate files never have import0_count < iat_count
    if import0_count is None:
        return Result.VALID

    if import0_count < iat_count:
        return Result.INVALID

    return Result.VALID