Man Lin

91 papers A* 1A 1B 4C 5Misc 4Journal 55Unranked 20
YearRankTypeTitle / Venue / Authors
2025 J jnl
IEEE Trans. Sustain. Comput.
Haoyu Wang, Xinyi Li, Ti Zhou, Man Lin
2025 J jnl
IEEE Trans. Sustain. Comput.
Xinyi Li, Ti Zhou, Haoyu Wang, Man Lin
2025 J jnl
IEEE Trans. Dependable Secur. Comput.
Zijie Lou, Gang Cao, Man Lin, Lifang Yu, Shaowei Weng
2025 J jnl
IEEE Signal Process. Lett.
Zijie Lou, Gang Cao, Man Lin
2025 A* conf
AAAI
Delong Zeng, Ying Shen, Man Lin, Zihao Yi, Jiarui Ouyang
2024 conf
PRCV (10)
Jianfa Bai, Man Lin, Gang Cao, Zijie Lou
2024 J jnl
CoRR
Jianfa Bai, Man Lin, Gang Cao
2024 J jnl
Knowl. Based Syst.
Enze Zha, De-Long Zeng, Man Lin, Ying Shen
2024 J jnl
CoRR
Haoyu Wang, Xinyi Li, Ti Zhou, Man Lin
2024 J jnl
IEEE Trans. Sustain. Comput.
Mir Ashraf Uddin, Man Lin, Laurence T. Yang
2024 J jnl
CoRR
Xinyi Li, Ti Zhou, Haoyu Wang, Man Lin
2024 conf
ICANN (9)
Man Lin, De-Long Zeng, Jiarui Ouyang, Ying Shen
2024 J jnl
J. Electronic Imaging
Man Lin, Gang Cao, Zijie Lou, Chi Zhang
2024 J jnl
CoRR
Zijie Lou, Gang Cao, Man Lin
2024 J jnl
CoRR
Zijie Lou, Gang Cao, Man Lin
2023 J jnl
Eng. Appl. Artif. Intell.
Zijie Lou, Gang Cao, Man Lin
2023 J jnl
CoRR
Ti Zhou, Man Lin
2023 J jnl
J. Syst. Archit.
Ti Zhou, Man Lin
2023 J jnl
IEEE Internet Things J.
Saroj Kumar Panda, Man Lin, Ti Zhou
2023 J jnl
CoRR
Man Lin, Gang Cao, Zijie Lou
2022 J jnl
CoRR
Zijie Lou, Gang Cao, Man Lin
2022 J jnl
IEEE Trans. Netw. Sci. Eng.
Ti Zhou, Man Lin
2022 J jnl
J. Syst. Archit.
Deepak Ramegowda, Man Lin
2022 conf
CI4PM/PAI@WCCI
Deepak Ramegowda, Man Lin
2021 conf
SmartWorld/SCALCOM/UIC/ATC/IOP/SCI
Deepak Ramegowda, Man Lin
2020 J jnl
Future Gener. Comput. Syst.
Jing Zeng, Laurence T. Yang, Man Lin, Huansheng Ning, Jianhua Ma
2020 J jnl
IEEE Trans. Ind. Informatics
Hui Huang, Man Lin, Laurence T. Yang, Qingchen Zhang
2019 J jnl
IEEE Trans. Serv. Comput.
Qingchen Zhang, Man Lin, Laurence T. Yang, Zhikui Chen, Samee U. Khan, Peng Li
2019 J jnl
IEEE Trans. Sustain. Comput.
Huazhong Liu, Jie Pu, Laurence T. Yang, Man Lin, Dexiang Yin, Yimu Guo, Xingyu Chen
2019 J jnl
Inf. Fusion
Xianjun Deng, Yalan Jiang, Laurence T. Yang, Man Lin, Lingzhi Yi, Minghua Wang
2019 J jnl
IEEE Internet Things J.
Xianjun Deng, Minliang Xu, Laurence T. Yang, Man Lin, Lingzhi Yi, Minghua Wang
2019 J jnl
IEEE Trans. Sustain. Comput.
Qingchen Zhang, Man Lin, Laurence T. Yang, Zhikui Chen, Peng Li
2019 J jnl
ACM Trans. Embed. Comput. Syst.
Xiaokang Wang, Laurence T. Yang, Hongguo Li, Man Lin, Jianjun Han, Bernady O. Apduhan
2019 J jnl
IEEE Internet Things J.
Minghua Wang, Lihua Zhu, Laurence T. Yang, Man Lin, Xianjun Deng, Lingzhi Yi
2018 J jnl
IEEE Netw.
Huazhong Liu, Laurence T. Yang, Man Lin, Dexiang Yin, Yimu Guo
2018 J jnl
IEEE Trans. Ind. Informatics
Xianjun Deng, Zujun Tang, Laurence Tianruo Yang, Man Lin, Bang Wang
2018 J jnl
IEEE Trans. Sustain. Comput.
Dakai Zhu, Muhammad Shafique, Man Lin, Sudeep Pasricha
2018 J jnl
Inf. Sci.
Fakhruddin Muhammad Mahbub Ul Islam, Man Lin, Laurence T. Yang, Kim-Kwang Raymond Choo
2018 J jnl
IEEE Trans. Big Data
Huazhong Liu, Baoshun Liu, Laurence T. Yang, Man Lin, Yuhui Deng, Kashif Bilal, Samee U. Khan
2017 conf
iThings/GreenCom/CPSCom/SmartData
Hui Huang, Man Lin, Qingchen Zhang
2017 J jnl
IEEE Syst. J.
Fakhruddin Muhammad Mahbub Ul Islam, Man Lin
2017 J jnl
ACM Trans. Embed. Comput. Syst.
Jing Zeng, Laurence T. Yang, Man Lin, Zili Shao, Dakai Zhu
2015 conf
HPCC/CSS/ICESS
Fakhruddin Muhammad Mahbub Ul Islam, Man Lin
2015 J jnl
IEEE Trans. Parallel Distributed Syst.
Jian-Jun Han, Man Lin, Dakai Zhu, Laurence T. Yang
2015 J jnl
IEEE Trans. Comput. Soc. Syst.
Mianxiong Dong, Rajiv Ranjan, Albert Y. Zomaya, Man Lin
2015 J jnl
IEEE Trans. Comput. Soc. Syst.
Mianxiong Dong, Rajiv Ranjan, Albert Y. Zomaya, Man Lin
2014 J jnl
IEEE Trans. Emerg. Top. Comput.
Liwei Kuang, Fei Hao, Laurence T. Yang, Man Lin, Changqing Luo, Geyong Min
2014 J jnl
IEEE Trans. Serv. Comput.
Fei Hao, Geyong Min, Jinjun Chen, Fei Wang, Man Lin, Changqing Luo, Laurence T. Yang
2014 J jnl
J. Supercomput.
Chenghua Li, Man Lin, Laurence T. Yang, Chen Ding
2014 conf
HPCC/CSS/ICESS
Fakhruddin Muhammad Mahbub Ul Islam, Man Lin
2014 J jnl
IEEE Trans. Parallel Distributed Syst.
Fei Hao, Geyong Min, Man Lin, Changqing Luo, Laurence T. Yang
2014 J jnl
Int. J. Parallel Program.
Chenghua Li, Laurence T. Yang, Man Lin
2014 J jnl
IEEE Intell. Syst.
Gang Pan, Li Zhang, Zhaohui Wu, Shijian Li, Laurence T. Yang, Man Lin, Yuanchun Shi
2014 J jnl
J. Supercomput.
Mianxiong Dong, Kaoru Ota, Man Lin, Zunyi Tang, Suguo Du, Haojin Zhu
2013 conf
HPCC/EUC
Chin-Feng Lai, Man Lin, Shih-Yeh Chen, Han-Chieh Chao, Shin-Feng Lin
2013 J jnl
IEEE Trans. Emerg. Top. Comput.
Man Lin, Yongwen Pan, Laurence T. Yang, Minyi Guo, Nenggan Zheng
2012 conf
CSE
Chin-Feng Lai, Man Lin, Yonggang Wen, Yi-Wei Ma, Jiann-Liang Chen
2012 conf
ICA3PP (1)
Liu Yang, Man Lin, Laurence Tianruo Yang
2011 conf
iThings/CPSCom
Wei Cheng, Nenggan Zheng, Man Lin, Laurence Tianruo Yang
2011 C conf
UIC
Yongwen Pan, Man Lin, Laurence Tianruo Yang
2011 J jnl
IEEE Intell. Syst.
Gang Pan, Yuqiong Xu, Zhaohui Wu, Shijian Li, Laurence Tianruo Yang, Man Lin, Zhong Liu
2010 J jnl
IEEE Trans. Inf. Technol. Biomed.
Nenggan Zheng, Zhaohui Wu, Man Lin, Laurence Tianruo Yang
2010 J jnl
IEEE Trans. Syst. Man Cybern. Part C
Nenggan Zheng, Zhaohui Wu, Man Lin, Laurence Tianruo Yang, Gang Pan
2009 conf
CCECE
Yongwen Pan, Man Lin
2009 J jnl
Intell. Autom. Soft Comput.
Zhigang Gao, Zhaohui Wu, Man Lin
2009 B conf
RTCSA
Liu Yang, Man Lin, Laurence Tianruo Yang
2009 conf
ICESS
Liu Yang, Man Lin
2009 J jnl
IEEE Trans. Ind. Informatics
Man Lin, Li Xu, Laurence Tianruo Yang, Xiao Qin, Nenggan Zheng, Zhaohui Wu, Meikang Qiu
2008 J jnl
J. Parallel Distributed Comput.
Meikang Qiu, Edwin Hsing-Mean Sha, Meilin Liu, Man Lin, Shaoxiong Hua, Laurence Tianruo Yang
2007 conf
ICESS
Zhigang Gao, Zhaohui Wu, Man Lin
2007 Misc conf
VLSI Design
Nenggan Zheng, Zhaohui Wu, Man Lin, Qijia Wang
2007 C conf
HPCC
Man Lin, Chen Ding
2006 C conf
EUC
Laurence Tianruo Yang, Li Xu, Man Lin, John P. Quinn
2006 C conf
ATC
Laurence Tianruo Yang, Li Xu, Man Lin, John P. Quinn
2006 C conf
DASC
Na Guo, Laurence Tianruo Yang, Man Lin, John P. Quinn
2006 A conf
IPDPS
Nenggan Zheng, Zhaohui Wu, Man Lin, Minde Zhao
2006 J jnl
Int. J. High Perform. Comput. Netw.
Tao Xie, Xiao Qin, Andrew H. Sung, Man Lin, Laurence Tianruo Yang
2006 B conf
ARES
Man Lin, Laurence Tianruo Yang
2005 B conf
AINA
Guozhen Zhang, Qun Jin, Man Lin
2005 J jnl
Parallel Process. Lett.
Man Lin, Sai Man Ng
2005 ed.
ICESS
Laurence Tianruo Yang, Xingshe Zhou, Wei Zhao, Zhaohui Wu, Yian Zhu, Man Lin
2005 Misc conf
PDPTA
Li Xu, Laurence Tianruo Yang, Man Lin
2005 Misc conf
PDPTA
Zhen Lin, Laurence Tianruo Yang, Man Lin
2005 conf
ICESS
Laurence Tianruo Yang, Li Xu, Man Lin
2001 conf
PDCS
Laurence Tianruo Yang, Man Lin
2000 conf
ICPADS Workshops
Man Lin, Lars Karlsson, Laurence Tianruo Yang
1999 B conf
RTCSA
Man Lin, Laurence Tianruo Yang
1999 conf
Ershov Memorial Conference
Man Lin, Jacek Malec, Simin Nadjm-Tehrani
1999 conf
HSCC
Man Lin
1997 Misc conf
ICASSP
Laurence Tianruo Yang, Man Lin
1997 conf
ASIAN
Man Lin, Jacek Malec, Simin Nadjm-Tehrani
redb/extractors/js_extractors/js_patterns.py
← Index redb/extractors/js_extractors/js_patterns.py python
"""Canonical, compiled JavaScript regex patterns shared across JS extractors.

All suspicious-API patterns and the few feature-only patterns live here so each
expression is compiled exactly once per Python process and so any pattern that
was previously duplicated across `js_features.py` and `js_suspicious_apis.py`
now resolves to a single shared compiled object.

JavaScript is case-sensitive at runtime, but every suspicious-API pattern matches
either a literal-case identifier (`\\beval\\s*\\(`, `String\\.fromCharCode`, etc.)
or a string-quoted token (`"powershell"`). Compiling them with `re.IGNORECASE`
matches the historical behaviour of `JSSuspiciousAPIsExtractor` and is safe for
the patterns that historically came from `JSFeaturesExtractor` — those literals
are spelled in real-world JS exactly as written.

`scan_source()` is the entry point used by extractors: it walks the source once
per pattern using the pre-compiled regexes and returns a flat
`{name: {"count": N, "lines": [unique_line_numbers_sorted]}}` dict. Both
`JSFeaturesExtractor` and `JSSuspiciousAPIsExtractor` consume the same dict so
the per-pattern × per-line loops they used to run independently collapse to a
single shared scan.
"""

import bisect
import re
from typing import Dict, Iterable, List, Mapping

_FLAGS = re.IGNORECASE

# Canonical compiled patterns, keyed by their human-readable name. The name is
# also the value emitted into `redb_js_suspicious_apis.api_name`.
PATTERNS = {
    # ---- code execution ----
    "eval": re.compile(r"\beval\s*\(", _FLAGS),
    "Function constructor": re.compile(r"\bnew\s+Function\s*\(", _FLAGS),
    "execScript": re.compile(r"\bexecScript\s*\(", _FLAGS),
    "document.write": re.compile(r"\bdocument\.write(?:ln)?\s*\(", _FLAGS),
    "innerHTML assignment": re.compile(r"\.innerHTML\s*=", _FLAGS),
    "outerHTML assignment": re.compile(r"\.outerHTML\s*=", _FLAGS),
    "insertAdjacentHTML": re.compile(r"\.insertAdjacentHTML\s*\(", _FLAGS),
    # ---- network ----
    "XMLHttpRequest": re.compile(r"\bnew\s+XMLHttpRequest\b", _FLAGS),
    "fetch": re.compile(r"\bfetch\s*\(", _FLAGS),
    "WebSocket": re.compile(r"\bnew\s+WebSocket\s*\(", _FLAGS),
    "navigator.sendBeacon": re.compile(r"\bnavigator\.sendBeacon\s*\(", _FLAGS),
    "ActiveXObject XMLHTTP": re.compile(
        r"ActiveXObject\s*\(\s*[\"\'](?:MSXML2\.XMLHTTP|Microsoft\.XMLHTTP)", _FLAGS
    ),
    "require network module": re.compile(
        r"require\s*\(\s*[\"\'](?:http|https|net|dgram)[\"\']", _FLAGS
    ),
    "axios": re.compile(r"\baxios\b", _FLAGS),
    # ---- filesystem ----
    "require fs": re.compile(r"require\s*\(\s*[\"\']fs[\"\']", _FLAGS),
    "require path": re.compile(r"require\s*\(\s*[\"\']path[\"\']", _FLAGS),
    "FileSystemObject": re.compile(r"Scripting\.FileSystemObject", _FLAGS),
    "ADODB.Stream": re.compile(r"ADODB\.Stream", _FLAGS),
    "Shell.Application": re.compile(r"Shell\.Application", _FLAGS),
    "WScript.CreateObject": re.compile(r"WScript\.CreateObject", _FLAGS),
    # ---- process ----
    "require child_process": re.compile(r"require\s*\(\s*[\"\']child_process[\"\']", _FLAGS),
    "child_process exec": re.compile(r"child_process\.(?:exec|spawn|execFile|fork)\s*\(", _FLAGS),
    "WScript.Shell": re.compile(r"WScript\.Shell", _FLAGS),
    "WScript.Shell.Run": re.compile(r"\.Run\s*\(", _FLAGS),
    "WScript.Shell.Exec": re.compile(r"\.Exec\s*\(", _FLAGS),
    "ShellExecute": re.compile(r"\bShellExecute\b", _FLAGS),
    "PowerShell reference": re.compile(r"[\"\']powershell[\"\']", _FLAGS),
    "cmd.exe reference": re.compile(r"[\"\']cmd\.exe[\"\']", _FLAGS),
    "require os": re.compile(r"require\s*\(\s*[\"\']os[\"\']", _FLAGS),
    # ---- registry ----
    "RegRead": re.compile(r"\.RegRead\s*\(", _FLAGS),
    "RegWrite": re.compile(r"\.RegWrite\s*\(", _FLAGS),
    "RegDelete": re.compile(r"\.RegDelete\s*\(", _FLAGS),
    "StdRegProv": re.compile(r"StdRegProv", _FLAGS),
    # ---- crypto / encoding ----
    "atob": re.compile(r"\batob\s*\(", _FLAGS),
    "btoa": re.compile(r"\bbtoa\s*\(", _FLAGS),
    "String.fromCharCode": re.compile(r"String\.fromCharCode\s*\(", _FLAGS),
    "unescape": re.compile(r"\bunescape\s*\(", _FLAGS),
    "decodeURIComponent": re.compile(r"\bdecodeURIComponent\s*\(", _FLAGS),
    "Buffer.from": re.compile(r"Buffer\.from\s*\(", _FLAGS),
    "crypto module": re.compile(r"crypto\.create(?:Cipher|Decipher|Hash|Hmac)", _FLAGS),
    # ---- DOM manipulation ----
    "document.forms": re.compile(r"document\.forms", _FLAGS),
    "document.cookie": re.compile(r"document\.cookie", _FLAGS),
    "querySelector sensitive input": re.compile(
        r"document\.querySelector\s*\([^)]*(?:password|credit|card|cvv|ssn)", _FLAGS
    ),
    "submit event listener": re.compile(r"addEventListener\s*\(\s*[\"\']submit", _FLAGS),
    "createElement script/iframe": re.compile(
        r"\.createElement\s*\(\s*[\"\'](?:script|iframe)", _FLAGS
    ),
    "dynamic script src": re.compile(r"\.src\s*=\s*[\"\'](?:https?://|//)", _FLAGS),
}

# Pattern name -> category (one of code_execution / network / filesystem /
# process / registry / crypto_encoding / dom_manipulation).
CATEGORIES = {
    "eval": "code_execution",
    "Function constructor": "code_execution",
    "execScript": "code_execution",
    "document.write": "code_execution",
    "innerHTML assignment": "code_execution",
    "outerHTML assignment": "code_execution",
    "insertAdjacentHTML": "code_execution",
    "XMLHttpRequest": "network",
    "fetch": "network",
    "WebSocket": "network",
    "navigator.sendBeacon": "network",
    "ActiveXObject XMLHTTP": "network",
    "require network module": "network",
    "axios": "network",
    "require fs": "filesystem",
    "require path": "filesystem",
    "FileSystemObject": "filesystem",
    "ADODB.Stream": "filesystem",
    "Shell.Application": "filesystem",
    "WScript.CreateObject": "filesystem",
    "require child_process": "process",
    "child_process exec": "process",
    "WScript.Shell": "process",
    "WScript.Shell.Run": "process",
    "WScript.Shell.Exec": "process",
    "ShellExecute": "process",
    "PowerShell reference": "process",
    "cmd.exe reference": "process",
    "require os": "process",
    "RegRead": "registry",
    "RegWrite": "registry",
    "RegDelete": "registry",
    "StdRegProv": "registry",
    "atob": "crypto_encoding",
    "btoa": "crypto_encoding",
    "String.fromCharCode": "crypto_encoding",
    "unescape": "crypto_encoding",
    "decodeURIComponent": "crypto_encoding",
    "Buffer.from": "crypto_encoding",
    "crypto module": "crypto_encoding",
    "document.forms": "dom_manipulation",
    "document.cookie": "dom_manipulation",
    "querySelector sensitive input": "dom_manipulation",
    "submit event listener": "dom_manipulation",
    "createElement script/iframe": "dom_manipulation",
    "dynamic script src": "dom_manipulation",
}

# Patterns consumed only by JSFeaturesExtractor (no category, never surfaced as
# a suspicious-API row). Kept here so every JS regex is compiled in one place.
FEATURE_PATTERNS = {
    "hex_escape": re.compile(r"\\x[0-9a-fA-F]{2}"),
    "unicode_escape": re.compile(r"\\u[0-9a-fA-F]{4}"),
    "base64_string": re.compile(r"[A-Za-z0-9+/]{40,}={0,2}"),
    # decodeURI matches BOTH decodeURI and decodeURIComponent. The latter is also
    # a suspicious-API pattern in PATTERNS; this broader form is what the
    # `decodeuri_count` feature column has historically counted.
    "decodeURI": re.compile(r"\b(?:decodeURI|decodeURIComponent)\s*\(", _FLAGS),
    "settimeout_setinterval": re.compile(r"\b(?:setTimeout|setInterval)\s*\(", _FLAGS),
    "function_decl": re.compile(r"\bfunction\s+\w+\s*\(|\bfunction\s*\("),
    "var_decl": re.compile(r"\b(?:var|let|const)\s+"),
    "string_concat": re.compile(r"[\"\'][\s]*\+[\s]*[\"\']"),
    "comment": re.compile(r"//.*?$|/\*[\s\S]*?\*/", re.MULTILINE),
    "long_string": re.compile(r"[\"\']([^\"\']{256,})[\"\']"),
    "array_function_call": re.compile(r"\[(?:0x[0-9a-f]+|[\d]+)\]\s*\(", _FLAGS),
}

# Patterns consumed only by JSStringsExtractor for encoded-string discovery.
# Scoped to *hidden* strings only — patterns whose decoded form is not visible
# to a substring search over the raw text. Plain long literals are not
# extracted here because they're already preserved in code_text_content and
# scraped by the IOC pipeline over text_raw / text_normalized.
#
# Distinct from FEATURE_PATTERNS even where the names rhyme:
#   FEATURE_PATTERNS["hex_escape"] / ["unicode_escape"]   -> single escape
#   STRING_PATTERNS["hex_escape_seq"] / ["unicode_escape_seq"] -> 4+ / 3+ in a row
#   FEATURE_PATTERNS["base64_string"]                     -> bare base64 token
#   STRING_PATTERNS["base64_quoted"]                      -> base64 inside JS quotes
# These do not share match objects with the suspicious-API or feature scans, so
# they are not folded into JSContext.scan; the strings extractor walks them
# itself (one finditer per pattern, with shared line-offset bisect in #4b).
STRING_PATTERNS = {
    "hex_escape_seq": re.compile(r"(?:\\x[0-9a-fA-F]{2}){4,}"),
    "unicode_escape_seq": re.compile(r"(?:\\u[0-9a-fA-F]{4}){3,}"),
    "charcode_call": re.compile(r"String\.fromCharCode\s*\(\s*([\d,\s]+)\s*\)"),
    "base64_quoted": re.compile(r"[\"\']([A-Za-z0-9+/]{40,}={0,2})[\"\']"),
    "concat_chain": re.compile(r"(?:[\"\'][^\"\']+[\"\']\s*\+\s*){3,}[\"\'][^\"\']+[\"\']"),
}


def line_offsets(source: str) -> List[int]:
    """Sorted list of byte offsets for every newline in `source`, plus a final
    sentinel of len(source). Used to translate match offsets into 1-indexed
    line numbers via bisect.
    """
    offsets = [-1]  # so that bisect_right of offset 0 returns line 1
    push = offsets.append
    idx = source.find("\n")
    while idx != -1:
        push(idx)
        idx = source.find("\n", idx + 1)
    return offsets


def _scan_one(
    pattern: "re.Pattern[str]", source: str, offsets: List[int]
) -> Dict[str, object]:
    """Run a single compiled pattern over `source` and return count + unique lines."""
    count = 0
    seen_lines: "set[int]" = set()
    for m in pattern.finditer(source):
        count += 1
        seen_lines.add(bisect.bisect_right(offsets, m.start()))
    if not count:
        return None  # type: ignore[return-value]
    return {"count": count, "lines": sorted(seen_lines)}


def scan_source(
    source: str,
    patterns: Iterable[Mapping[str, "re.Pattern[str]"]] = (PATTERNS, FEATURE_PATTERNS),
) -> Dict[str, Dict[str, object]]:
    """Scan `source` against every compiled pattern in `patterns`.

    Returns a dict keyed by pattern name. Each entry has:
        "count": total number of matches in the source
        "lines": sorted list of unique 1-indexed line numbers where the pattern
                 matched (deduplicated — multiple matches on the same line
                 collapse to one entry, preserving the historical
                 line-set semantics of JSSuspiciousAPIsExtractor)
    Patterns with zero matches are absent from the dict; callers should default
    to {"count": 0, "lines": []}.
    """
    if not source:
        return {}
    offsets = line_offsets(source)
    results: Dict[str, Dict[str, object]] = {}
    for table in patterns:
        for name, pat in table.items():
            entry = _scan_one(pat, source, offsets)
            if entry is not None:
                results[name] = entry
    return results