Xiangxiang Chu

153 papers A* 25A 5B 1Misc 3Journal 111Unranked 8
YearRankTypeTitle / Venue / Authors
2026 J jnl
CoRR
Liang Lin, Feng Xiong, Zengbin Wang, Kun Wang, Junhao Dong, Xuecai Hu, Yong Wang, Xiangxiang Chu
2026 A* conf
AAAI
Renda Li, Hailang Huang, Fei Wei, Feng Xiong, Yong Wang, Xiangxiang Chu
2026 A* conf
WWW
Yanqi Dai, Yong Wang, Zebin You, Dong Jing, Xiangxiang Chu, Zhiwu Lu
2026 J jnl
CoRR
Chen Zhu, Jiashu Zhu, Yanxun Li, Meiqi Wu, Bingze Song, Chubin Chen, Jiahong Wu, Xiangxiang Chu, Yangang Wang
2026 J jnl
CoRR
Yuhao Zheng, Li'an Zhong, Yi Wang, Rui Dai, Kaikui Liu, Xiangxiang Chu, Linyuan Lv, Philip Torr, Kevin Qinghong Lin
2026 J jnl
CoRR
Jintao Chen, Aiming Hao, Xiaoqing Chen, Chengyu Bai, Chubin Chen, Yanxun Li, Jiahong Wu, Xiangxiang Chu, Shanghang Zhang
2026 J jnl
CoRR
Shidong Yang, Tongwen Huang, Hao Wen, Yong Wang, Li Chen, Xiangxiang Chu
2026 J jnl
CoRR
Zengbin Wang, Xuecai Hu, Yong Wang, Feng Xiong, Man Zhang, Xiangxiang Chu
2026 J jnl
CoRR
Yifei Wang, Yueqi Wang, Zhenrui Yue, Huimin Zeng, Yong Wang, Ismini Lourentzou, Zhengzhong Tu, Xiangxiang Chu, Julian J. McAuley
2026 J jnl
IEEE Trans. Circuits Syst. Video Technol.
Sifan Zhou, Xinyu Zhang, Xiangxiang Chu, Bo Zhang, Ziyu Zhao, Xiaobo Lu
2026 J jnl
CoRR
Xiangyan Qu, Zhenlong Yuan, Jing Tang, Rui Chen, Datao Tang, Meng Yu, Lei Sun, Yancheng Bai, Xiangxiang Chu, Gaopeng Gou, Gang Xiong, Yujun Cai
2026 J jnl
CoRR
Chengzhang Wang, Chao Chen, Jun Tao, Tengfei Liu, He Bai, Song Wang, Longfei Xu, Kaikui Liu, Xiangxiang Chu
2026 J jnl
CoRR
Zihan Su, Hongyang Wei, Kangrui Cen, Yong Wang, Guanhua Chen, Chun Yuan, Xiangxiang Chu
2026 J jnl
CoRR
Jiyuan Wang, Chunyu Lin, Lei Sun, Zhi Cao, YuYang Yin, Lang Nie, Zhenlong Yuan, Xiangxiang Chu, Yunchao Wei, Kang Liao, Guosheng Lin
2026 J jnl
CoRR
Yanqi Dai, Yuxiang Ji, Xiao Zhang, Yong Wang, Xiangxiang Chu, Zhiwu Lu
2026 A* conf
AAAI
Meiqi Wu, Jiashu Zhu, Xiaokun Feng, Chubin Chen, Chen Zhu, Bingze Song, Fangyuan Mao, Jiahong Wu, Xiangxiang Chu, Kaiqi Huang
2026 J jnl
CoRR
Zesheng Wang, Longfei Xu, Weidong Deng, Huimin Yan, Kaikui Liu, Xiangxiang Chu
2026 J jnl
CoRR
Huimin Yan, Longfei Xu, Junjie Sun, Zheng Liu, Wei Luo, Kaikui Liu, Xiangxiang Chu
2026 J jnl
CoRR
Meiqi Wu, Bingze Song, Ruimin Lin, Chen Zhu, Xiaokun Feng, Jiahong Wu, Xiangxiang Chu, Kaiqi Huang
2026 J jnl
CoRR
Ruidong Chen, Yancheng Bai, Xuanpu Zhang, Jianhao Zeng, Lanjun Wang, Dan Song, Lei Sun, Xiangxiang Chu, Anan Liu
2026 J jnl
CoRR
Zhiheng Song, Jingshuai Zhang, Chuan Qin, Chao Wang, Chao Chen, Longfei Xu, Kaikui Liu, Xiangxiang Chu, Hengshu Zhu
2026 A* conf
AAAI
Fangyuan Mao, Aiming Hao, Jintao Chen, Dongxia Liu, Xiaokun Feng, Jiashu Zhu, Meiqi Wu, Chubin Chen, Jiahong Wu, Xiangxiang Chu
2026 J jnl
CoRR
Meiqi Wu, Zhixin Cai, Fufangchen Zhao, Xiaokun Feng, Rujing Dang, Bingze Song, Ruitian Tian, Jiashu Zhu, Jiachen Lei, Hao Dou, Jing Tang, Lei Sun, Jiahong Wu, Xiangxiang Chu, Zeming Liu, Kaiqi Huang
2026 J jnl
CoRR
Wulin Xie, Rui Dai, Ruidong Ding, Kaikui Liu, Xiangxiang Chu, Xinwen Hou, Jie Wen
2026 J jnl
CoRR
Aiming Hao, Chen Zhu, Jiashu Zhu, Jiahong Wu, Xiangxiang Chu
2026 A* conf
AAAI
Ryan Xu, Dongyang Jin, Yancheng Bai, Rui Lan, Xu Duan, Lei Sun, Xiangxiang Chu
2026 J jnl
CoRR
Chao Chen, Longfei Xu, Daohan Su, Tengfei Liu, Hanyu Guo, Yihai Duan, Kaikui Liu, Xiangxiang Chu
2026 J jnl
CoRR
Haodong He, Xin Zhan, Yancheng Bai, Rui Lan, Lei Sun, Xiangxiang Chu
2026 J jnl
CoRR
Yuxiang Ji, Yong Wang, Ziyu Ma, Yiming Hu, Hailang Huang, Xuecai Hu, Guanhua Chen, Liaoni Wu, Xiangxiang Chu
2026 J jnl
CoRR
Yu Wang, Yi Wang, Rui Dai, Yujie Wang, Kaikui Liu, Xiangxiang Chu, Yansheng Li
2026 J jnl
CoRR
Qile Su, Jing Tang, Rui Chen, Lei Sun, Xiangxiang Chu
2026 J jnl
CoRR
Zhenlong Yuan, Xiangyan Qu, Jing Tang, Rui Chen, Lei Sun, Ruidong Chen, Hongwei Yu, Chengxuan Qian, Xiangxiang Chu, Shuo Li, Yuyin Zhou
2025 J jnl
CoRR
Renda Li, Hailang Huang, Fei Wei, Feng Xiong, Yong Wang, Xiangxiang Chu
2025 J jnl
CoRR
Jiachen Lei, Keli Liu, Julius Berner, Haiming Yu, Hongkai Zheng, Jiahong Wu, Xiangxiang Chu
2025 J jnl
CoRR
Zhenlong Yuan, Jing Tang, Jinguo Luo, Rui Chen, Chengxuan Qian, Lei Sun, Xiangxiang Chu, Yujun Cai, Dapeng Zhang, Shuo Li
2025 J jnl
CoRR
Chao Chen, Longfei Xu, Hanyu Guo, Chengzhang Wang, Ying Wang, Kaikui Liu, Xiangxiang Chu
2025 A conf
ICWSM
Ming Shan Hee, Zihan Gao, Yinglong Wang, Xiangxiang Chu, Roy Ka-Wei Lee, Zengchang Qin
2025 conf
WWW (Companion Volume)
Jiahao Yu, Yihai Duan, Longfei Xu, Chao Chen, Shuliang Liu, Kaikui Liu, Fan Yang, Xiangxiang Chu, Ning Guo
2025 J jnl
CoRR
Jianhao Zeng, Yancheng Bai, Ruidong Chen, Xuanpu Zhang, Lei Sun, Dongyang Jin, Ryan Xu, Nannan Zhang, Dan Song, Xiangxiang Chu
2025 J jnl
CoRR
Xinyan Wang, Rui Dai, Kaikui Liu, Xiangxiang Chu
2025 J jnl
CoRR
Rui Lan, Yancheng Bai, Xu Duan, Mingxing Li, Lei Sun, Xiangxiang Chu
2025 A* conf
ACM Multimedia
Rui Chen, Lei Sun, Jing Tang, Geng Li, Xiangxiang Chu
2025 J jnl
CoRR
Rui Chen, Lei Sun, Jing Tang, Gen Li, Xiangxiang Chu
2025 J jnl
CoRR
Jiyuan Wang, Chunyu Lin, Lei Sun, Rongying Liu, Lang Nie, Mingxing Li, Kang Liao, Xiangxiang Chu, Yao Zhao
2025 J jnl
CoRR
Xiangxiang Chu, Hailang Huang, Xiao Zhang, Fei Wei, Yong Wang
2025 J jnl
CoRR
Feng Xiong, Hongling Xu, Yifei Wang, Runxi Cheng, Yong Wang, Xiangxiang Chu
2025 A* conf
EMNLP
Feng Xiong, Hongling Xu, Yifei Wang, Runxi Cheng, Yong Wang, Xiangxiang Chu
2025 J jnl
CoRR
Meiqi Wu, Jiashu Zhu, Xiaokun Feng, Chubin Chen, Chen Zhu, Bingze Song, Fangyuan Mao, Jiahong Wu, Xiangxiang Chu, Kaiqi Huang
2025 J jnl
CoRR
Huimin Yan, Longfei Xu, Junjie Sun, Ni Ou, Wei Luo, Xing Tan, Ran Cheng, Kaikui Liu, Xiangxiang Chu
2025 J jnl
CoRR
Huaqiu Li, Yong Wang, Tongwen Huang, Hailang Huang, Haoqian Wang, Xiangxiang Chu
2025 Misc conf
ICASSP
Fei Wei, Xinyu Zhang, Ailing Zhang, Bo Zhang, Xiangxiang Chu
2025 J jnl
CoRR
Xiaokun Feng, Haiming Yu, Meiqi Wu, Shiyu Hu, Jintao Chen, Chen Zhu, Jiahong Wu, Xiangxiang Chu, Kaiqi Huang
2025 J jnl
CoRR
Mingxing Li, Rui Wang, Lei Sun, Yancheng Bai, Xiangxiang Chu
2025 J jnl
CoRR
Fangyuan Mao, Aiming Hao, Jintao Chen, Dongxia Liu, Xiaokun Feng, Jiashu Zhu, Meiqi Wu, Chubin Chen, Jiahong Wu, Xiangxiang Chu
2025 A* conf
EMNLP
Yifei Wang, Feng Xiong, Yong Wang, Linjing Li, Xiangxiang Chu, Daniel Dajun Zeng
2025 J jnl
CoRR
Yifei Wang, Feng Xiong, Yong Wang, Linjing Li, Xiangxiang Chu, Daniel Dajun Zeng
2025 J jnl
CoRR
Haodong He, Yancheng Bai, Rui Lan, Xu Duan, Lei Sun, Xiangxiang Chu, Gui-Song Xia
2025 J jnl
CoRR
Chubin Chen, Jiashu Zhu, Xiaokun Feng, Nisha Huang, Meiqi Wu, Fangyuan Mao, Jiahong Wu, Xiangxiang Chu, Xiu Li
2025 J jnl
CoRR
Ryan Xu, Dongyang Jin, Yancheng Bai, Rui Lan, Xu Duan, Lei Sun, Xiangxiang Chu
2025 J jnl
CoRR
Dongyang Jin, Ryan Xu, Jianhao Zeng, Rui Lan, Yancheng Bai, Lei Sun, Xiangxiang Chu
2025 J jnl
CoRR
Zhe Huang, Hao Wen, Aiming Hao, Bingze Song, Meiqi Wu, Jiahong Wu, Xiangxiang Chu, Sheng Lu, Haoqian Wang
2025 J jnl
CoRR
Chubin Chen, Sujie Hu, Jiashu Zhu, Meiqi Wu, Jintao Chen, Yanxun Li, Nisha Huang, Chengyu Fang, Jiahong Wu, Xiangxiang Chu, Xiu Li
2025 A* conf
CVPR
Zhaochen Liu, Limeng Qiao, Xiangxiang Chu, Lin Ma, Tingting Jiang
2025 J jnl
CoRR
Yuxiang Ji, Ziyu Ma, Yong Wang, Guanhua Chen, Xiangxiang Chu, Liaoni Wu
2025 J jnl
CoRR
Xiao Zhang, Fei Wei, Yong Wang, Wenda Zhao, Feiyi Li, Xiangxiang Chu
2025 J jnl
CoRR
Xiangxiang Chu, Renda Li, Yong Wang
2025 J jnl
CoRR
Sule Bai, Mingxing Li, Yong Liu, Jing Tang, Haoji Zhang, Lei Sun, Xiangxiang Chu, Yansong Tang
2025 J jnl
CoRR
Xinran Ling, Chen Zhu, Meiqi Wu, Hangyu Li, Xiaokun Feng, Cundian Yang, Aiming Hao, Jiashu Zhu, Jiahong Wu, Xiangxiang Chu
2025 J jnl
CoRR
Zhenlong Yuan, Xiangyan Qu, Chengxuan Qian, Rui Chen, Jing Tang, Lei Sun, Xiangxiang Chu, Dapeng Zhang, Yiwei Wang, Yujun Cai, Shuo Li
2025 J jnl
CoRR
Ziyu Ma, Chenhui Gou, Yiming Hu, Yong Wang, Xiangxiang Chu, Bohan Zhuang, Jianfei Cai
2024 J jnl
IEEE Trans. Geosci. Remote. Sens.
Xiaoming Wang, Hao Chen, Xiangxiang Chu, Peng Wang
2024 J jnl
CoRR
Di Qiu, Xinyang Lin, Kaiye Wang, Xiangxiang Chu, Pengfei Yan
2024 J jnl
CoRR
Hangyu Li, Xiangxiang Chu, Dingyuan Shi
2024 conf
ECCV (71)
Yurong Zhang, Honghao Chen, Xinyu Zhang, Xiangxiang Chu, Li Song
2024 J jnl
CoRR
Yurong Zhang, Honghao Chen, Xinyu Zhang, Xiangxiang Chu, Li Song
2024 A* conf
ICLR
Sifan Zhou, Liang Li, Xinyu Zhang, Bo Zhang, Shipeng Bai, Miao Sun, Ziyu Zhao, Xiaobo Lu, Xiangxiang Chu
2024 J jnl
CoRR
Sifan Zhou, Liang Li, Xinyu Zhang, Bo Zhang, Shipeng Bai, Miao Sun, Ziyu Zhao, Xiaobo Lu, Xiangxiang Chu
2024 J jnl
CoRR
Yuhe Liu, Mengxue Kang, Zengchang Qin, Xiangxiang Chu
2024 J jnl
CoRR
Hailang Huang, Yong Wang, Zixuan Huang, Huaqiu Li, Tongwen Huang, Xiangxiang Chu, Richong Zhang
2024 A* conf
AAAI
Xiangxiang Chu, Liang Li, Bo Zhang
2024 J jnl
CoRR
Xiangxiang Chu, Limeng Qiao, Xinyu Zhang, Shuang Xu, Fei Wei, Yang Yang, Xiaofei Sun, Yiming Hu, Xinyang Lin, Bo Zhang, Chunhua Shen
2024 A* conf
AAAI
Liang Li, Qingyuan Li, Bo Zhang, Xiangxiang Chu
2024 J jnl
CoRR
Zhaochen Liu, Limeng Qiao, Xiangxiang Chu, Tingting Jiang
2024 A* conf
CVPR
Honghao Chen, Xiangxiang Chu, Yongjian Ren, Xin Zhao, Kaiqi Huang
2024 J jnl
CoRR
Honghao Chen, Xiangxiang Chu, Yongjian Ren, Xin Zhao, Kaiqi Huang
2024 J jnl
CoRR
Dingyuan Shi, Yong Wang, Hangyu Li, Xiangxiang Chu
2024 A* conf
ICML
Honghao Chen, Yurong Zhang, Xiaokun Feng, Xiangxiang Chu, Kaiqi Huang
2024 J jnl
CoRR
Honghao Chen, Yurong Zhang, Xiaokun Feng, Xiangxiang Chu, Kaiqi Huang
2024 A* conf
AAAI
Zhengze Xu, Dongyue Wu, Changqian Yu, Xiangxiang Chu, Nong Sang, Changxin Gao
2024 conf
ECCV (66)
Xiangxiang Chu, Jianlin Su, Bo Zhang, Chunhua Shen
2024 J jnl
CoRR
Xiangxiang Chu, Jianlin Su, Bo Zhang, Chunhua Shen
2023 J jnl
CoRR
Qingyuan Li, Ran Meng, Yiduo Li, Bo Zhang, Liang Li, Yifan Lu, Xiangxiang Chu, Yerui Sun, Yuchen Xie
2023 A* conf
CVPR
Chengjian Feng, Zequn Jie, Yujie Zhong, Xiangxiang Chu, Lin Ma
2023 A* conf
ICLR
Xiangxiang Chu, Zhi Tian, Bo Zhang, Xinlong Wang, Chunhua Shen
2023 J jnl
CoRR
Kaiheng Weng, Xiangxiang Chu, Xiaoming Xu, Junshi Huang, Xiaoming Wei
2023 J jnl
CoRR
Qingyuan Li, Yifan Zhang, Liang Li, Peng Yao, Bo Zhang, Xiangxiang Chu, Yerui Sun, Li Du, Yuchen Xie
2023 J jnl
CoRR
Sifan Zhou, Zhi Tian, Xiangxiang Chu, Xinyu Zhang, Bo Zhang, Xiaobo Lu, Chengjian Feng, Zequn Jie, Patrick Yin Chiang, Lin Ma
2023 J jnl
CoRR
Fei Wei, Xinyu Zhang, Ailing Zhang, Bo Zhang, Xiangxiang Chu
2023 J jnl
CoRR
Yiming Hu, Xiangxiang Chu, Bo Zhang
2023 A* conf
ICCV
Xiangxiang Chu, Shun Lu, Xudong Li, Bo Zhang
2023 J jnl
CoRR
Xiangxiang Chu, Limeng Qiao, Xinyang Lin, Shuang Xu, Yang Yang, Yiming Hu, Fei Wei, Xinyu Zhang, Bo Zhang, Xiaolin Wei, Chunhua Shen
2023 J jnl
CoRR
Liang Li, Qingyuan Li, Bo Zhang, Xiangxiang Chu
2023 A* conf
ICCV
Xiaoxing Wang, Xiangxiang Chu, Yuda Fan, Zhexi Zhang, Bo Zhang, Xiaokang Yang, Junchi Yan
2023 J jnl
CoRR
Shuang Xu, Sifan Zhou, Zhi Tian, Jizhou Ma, Qiong Nie, Xiangxiang Chu
2023 J jnl
CoRR
Zhengze Xu, Dongyue Wu, Changqian Yu, Xiangxiang Chu, Nong Sang, Changxin Gao
2023 J jnl
CoRR
Chuyi Li, Lulu Li, Yifei Geng, Hongliang Jiang, Meng Cheng, Bo Zhang, Zaidan Ke, Xiaoming Xu, Xiangxiang Chu
2022 A conf
BMVC
Xiangxiang Chu, Xiaohang Zhan, Bo Zhang
2022 J jnl
CoRR
Chengjian Feng, Zequn Jie, Yujie Zhong, Xiangxiang Chu, Lin Ma
2022 A conf
BMVC
Qingyuan Li, Bo Zhang, Xiangxiang Chu
2022 J jnl
CoRR
Qingyuan Li, Bo Zhang, Xiangxiang Chu
2022 A* conf
NeurIPS
Zhi Tian, Xiangxiang Chu, Xiaoming Wang, Xiaolin Wei, Chunhua Shen
2022 J jnl
CoRR
Zhi Tian, Xiangxiang Chu, Xiaoming Wang, Xiaolin Wei, Chunhua Shen
2022 J jnl
CoRR
Xiangxiang Chu, Liang Li, Bo Zhang
2022 A* conf
CVPR
Wangbo Zhao, Kai Wang, Xiangxiang Chu, Fuzhao Xue, Xinchao Wang, Yang You
2022 J jnl
CoRR
Wangbo Zhao, Kai Wang, Xiangxiang Chu, Fuzhao Xue, Xinchao Wang, Yang You
2022 J jnl
CoRR
Chengjian Feng, Yujie Zhong, Zequn Jie, Xiangxiang Chu, Haibing Ren, Xiaolin Wei, Weidi Xie, Lin Ma
2022 conf
ECCV (9)
Chengjian Feng, Yujie Zhong, Zequn Jie, Xiangxiang Chu, Haibing Ren, Xiaolin Wei, Weidi Xie, Lin Ma
2022 A* conf
NeurIPS
Bowen Zhang, Zhi Tian, Quan Tang, Xiangxiang Chu, Xiaolin Wei, Chunhua Shen, Yifan Liu
2022 J jnl
CoRR
Bowen Zhang, Zhi Tian, Quan Tang, Xiangxiang Chu, Xiaolin Wei, Chunhua Shen, Yifan Liu
2022 J jnl
CoRR
Chuyi Li, Lulu Li, Hongliang Jiang, Kaiheng Weng, Yifei Geng, Liang Li, Zaidan Ke, Qingyuan Li, Meng Cheng, Weiqiang Nie, Yiduo Li, Bo Zhang, Yufei Liang, Linyuan Zhou, Xiaoming Xu, Xiangxiang Chu, Xiaoming Wei, Xiaolin Wei
2021 Misc conf
ICASSP
Bo Zhang, Wenfeng Li, Qingyuan Li, Weiji Zhuang, Xiangxiang Chu, Yujun Wang
2021 J jnl
CoRR
Ye Tian, Xiangxiang Chu, Hongpeng Wang
2021 J jnl
CoRR
Xiaoxing Wang, Xiangxiang Chu, Junchi Yan, Xiaokang Yang
2021 A* conf
ICLR
Xiangxiang Chu, Xiaoxing Wang, Bo Zhang, Shun Lu, Xiaolin Wei, Junchi Yan
2021 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Zhi Tian, Xiaolin Wei, Huaxia Xia
2021 A* conf
ICCV
Xiangxiang Chu, Bo Zhang, Ruijun Xu
2021 A conf
BMVC
Xiangxiang Chu, Bo Zhang
2021 conf
ICCVW
Xiangxiang Chu, Bo Zhang, Qingyuan Li, Ruijun Xu, Xudong Li
2021 J jnl
CoRR
Xiangxiang Chu, Zhi Tian, Yuqing Wang, Bo Zhang, Haibing Ren, Xiaolin Wei, Huaxia Xia, Chunhua Shen
2021 A* conf
NeurIPS
Xiangxiang Chu, Zhi Tian, Yuqing Wang, Bo Zhang, Haibing Ren, Xiaolin Wei, Huaxia Xia, Chunhua Shen
2020 conf
ACCV (2)
Hailong Ma, Xiangxiang Chu, Bo Zhang
2020 J jnl
CoRR
Bo Zhang, Wenfeng Li, Qingyuan Li, Weiji Zhuang, Xiangxiang Chu, Yujun Wang
2020 J jnl
CoRR
Xiangxiang Chu, Xiaohang Zhan, Xiaolin Wei
2020 J jnl
CoRR
Xiangxiang Chu, Xiaoxing Wang, Bo Zhang, Shun Lu, Xiaolin Wei, Junchi Yan
2020 conf
ECCV (15)
Xiangxiang Chu, Tianbao Zhou, Bo Zhang, Jixiang Li
2020 B conf
ICPR
Xiangxiang Chu, Bo Zhang, Hailong Ma, Ruijun Xu, Qingyuan Li
2020 J jnl
CoRR
Xiangxiang Chu, Xudong Li, Yi Lu, Bo Zhang, Jixiang Li
2020 Misc conf
ICASSP
Xiangxiang Chu, Bo Zhang, Ruijun Xu
2020 conf
ECCV Workshops (4)
Xiangxiang Chu, Bo Zhang, Ruijun Xu
2020 A conf
INTERSPEECH
Jixiang Li, Chuming Liang, Bo Zhang, Zhao Wang, Fei Xiang, Xiangxiang Chu
2020 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Xudong Li
2020 J jnl
CoRR
Xiaoxing Wang, Xiangxiang Chu, Yuda Fan, Zhexi Zhang, Xiaolin Wei, Junchi Yan, Xiaokang Yang
2019 J jnl
CoRR
Hailong Ma, Xiangxiang Chu, Bo Zhang, Shaohua Wan, Bo Zhang
2019 J jnl
CoRR
Xiangxiang Chu, Tianbao Zhou, Bo Zhang, Jixiang Li
2019 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Ruijun Xu, Jixiang Li
2019 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Hailong Ma, Ruijun Xu, Jixiang Li, Qingyuan Li
2019 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Ruijun Xu
2019 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Ruijun Xu, Hailong Ma
2019 J jnl
CoRR
Jixiang Li, Chuming Liang, Bo Zhang, Zhao Wang, Fei Xiang, Xiangxiang Chu
2019 J jnl
CoRR
Xiangxiang Chu, Bo Zhang, Jixiang Li, Qingyuan Li, Ruijun Xu
2018 J jnl
CoRR
Xiangxiang Chu, Xinjie Yu
2018 J jnl
CoRR
Xiangxiang Chu
2017 J jnl
CoRR
Xiangxiang Chu, Hangjun Ye
redb/ingestor.py
← Index redb/ingestor.py python
"""
REDB Ingestor - Core ingestion orchestration.

This module contains the Ingestor class which orchestrates the entire
sample processing pipeline: querying catalogs, downloading from S3,
dispatching to workers, and collecting results.

The actual implementation is split across focused modules:
- redb.queries: Database query and deduplication functions
- redb.s3_utils: S3/MinIO client and file operations
- redb.workers: File processing and worker functions
- redb.logging_utils: Logging setup and ImportResult enum

For backward compatibility, all public names from these modules are
re-exported here so that `from redb.ingestor import *` continues to work.
"""
import multiprocessing
from multiprocessing import Pool
from datetime import datetime
import os
import sys
import gc
import psutil
import time
import json
import tempfile
import warnings
from urllib3.exceptions import InsecureRequestWarning
from dotenv import load_dotenv

load_dotenv(override=True)

warnings.filterwarnings("ignore", category=InsecureRequestWarning, module="urllib3")
warnings.filterwarnings("ignore", category=UserWarning, module="elasticsearch")

# =============================================================================
# Re-exports for backward compatibility
# =============================================================================
# These imports ensure that `from redb.ingestor import X` and
# `@patch('redb.ingestor.X')` continue to work after the refactor.

from redb.logging_utils import (  # noqa: F401
    ImportResult,
    FileNameFormatter,
    setup_logger,
    logger_thread,
    setup_direct_logger,
)

from redb.queries import (  # noqa: F401
    get_supported_formats,
    get_db_catalog_connection,
    fetch_s3_objects_by_repository,
    fetch_s3_objects_by_date_range,
    fetch_analyzed_samples,
    is_in_db,
    is_in_code_db,
    is_in_db_bulk,
)

from redb.s3_utils import (  # noqa: F401
    get_minio_client,
    generate_s3_key_from_hash,
    download_s3_object,
    extract_fat_slices,
)

from redb.workers import (  # noqa: F401
    process_s3_file,
    process_file,
    _process_file_internal,
    process_zip_file,
    process_7zip_file,
    process_binary_file,
    worker,
    direct_s3_worker,
    is_binary_file,
    check_dotnet,
    check_high_swap,
    get_module_by_name,
    filter_selected_modules,
    _is_packed,
)

# Re-export settings for patches like @patch('redb.ingestor.settings')
from redb import settings  # noqa: F401

# Re-export hashlib and Magika for patches like @patch('redb.ingestor.hashlib')
import hashlib  # noqa: F401
try:
    from magika import Magika  # noqa: F401
except ImportError:
    pass

# Re-export py7zr for patches like @patch('redb.ingestor.py7zr')
try:
    import py7zr  # noqa: F401
except ImportError:
    pass


class Ingestor:
    def __init__(
        self,
        path=None,
        decompile=False,
        yara_scan=False,
        with_yara=False,
        repository="",
        index_prefix="",
        selected_modules=None,
        s3_mode=False,
        s3_notes=None,
        magika_filter=None,
        s3_solo=False,
        s3_solo_hash=None,
        s3_solo_key=None,
        dry_run=False,
        force=False,
        job_id=None,
        start_date=None,
        end_date=None,
        analyzed=False,
        decompile_modules=None,
        rerun=False,
    ):

        # Set multiprocessing start method as early as possible
        try:
            multiprocessing.set_start_method('spawn', force=True)
        except RuntimeError:
            current_method = multiprocessing.get_start_method()
            if current_method != 'spawn':
                print(f"[WARNING] Multiprocessing start method is {current_method}, not 'spawn'. This may cause issues.")

        self.path = path
        self.decompile = decompile
        self.yara_scan = yara_scan
        self.with_yara = with_yara
        self.repository = repository
        self.index_prefix = index_prefix
        self.selected_modules = selected_modules
        self.s3_mode = s3_mode
        self.s3_notes = s3_notes
        self.magika_filter = magika_filter
        self.s3_solo = s3_solo
        self.s3_solo_hash = s3_solo_hash
        self.s3_solo_key = s3_solo_key
        self.dry_run = dry_run
        # --rerun implies force at the worker level: the query already selects
        # only already-disassembled samples, so the per-file is_in_code_db
        # dedup check must be skipped or every sample gets skipped.
        self.force = force or rerun
        self.job_id = job_id
        self.start_date = start_date
        self.end_date = end_date
        self.analyzed = analyzed
        self.decompile_modules = decompile_modules or {"all"}
        self.rerun = rerun

        self.manager = multiprocessing.Manager()
        self.file_type_stats = self.manager.dict()
        self.total_results = self.manager.dict({result: 0 for result in ImportResult})

        self.today = datetime.today().strftime("%Y%m%dT%H%M%S")
        log_base_path = os.getenv("LOG_FILE_PATH", "/app/logs/")
        if not log_base_path.endswith("/"):
            log_base_path += "/"
        index_suffix = self.index_prefix.upper() if self.index_prefix else "DEFAULT"
        self.log_file = log_base_path + f"{self.today}-{self.repository}-{index_suffix}.txt"

        with open(self.log_file, "a") as f:
            f.write(f"CMD: {' '.join(sys.argv)}\n")
            f.write(f"=== Ingestor started at {datetime.now()} ===\n")


    def restart_worker_pool(self):
        """Restart the worker pool to help address memory issues"""
        if hasattr(self, 'pool') and self.pool:
            try:
                print("[INFO] Restarting worker pool to address memory fragmentation")
                self.pool.close()
                self.pool.join()
                self.pool = None
            except:
                pass

        # Force garbage collection
        gc.collect(2)


    def _process_files_streaming(self, s3_files, temp_dir, total_files, parallel_proc, decompile=None):
        """Process files in a streaming fashion using direct process management."""
        import queue

        # Use the instance's decompile flag if not provided
        if decompile is None:
            decompile = self.decompile

        # Use local tracking for statistics
        completed_count = 0
        skipped_count = 0
        failed_count = 0
        correctly_processed = 0
        partially_processed = 0
        filetype_stats = {}

        # Create a result queue for workers to return their results
        result_queue = multiprocessing.Queue()

        # Create a process ID tracking dict
        active_processes = {}  # {proc_id: (process, start_time, s3_key)}

        mode_str = "decompile" if decompile else "analysis"
        print(f"[INFO] Starting streaming processing of {len(s3_files)} files with {parallel_proc} workers ({mode_str} mode)")

        # Process files
        file_index = 0
        # Use different timeouts based on mode
        if decompile:
            worker_timeout = int(os.getenv("DECOMPILE_WORKER_TIMEOUT", "2700"))
        else:
            worker_timeout = int(os.getenv("REDB_TIMEOUT", "1200"))

        # Main processing loop
        while file_index < len(s3_files) or active_processes:
            # Start new processes if we have capacity and files to process
            while len(active_processes) < parallel_proc and file_index < len(s3_files):
                s3_bucket, s3_key, first_seen = s3_files[file_index]
                file_number = file_index + 1

                # Create and start a new process
                p = multiprocessing.Process(
                    target=direct_s3_worker,
                    args=(
                        s3_bucket,
                        s3_key,
                        temp_dir,
                        decompile,  # Pass the actual decompile flag
                        self.index_prefix,
                        self.log_file,
                        file_number,
                        total_files,
                        self.selected_modules,
                        result_queue,
                        self.dry_run,
                        self.yara_scan,
                        self.with_yara,
                        self.force,
                        self.decompile_modules,
                        first_seen,
                    )
                )
                p.start()

                # Track the process
                active_processes[p.pid] = (p, time.time(), s3_key, file_number)
                file_index += 1

                # Small delay to avoid overloading
                time.sleep(0.05)

            # Check for completed processes
            try:
                # Poll the result queue with a timeout
                while True:
                    try:
                        result = result_queue.get(block=True, timeout=1)

                        # Process result
                        s3_key = result.get('s3_key')
                        status = result.get('status', 'FAILED')
                        filetype = result.get('filetype')
                        file_number = result.get('file_number')
                        worker_pid = result.get('worker_pid')

                        # Remove from active processes if present
                        if worker_pid in active_processes:
                            del active_processes[worker_pid]

                        # Update statistics
                        if status == 'CORRECTLY':
                            correctly_processed += 1
                        elif status == 'PARTIALLY':
                            partially_processed += 1
                        elif status == 'SKIPPED':
                            skipped_count += 1
                        else:  # Any other status is treated as failure
                            failed_count += 1

                        if filetype:
                            filetype_stats[filetype] = filetype_stats.get(filetype, 0) + 1

                        # Update progress
                        completed_count += 1
                        if completed_count % 50 == 0 or completed_count == 1:
                            print(f"[INFO] Completed {completed_count}/{total_files} files. Last: {s3_key}")
                            print(f"[INFO] Progress - OK: {correctly_processed}, Partial: {partially_processed}, Failed: {failed_count}, Skipped: {skipped_count}, Active: {len(active_processes)}")

                    except queue.Empty:
                        # No results in the queue, break and check for timeouts
                        break

                # Check for timed-out processes
                current_time = time.time()
                timed_out_pids = []

                for pid, (proc, start_time, s3_key, file_number) in active_processes.items():
                    runtime = current_time - start_time

                    # Check if process has exceeded timeout
                    if runtime > worker_timeout:
                        print(f"[WARNING] Process {pid} processing {s3_key} exceeded timeout ({runtime:.0f}s > {worker_timeout}s)")

                        # Terminate the process
                        try:
                            proc.terminate()
                            time.sleep(0.1)  # Give it a moment to terminate
                            if proc.is_alive():
                                # If still alive, force kill
                                proc.kill()
                        except:
                            pass

                        # Clean up any child processes
                        try:
                            parent = psutil.Process(pid)
                            for child in parent.children(recursive=True):
                                try:
                                    child.kill()
                                except:
                                    pass
                        except:
                            pass

                        # Mark as failed
                        failed_count += 1
                        completed_count += 1
                        timed_out_pids.append(pid)

                    # Check if process has terminated without returning a result
                    elif not proc.is_alive():
                        print(f"[WARNING] Process {pid} processing {s3_key} terminated without result")

                        # Mark as failed
                        failed_count += 1
                        completed_count += 1
                        timed_out_pids.append(pid)

                # Remove timed-out processes from tracking
                for pid in timed_out_pids:
                    if pid in active_processes:
                        del active_processes[pid]

                # Sleep briefly to avoid hogging CPU
                time.sleep(0.1)

            except Exception as e:
                print(f"[ERROR] Exception in main processing loop: {e}")
                time.sleep(1)  # Sleep to avoid tight loop on error

        # Set final results in the shared dictionaries
        self.total_results[ImportResult.CORRECTLY] = correctly_processed
        self.total_results[ImportResult.PARTIALLY] = partially_processed
        self.total_results[ImportResult.FAILED] = failed_count
        self.total_results[ImportResult.SKIPPED] = skipped_count

        for filetype, count in filetype_stats.items():
            self.file_type_stats[filetype] = count

        print(f"[INFO] Streaming processing completed. Processed {completed_count}/{total_files} files.")

        # Final cleanup
        killed = self._kill_all_python_processes()
        if killed > 0:
            print(f"[INFO] Killed {killed} lingering processes during final cleanup")


    def _kill_all_python_processes(self):
        """Kill all python worker processes."""
        killed_count = 0
        for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
            try:
                if proc.info['name'] == 'python' and proc.info['cmdline']:
                    # Check if it's one of our processes
                    is_worker = False
                    for cmd in proc.info['cmdline']:
                        if 'deploy/redb/venv312bin/python' in cmd and 'multiprocessing' in cmd:
                            is_worker = True
                            break

                    if is_worker:
                        try:
                            proc.kill()
                            killed_count += 1
                        except Exception as e:
                            print(f"[ERROR] Failed to kill process {proc.info['pid']}: {e}")
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass

        if killed_count > 0:
            print(f"[INFO] Killed {killed_count} python processes during cleanup")

        return killed_count


    def ingest(self):
        general_start_time = time.time()
        BATCH_SIZE = int(os.getenv("BATCH_SIZE", 1000))
        pool = None

        try:
            # Handle S3-solo mode
            if self.s3_solo:
                # Create a temporary directory for S3 downloads
                with tempfile.TemporaryDirectory() as temp_dir:
                    s3_bucket = os.getenv('S3_BUCKET')
                    if not s3_bucket:
                        print("[ERROR] S3_BUCKET environment variable is required for S3-solo mode")
                        return

                    # Use the provided S3 key directly (supports both sharded and private paths)
                    s3_key = self.s3_solo_key
                    print(f"[INFO] S3-solo mode: processing {s3_bucket}/{s3_key}")
                    print(f"[INFO] Extracted hash: {self.s3_solo_hash}")

                    # Fetch first_seen from catalog_samples
                    first_seen = None
                    try:
                        client = get_db_catalog_connection()
                        result = client.query(
                            "SELECT first_seen FROM catalog_samples WHERE sha256 = %(hash)s LIMIT 1",
                            parameters={"hash": self.s3_solo_hash}
                        )
                        if result.result_rows:
                            first_seen = result.result_rows[0][0]
                            print(f"[INFO] first_seen from catalog: {first_seen}")
                        else:
                            print(f"[INFO] No catalog entry found, first_seen will default to epoch zero")
                        client.close()
                    except Exception as e:
                        print(f"[WARNING] Could not fetch first_seen from catalog: {e}")

                    # Process single S3 file directly
                    result = process_s3_file(
                        s3_bucket,
                        s3_key,
                        temp_dir,
                        self.decompile,
                        self.index_prefix,
                        self.log_file,
                        1,  # file_number
                        1,  # total_files
                        selected_modules=self.selected_modules,
                        dry_run=self.dry_run,
                        yara_scan=self.yara_scan,
                        with_yara=self.with_yara,
                        force=self.force,
                        decompile_modules=self.decompile_modules,
                        first_seen=first_seen,
                    )

                    if result:
                        print(f"[INFO] S3-solo processing completed successfully")
                    else:
                        print(f"[ERROR] S3-solo processing failed")

                    return

            # Handle S3 bulk mode
            elif self.s3_mode:
                # Create a temporary directory for S3 downloads
                with tempfile.TemporaryDirectory() as temp_dir:
                    # Query catalog for S3 objects based on mode
                    if self.start_date and self.end_date:
                        # Date-based query: join catalog_samples with repository_upload_sessions
                        print(f"[INFO] Querying samples by date range: {self.start_date} to {self.end_date}")
                        # Pass repository as None if it's a default placeholder (not a real repo name)
                        repo_filter = self.repository if self.repository not in ("date-range", "analyzed") else None
                        catalog_entries = fetch_s3_objects_by_date_range(
                            index_prefix=self.index_prefix,
                            decompile=self.decompile,
                            start_date=self.start_date,
                            end_date=self.end_date,
                            repository=repo_filter,
                            notes=self.s3_notes,
                            magika_filter=self.magika_filter,
                            yara_scan=self.yara_scan,
                            force=self.force,
                            analyzed=self.analyzed
                        )
                        date_info = f" from {self.start_date} to {self.end_date}"
                    elif self.analyzed:
                        # Analyzed mode (standalone, no date filter): query basic_properties for already-analyzed samples
                        print(f"[INFO] Querying already-analyzed samples from {self.index_prefix}_basic_properties")
                        catalog_entries = fetch_analyzed_samples(
                            index_prefix=self.index_prefix,
                            decompile=self.decompile,
                            magika_filter=self.magika_filter,
                            yara_scan=self.yara_scan,
                            force=self.force,
                            rerun=self.rerun
                        )
                        date_info = ""
                    else:
                        # Repository-based query: direct query to repository_upload_sessions
                        catalog_entries = fetch_s3_objects_by_repository(
                            self.repository,
                            self.index_prefix,
                            self.decompile,
                            self.s3_notes,
                            self.magika_filter,
                            self.yara_scan,
                            self.force
                        )
                        date_info = ""

                    if not catalog_entries:
                        print(f"[INFO] No files found for repository: {self.repository}{date_info}" +
                              (f" with notes: {self.s3_notes}" if self.s3_notes else ""))
                        return

                    # Extract S3 bucket, keys, and first_seen
                    s3_files = []
                    for entry in catalog_entries:
                        s3_bucket = entry.get('s3_bucket')
                        s3_key = entry.get('s3_key')
                        first_seen = entry.get('first_seen')
                        if s3_bucket and s3_key:
                            s3_files.append((s3_bucket, s3_key, first_seen))

                    total_files = len(s3_files)
                    num_cores = multiprocessing.cpu_count()
                    parallel_proc = num_cores - 1

                    if self.decompile:
                        if self.magika_filter == 'apk':
                            parallel_proc = num_cores - 1
                            print(f"[INFO] Using decompile mode (APK) with {parallel_proc} parallel processes")
                        else:
                            parallel_proc = max(1, int((num_cores - 1) / 2))
                            print(f"[INFO] Using decompile mode with {parallel_proc} parallel processes")
                    else:
                        print(f"[INFO] Using analysis mode with {parallel_proc} parallel processes")

                    # Use streaming approach for both decompile and non-decompile cases
                    self._process_files_streaming(s3_files, temp_dir, total_files, parallel_proc, self.decompile)
            else:
                # Original file/directory processing logic
                if os.path.isfile(self.path):
                    # Check if it's a text file containing paths
                    if self.path.endswith('.txt'):
                        try:
                            with open(self.path, 'r') as f:
                                files = [line.strip() for line in f
                                    if line.strip() and not os.path.basename(line.strip()).startswith('.')]
                        except Exception as e:
                            print(f"[ERR] Failed to read file list from {self.path}: {str(e)}")
                            return
                    else:
                        files = [self.path]
                elif os.path.isdir(self.path):
                    files = [
                        os.path.join(root, file)
                        for root, dirs, files_list in os.walk(self.path)
                        for file in files_list
                        if not file.startswith('.')
                    ]
                else:
                    print(f"[ERR] Invalid path: {self.path}")
                    return

                total_files = len(files)
                num_cores = multiprocessing.cpu_count()
                parallel_proc = num_cores - 1
                if self.decompile:
                    if self.magika_filter == 'apk':
                        parallel_proc = num_cores - 1
                    else:
                        parallel_proc = int(num_cores/2)
                print(f"Number of CPU cores: {num_cores}")
                print(f"Number of parallel processes: {parallel_proc}")

                # Process files in batches
                for i in range(0, len(files), BATCH_SIZE):
                    batch_files = files[i:i + BATCH_SIZE]
                    batch_start = i
                    print(f"\nProcessing batch {i//BATCH_SIZE + 1}/{(len(files) + BATCH_SIZE - 1)//BATCH_SIZE}")
                    pool = None
                    try:
                        pool = Pool(processes=parallel_proc)
                        batch_results = pool.map(
                            worker,
                            [
                                (
                                    f,
                                    self.decompile,
                                    self.index_prefix,
                                    self.log_file,
                                    batch_start + idx + 1,
                                    total_files,
                                    self.selected_modules,
                                    self.dry_run,
                                    self.yara_scan,
                                    self.with_yara,
                                    self.force,
                                    self.decompile_modules,
                                )
                                for idx, f in enumerate(batch_files)
                            ],
                        )

                        # Update statistics for this batch
                        for result, filetype in batch_results:
                            if result is not None:
                                self.total_results[result] += 1
                            if filetype:
                                self.file_type_stats[filetype] = (
                                    self.file_type_stats.get(filetype, 0) + 1
                                )

                    finally:
                        # Properly close the pool after each batch
                        if pool:
                            try:
                                pool.close()
                                pool.join()
                                pool = None
                                gc.collect()
                            except Exception as e:
                                print(f"[ERROR] Error cleaning up pool: {e}")
                                try:
                                    pool.terminate()
                                    pool.join()
                                except:
                                    pass
                                pool = None
                                gc.collect()

                        if check_high_swap():
                            print("[INFO] High swap detected, restarting pool")
                            self.restart_worker_pool()

                            gc.collect(2)

                            # Create a fresh pool
                            self.pool = Pool(processes=parallel_proc)

                        # Export strings after each batch
            general_end_time = time.time()
            general_elapsed_time = general_end_time - general_start_time
            general_elapsed_time_pretty = time.strftime("%H:%M:%S", time.gmtime(general_elapsed_time))

            summary = (
                f"\n\nIngestion finished for {self.path}."
                f"\nTime required: {general_elapsed_time_pretty}"
                f"\nResults:"
                f"\n- Total analyzed: {sum(self.total_results.values())}"
                f"\n- Correctly imported: {self.total_results[ImportResult.CORRECTLY]}"
                f"\n- Partially imported: {self.total_results[ImportResult.PARTIALLY]}"
                f"\n- Failed: {self.total_results[ImportResult.FAILED]}"
                f"\n- Skipped: {self.total_results[ImportResult.SKIPPED]}"
                f"\n\nFiletype stats:\n{json.dumps(dict(self.file_type_stats))}\n"
            )

            with open(self.log_file, "a") as f:
                f.write(summary)

            print("Ingestion completed. Check the log file for details.")
            print(summary)

        finally:
            try:
                self._kill_all_python_processes()
            except Exception as e:
                print(f"[ERROR] Error in final cleanup: {e}")

            try:
                gc.collect(2)
            except Exception as e:
                print(f"[ERROR] Final garbage collection error: {e}")