Kaiyuan Yang

94 papers A* 9A 2C 3Journal 37Unranked 43
YearRankTypeTitle / Venue / Authors
2026 conf
ISSCC
Qiang Zhou, Yumin Su, Hao Guo, Yaolong Hu, Kaiyuan Yang, Taiyun Chi
2026 J jnl
CoRR
Yiwei Zou, Huan-Cheng Liao, Wei Wang, Wonjune Kim, Yumin Su, Jacob T. Robinson, Kaiyuan Yang
2026 J jnl
IEEE J. Solid State Circuits
Yiwei Zou, Huan-Cheng Liao, Wei Wang, Wonjune Kim, Yumin Su, Jacob T. Robinson, Kaiyuan Yang
2026 J jnl
CoRR
Jian Gao, Yiwei Zou, Abhishek Pradhan, Wenhao Huang, Yumin Su, Kaiyuan Yang, Xuan Zhang
2025 conf
ISSCC
Huan-Cheng Liao, Shunyao Zhang, Yumin Su, Arvind Govinday, Yiwei Zou, Wei Wang, Vivek Boominathan, Ashok Veeraraghavan, Lei Li, Kaiyuan Yang
2025 conf
ISSCC
Wei Wang, Yumin Su, Huan-Cheng Liao, Yiwei Zou, Tian Qiu, Kaiyuan Yang
2025 conf
CICC
Yiwei Zou, Huan-Cheng Liao, Wei Wang, Wonjune Kim, Yumin Su, Jacob T. Robinson, Kaiyuan Yang
2025 J jnl
IEEE J. Solid State Circuits
Huan-Cheng Liao, Shunyao Zhang, Yumin Su, Arvind Govinday, Yiwei Zou, Wei Wang, Vivek Boominathan, Ashok Veeraraghavan, Lei Li, Kaiyuan Yang
2025 J jnl
CoRR
Yan He, Yumin Su, Kaiyuan Yang
2025 J jnl
IEEE J. Solid State Circuits
Yan He, Yumin Su, Kaiyuan Yang
2025 A* conf
MobiCom
Wei Wang, Ellie C. Chen, Naveed H. Ahmed, Wonjune Kim, Yiwei Zou, Joshua E. Woods, Yumin Su, Huan-Cheng Liao, Jacob T. Robinson, Kaiyuan Yang
2025 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Akhil Reddy Pakala, Zhiyu Chen, Kaiyuan Yang
2025 conf
IEEECONF
Vishesh Kumar, Jingyi Miao, Shunyao Zhang, Huan-Cheng Liao, Kaiyuan Yang, Lei Li, Ashok Veeraraghavan, Vishwanath Saragadam, Vivek Boominathan
2025 J jnl
IEEE J. Solid State Circuits
Zhiyu Chen, Ziyuan Wen, Weier Wan, Akhil Reddy Pakala, Yiwei Zou, Wei-Chen Wei, Zengyi Li, Yubei Chen, Kaiyuan Yang
2025 A* conf
ISCA
Ziyuan Wen, Alexis Le Glaunec, Konstantinos Mamouras, Kaiyuan Yang
2025 conf
CICC
Yonghee Chang, Wei Wang, Yiwei Zou, Kaiyuan Yang
2024 conf
ISSCC
Yan He, Kaiyuan Yang
2024 conf
ISSCC
Wei Wang, Zhanghao Yu, Yiwei Zou, Joshua E. Woods, Prahalad Chari, Jacob T. Robinson, Kaiyuan Yang
2024 conf
ISSCC
Jacob T. Robinson, Joshua E. Woods, Kaiyuan Yang
2024 conf
ISSCC
Zhanghao Yu, Huan-Cheng Liao, Fatima T. Alrashdan, Ziyuan Wen, Yiwei Zou, Joshua E. Woods, Wei Wang, Jacob T. Robinson, Kaiyuan Yang
2024 J jnl
CoRR
Zhanghao Yu, Yiwei Zou, Huan-Cheng Liao, Fatima Alrashdan, Ziyuan Wen, Joshua E. Woods, Wei Wang, Jacob T. Robinson, Kaiyuan Yang
2024 J jnl
IEEE Trans. Biomed. Circuits Syst.
Zhanghao Yu, Yiwei Zou, Huan-Cheng Liao, Fatima T. Alrashdan, Ziyuan Wen, Joshua E. Woods, Wei Wang, Jacob T. Robinson, Kaiyuan Yang
2024 conf
ASPLOS (2)
Ziyuan Wen, Lingkun Kong, Alexis Le Glaunec, Konstantinos Mamouras, Kaiyuan Yang
2024 conf
EMBC
Yonghee Chang, Naveed Ahmed, Kaiyuan Yang
2024 conf
ICC
Qiufeng Rui, Noah Elzner, Qiang Zhou, Ziyuan Wen, Yan He, Kaiyuan Yang, Taiyun Chi
2024 J jnl
CoRR
Wei Wang, Zhanghao Yu, Yiwei Zou, Joshua E. Woods, Prahalad Chari, Yumin Su, Jacob T. Robinson, Kaiyuan Yang
2024 J jnl
IEEE J. Solid State Circuits
Wei Wang, Zhanghao Yu, Yiwei Zou, Joshua E. Woods, Prahalad Chari, Yumin Su, Jacob T. Robinson, Kaiyuan Yang
2024 J jnl
CoRR
Zhiyu Chen, Ziyuan Wen, Weier Wan, Akhil Reddy Pakala, Yiwei Zou, Wei-Chen Wei, Zengyi Li, Yubei Chen, Kaiyuan Yang
2023 J jnl
IEEE Trans. Circuits Syst. II Express Briefs
Yunbo Huang, Yong Chen, Kaiyuan Yang, Paolo Crovetti, Pui-In Mak, Rui Paulo Martins
2023 conf
VLSI Technology and Circuits
Wei Wang, Liwen Jiang, Shayok Dutta, Yumin Su, Zhiyu Chen, Zhanghao Yu, Caleb Kemere, Kaiyuan Yang
2023 conf
VLSI Technology and Circuits
Yan He, Kaiyuan Yang
2023 J jnl
IEEE J. Solid State Circuits
Yan He, Dai Li, Zhanghao Yu, Kaiyuan Yang
2023 J jnl
CoRR
Yan He, Dai Li, Zhanghao Yu, Kaiyuan Yang
2023 A* conf
MICRO
Yi Huang, Lingkun Kong, Dibei Chen, Zhiyu Chen, Xiangyu Kong, Jianfeng Zhu, Konstantinos Mamouras, Shaojun Wei, Kaiyuan Yang, Leibo Liu
2023 J jnl
GetMobile Mob. Comput. Commun.
Zhanghao Yu, Fatima T. Alrashdan, Wei Wang, Matthew Parker, Xinyu Chen, Frank Y. Chen, Joshua E. Woods, Zhiyu Chen, Jacob T. Robinson, Kaiyuan Yang
2022 conf
CICC
Yan He, Qixuan Yu, Kaiyuan Yang
2022 A* conf
HPCA
Yi Huang, Zhiyu Chen, Dai Li, Kaiyuan Yang
2022 conf
CICC
Zhiyu Chen, Qing Jin, Zhanghao Yu, Yanzhi Wang, Kaiyuan Yang
2022 A* conf
ICLR
Qing Jin, Jian Ren, Richard Zhuang, Sumant Hanumante, Zhengang Li, Zhiyu Chen, Yanzhi Wang, Kaiyuan Yang, Sergey Tulyakov
2022 J jnl
CoRR
Qing Jin, Jian Ren, Richard Zhuang, Sumant Hanumante, Zhengang Li, Zhiyu Chen, Yanzhi Wang, Kaiyuan Yang, Sergey Tulyakov
2022 J jnl
IEEE J. Solid State Circuits
Zhanghao Yu, Joshua C. Chen, Yan He, Fatima T. Alrashdan, Benjamin W. Avants, Amanda Singer, Jacob T. Robinson, Kaiyuan Yang
2022 A* conf
MobiCom
Zhanghao Yu, Fatima T. Alrashdan, Wei Wang, Matthew Parker, Xinyu Chen, Frank Y. Chen, Joshua E. Woods, Zhiyu Chen, Jacob T. Robinson, Kaiyuan Yang
2022 J jnl
CoRR
Dai Li, Akhil Reddy Pakala, Kaiyuan Yang
2022 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Dai Li, Akhil Reddy Pakala, Kaiyuan Yang
2022 J jnl
CoRR
Qing Jin, Zhiyu Chen, Jian Ren, Yanyu Li, Yanzhi Wang, Kaiyuan Yang
2022 J jnl
CoRR
Lingkun Kong, Qixuan Yu, Agnishom Chattopadhyay, Alexis Le Glaunec, Yi Huang, Konstantinos Mamouras, Kaiyuan Yang
2022 A* conf
PLDI
Lingkun Kong, Qixuan Yu, Agnishom Chattopadhyay, Alexis Le Glaunec, Yi Huang, Konstantinos Mamouras, Kaiyuan Yang
2021 conf
ISSCC
Qiang Zhou, Yan He, Kaiyuan Yang, Taiyun Chi
2021 conf
ISSCC
Yan He, Dai Li, Zhanghao Yu, Kaiyuan Yang
2021 J jnl
CoRR
Dai Li, Kaiyuan Yang
2021 J jnl
CoRR
Dai Li, Kaiyuan Yang
2021 J jnl
CoRR
Yi Huang, Zhiyu Chen, Dai Li, Kaiyuan Yang
2021 J jnl
CoRR
Zhiyu Chen, Zhanghao Yu, Qing Jin, Yan He, Jingyu Wang, Sheng Lin, Dai Li, Yanzhi Wang, Kaiyuan Yang
2021 J jnl
IEEE J. Solid State Circuits
Zhiyu Chen, Zhanghao Yu, Qing Jin, Yan He, Jingyu Wang, Sheng Lin, Dai Li, Yanzhi Wang, Kaiyuan Yang
2021 A conf
ISLPED
Zhiyu Chen, Qing Jin, Jingyu Wang, Yanzhi Wang, Kaiyuan Yang
2021 conf
VLSI Circuits
Dai Li, Yan He, Akhil Reddy Pakala, Kaiyuan Yang
2021 conf
CICC
Zhanghao Yu, Joshua C. Chen, Yan He, Fatima T. Alrashdan, Benjamin W. Avants, Amanda Singer, Jacob T. Robinson, Kaiyuan Yang
2021 A* conf
CVPR
Zhengang Li, Geng Yuan, Wei Niu, Pu Zhao, Yanyu Li, Yuxuan Cai, Xuan Shen, Zheng Zhan, Zhenglun Kong, Qing Jin, Zhiyu Chen, Sijia Liu, Kaiyuan Yang, Bin Ren, Yanzhi Wang, Xue Lin
2020 conf
ISSCC
Yan He, Kaiyuan Yang
2020 conf
ISSCC
Zhanghao Yu, Joshua C. Chen, Benjamin W. Avants, Yan He, Amanda Singer, Jacob T. Robinson, Kaiyuan Yang
2020 J jnl
CoRR
Zhengang Li, Geng Yuan, Wei Niu, Yanyu Li, Pu Zhao, Yuxuan Cai, Xuan Shen, Zheng Zhan, Zhenglun Kong, Qing Jin, Zhiyu Chen, Sijia Liu, Kaiyuan Yang, Bin Ren, Yanzhi Wang, Xue Lin
2020 J jnl
IEEE J. Solid State Circuits
Dai Li, Kaiyuan Yang
2020 conf
MWSCAS
Jongyup Lim, Myungjoon Choi, Bowen Liu, Taewook Kang, Ziyun Li, Zhehong Wang, Yiqun Zhang, Kaiyuan Yang, David T. Blaauw, Hun-Seok Kim, Dennis Sylvester
2020 conf
Robotics: Science and Systems
Lin Shao, Toki Migimatsu, Qiang Zhang, Kaiyuan Yang, Jeannette Bohg
2020 J jnl
IEEE Trans. Biomed. Circuits Syst.
Zhanghao Yu, Joshua C. Chen, Fatima T. Alrashdan, Benjamin W. Avants, Yan He, Amanda Singer, Jacob T. Robinson, Kaiyuan Yang
2019 conf
CICC
Peiyu Chen, Dai Li, Zhanghao Yu, Qing Jin, Kaiyuan Yang
2019 conf
ISSCC
Dai Li, Kaiyuan Yang
2019 A conf
DATE
Sechang Oh, Minchang Cho, Xiao Wu, Yejoong Kim, Li-Xuan Chuo, Wootaek Lim, Pat Pannuto, Suyoung Bang, Kaiyuan Yang, Hun-Seok Kim, Dennis Sylvester, David T. Blaauw
2018 conf
VLSI Circuits
Xiao Wu, Inhee Lee, Qing Dong, Kaiyuan Yang, Dongkwun Kim, Jingcheng Wang, Yimai Peng, Yiqun Zhang, Mehdi Saligane, Makoto Yasuda, Kazuyuki Kumeno, Fumitaka Ohno, Satoru Miyoshi, Masaru Kawaminami, Dennis Sylvester, David T. Blaauw
2018 conf
VLSI Circuits
Kaiyuan Yang, Qing Dong, Zhehong Wang, Yi-Chun Shih, Yu-Der Chih, Tsung-Yung Jonathan Chang, David T. Blaauw, Dennis Sylvester
2018 J jnl
IEEE J. Solid State Circuits
Yiqun Zhang, Mahmood Khayatzadeh, Kaiyuan Yang, Mehdi Saligane, Nathaniel Ross Pinckney, Massimo Alioto, David T. Blaauw, Dennis Sylvester
2017 conf
ISSCC
Qing Dong, Yejoong Kim, Inhee Lee, Myungjoon Choi, Ziyun Li, Jingcheng Wang, Kaiyuan Yang, Yen-Po Chen, Junjie Dong, Minchang Cho, Gyouho Kim, Wei-Keng Chang, Yun-Sheng Chen, Yu-Der Chih, David T. Blaauw, Dennis Sylvester
2017 conf
ISSCC
Kaiyuan Yang, Qing Dong, David T. Blaauw, Dennis Sylvester
2017 conf
ISSCC
Kaiyuan Yang, Qing Dong, Wanyeong Jung, Yiqun Zhang, Myungjoon Choi, David T. Blaauw, Dennis Sylvester
2017 conf
ESSCIRC
Qing Dong, Inhee Lee, Kaiyuan Yang, David T. Blaauw, Dennis Sylvester
2017 J jnl
IEEE J. Solid State Circuits
Xiao Wu, Yao Shi, Supreet Jeloka, Kaiyuan Yang, Inhee Lee, Yoonmyung Lee, Dennis Sylvester, David T. Blaauw
2017 J jnl
Commun. ACM
Kaiyuan Yang, Matthew Hicks, Qing Dong, Todd M. Austin, Dennis Sylvester
2017 J jnl
IEEE Micro
Kaiyuan Yang, David T. Blaauw, Dennis Sylvester
2017 J jnl
IEEE Trans. Very Large Scale Integr. Syst.
Qing Dong, Kaiyuan Yang, Laura Fick, David Fick, David T. Blaauw, Dennis Sylvester
2017 C conf
ISCAS
Qing Dong, Kaiyuan Yang, Laura Fick, David T. Blaauw, Dennis Sylvester
2016 conf
ISSCC
Wanyeong Jung, Junhua Gu, Paul D. Myers, Minseob Shim, Seokhyeon Jeong, Kaiyuan Yang, Myungjoon Choi, Zhiyoong Foo, Suyoung Bang, Sechang Oh, Dennis Sylvester, David T. Blaauw
2016 conf
ISSCC
Yiqun Zhang, Mahmood Khayatzadeh, Kaiyuan Yang, Mehdi Saligane, Nathaniel Ross Pinckney, Massimo Alioto, David T. Blaauw, Dennis Sylvester
2016 conf
VLSI Circuits
Qing Dong, Kaiyuan Yang, David T. Blaauw, Dennis Sylvester
2016 conf
VLSI Circuits
Xiao Wu, Yao Shi, Supreet Jeloka, Kaiyuan Yang, Inhee Lee, Dennis Sylvester, David T. Blaauw
2016 conf
VLSI Circuits
Yiqun Zhang, Kaiyuan Yang, Mehdi Saligane, David T. Blaauw, Dennis Sylvester
2016 A* conf
IEEE Symposium on Security and Privacy
Kaiyuan Yang, Matthew Hicks, Qing Dong, Todd M. Austin, Dennis Sylvester
2016 J jnl
IEEE J. Solid State Circuits
Kaiyuan Yang, David T. Blaauw, Dennis Sylvester
2015 conf
ISSCC
Kaiyuan Yang, Qing Dong, David T. Blaauw, Dennis Sylvester
2015 conf
VLSIC
Kaiyuan Yang, David T. Blaauw, Dennis Sylvester
2015 C conf
ISCAS
Qing Dong, Kaiyuan Yang, Laura Fick, David Fick, David T. Blaauw, Dennis Sylvester
2014 conf
VLSIC
Sechang Oh, Wanyeong Jung, Kaiyuan Yang, David T. Blaauw, Dennis Sylvester
2014 conf
ISSCC
Kaiyuan Yang, David Fick, Michael B. Henry, Yoonmyung Lee, David T. Blaauw, Dennis Sylvester
2012 C conf
ISCAS
Qing Jin, Kaiyuan Yang, Chunyuan Zhou, Dongxu Yang, Lei Zhang, Yan Wang, Zhiping Yu, Weidong Geng
2012 conf
ISQED
Kaiyuan Yang, Dae Hyun Kim, Sung Kyu Lim
redb/extractors/js_extractors/js_strings.py
← Index redb/extractors/js_extractors/js_strings.py python
import base64
import bisect
import inspect
import re
from datetime import datetime, timezone
from typing import Any

from redb.extractors.enum import Tag
from redb.extractors.js_extractor import JSExtractor
from redb.extractors.js_extractors.js_patterns import STRING_PATTERNS, line_offsets

# Local aliases for the compiled patterns this extractor uses. Defined and
# compiled exactly once in js_patterns.STRING_PATTERNS.
_HEX_STRING_RE = STRING_PATTERNS["hex_escape_seq"]
_UNICODE_STRING_RE = STRING_PATTERNS["unicode_escape_seq"]
_CHARCODE_RE = STRING_PATTERNS["charcode_call"]
_BASE64_STRING_RE = STRING_PATTERNS["base64_quoted"]
_CONCAT_STRING_RE = STRING_PATTERNS["concat_chain"]

# Tokeniser used inside _reconstruct_concat to pull each quoted part out of a
# matched concat chain. Compiled once at module load (was recompiled on every
# concat match before).
_CONCAT_TOKEN_RE = re.compile(r'["\']([^"\']*)["\']')


class JSStringsExtractor(JSExtractor):

    def __init__(
        self, filepath, log, exporters=None, index_prefix=None,
        known_benign=False, known_malicious=False, source=None, context=None,
    ):
        super().__init__(
            filepath, log, exporters, index_prefix,
            known_benign, known_malicious, source, context=context,
        )
        self.string_findings = None
        self.log.debug(inspect.currentframe().f_code.co_name)

    def tag(self):
        return Tag.JS_STRINGS.value

    def _decode_hex_string(self, hex_str):
        """Decode \\x41\\x42 style hex strings."""
        try:
            # Remove \\x prefix and decode
            clean = hex_str.replace('\\x', '')
            return bytes.fromhex(clean).decode('utf-8', errors='replace')
        except Exception:
            return None

    def _decode_unicode_string(self, uni_str):
        """Decode \\u0041\\u0042 style unicode strings."""
        try:
            return uni_str.encode('utf-8').decode('unicode_escape')
        except Exception:
            return None

    def _decode_charcode(self, charcode_str):
        """Decode String.fromCharCode(72, 101, 108, ...) sequences."""
        try:
            codes = [int(c.strip()) for c in charcode_str.split(',') if c.strip().isdigit()]
            return ''.join(chr(c) for c in codes if 0 <= c <= 0x10FFFF)
        except Exception:
            return None

    def _decode_base64(self, b64_str):
        """Attempt to decode base64 string."""
        try:
            decoded = base64.b64decode(b64_str)
            # Check if result is printable text
            text = decoded.decode('utf-8', errors='strict')
            # Only return if it looks like text (>80% printable)
            printable = sum(1 for c in text if c.isprintable() or c in '\n\r\t')
            if printable / len(text) > 0.8:
                return text
        except Exception:
            pass
        return None

    def _reconstruct_concat(self, concat_match):
        """Reconstruct concatenated string parts."""
        try:
            parts = _CONCAT_TOKEN_RE.findall(concat_match)
            return ''.join(parts)
        except Exception:
            return None

    def _find_line_number(self, match_start):
        """1-indexed line number for `match_start`, looked up in O(log L) via
        bisect over `self._line_offsets` (built once per extract() call).

        Replaces the historical `self.js_source[:match_start].count('\\n') + 1`
        which was O(N) per call and quadratic across all matches in a sample.
        """
        return bisect.bisect_right(self._line_offsets, match_start)

    def _scan_text(self, text):
        """Run every encoded-string pattern over `text` and return a list of
        finding dicts. Stateless apart from the per-call `_line_offsets` cache,
        which `_find_line_number` reads — callers must reset it before invoking
        this so line numbers reference the text being scanned, not the previous
        one.
        """
        findings = []

        # Hex-encoded strings
        for m in _HEX_STRING_RE.finditer(text):
            raw = m.group()
            decoded = self._decode_hex_string(raw)
            if decoded and len(decoded) >= 4:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'hex',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # Unicode-encoded strings
        for m in _UNICODE_STRING_RE.finditer(text):
            raw = m.group()
            decoded = self._decode_unicode_string(raw)
            if decoded and len(decoded) >= 3:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'unicode',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # String.fromCharCode sequences
        for m in _CHARCODE_RE.finditer(text):
            raw = m.group()
            decoded = self._decode_charcode(m.group(1))
            if decoded and len(decoded) >= 4:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'charcode',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # Base64-encoded strings
        for m in _BASE64_STRING_RE.finditer(text):
            raw = m.group(0)
            b64_val = m.group(1)
            decoded = self._decode_base64(b64_val)
            if decoded and len(decoded) >= 10:
                findings.append({
                    'string': decoded[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'base64',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(decoded),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(decoded),
                })

        # Concatenated strings (reassembled)
        for m in _CONCAT_STRING_RE.finditer(text):
            raw = m.group()
            reconstructed = self._reconstruct_concat(raw)
            if reconstructed and len(reconstructed) >= 20:
                findings.append({
                    'string': reconstructed[:4000],
                    'string_raw': raw[:4000],
                    'string_encoding': 'concat',
                    'string_offset': self._find_line_number(m.start()),
                    'string_length': len(reconstructed),
                    'string_raw_length': len(raw),
                    'string_entropy': self._calculate_text_entropy(reconstructed),
                })

        return findings

    def extract(self):
        src = self.js_source
        if not src:
            return None

        # Pass 1: raw source. _line_offsets is keyed off whichever text is
        # currently being scanned so _find_line_number resolves to that text.
        self._line_offsets = line_offsets(src)
        findings = self._scan_text(src)

        # Pass 2: deobfuscated text, when the deobfuscator produced something
        # meaningfully different. Same patterns, but a different surface — for
        # samples where the encoded payload is hidden behind an outer wrapper
        # (e.g. array.join() + eval in Vjw0rm/WSH-RAT) only this pass yields
        # any rows at all.
        deobf_text, _ = self._context.deobfuscated
        if deobf_text and deobf_text != src:
            self._line_offsets = line_offsets(deobf_text)
            findings.extend(self._scan_text(deobf_text))

        if not findings:
            return None

        # Deduplicate by decoded string value (raw pass wins on collision: it
        # comes first in `findings`). A string that surfaces only in the
        # deobfuscated text still gets persisted, which is the whole point of
        # the second pass.
        seen_values = set()
        deduped = []
        for f in findings:
            val_key = f['string'][:100]
            if val_key not in seen_values:
                seen_values.add(val_key)
                deduped.append(f)

        self.string_findings = deduped[:500]  # Limit per file
        # Publish to the shared context so post-loop consumers (notably the IOC
        # plumbing in workers.py) can scrape the decoded strings without
        # holding a reference to this extractor instance.
        self._context.decoded_strings = self.string_findings
        return self.string_findings

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ClickHouseExporter":
            if not self.string_findings:
                return None

            data = []
            for f in self.string_findings:
                data.append([
                    self.sha256,
                    f['string'],
                    f['string_raw'],
                    f['string_encoding'],
                    f['string_offset'],
                    f['string_length'],
                    f['string_raw_length'],
                    f['string_entropy'],
                ])

            column_names = [
                "sha256",
                "string",
                "string_raw",
                "string_encoding",
                "string_offset",
                "string_length",
                "string_raw_length",
                "string_entropy",
            ]

            column_type_names = [
                "FixedString(64)",
                "String",
                "String",
                "LowCardinality(String)",
                "UInt64",
                "UInt32",
                "UInt32",
                "Float32",
            ]

            return (data, column_names, column_type_names)

    def get_clickhouse_table(self) -> str:
        return "code_binja_strings_raw"