Isi Mitrani

120 papers A* 6A 1B 13C 1Misc 13Journal 50Unranked 33
YearRankTypeTitle / Venue / Authors
2025 B conf
MASCOTS
Paul D. Ezhilchelvan, Isi Mitrani, Jim Webber
2024 J jnl
ACM Trans. Model. Perform. Evaluation Comput. Syst.
Paul D. Ezhilchelvan, Isi Mitrani
2024 conf
EPEW
Ye Liu, Paul D. Ezhilchelvan, Isi Mitrani
2023 conf
QEST
Paul D. Ezhilchelvan, Isi Mitrani, Jim Webber
2023 conf
EPEW
Paul D. Ezhilchelvan, Isi Mitrani, Jim Webber, Yingming Wang
2022 B conf
ICPE
Simonetta Balsamo, Andrea Marin, Isi Mitrani
2022 B conf
SRDS
Jack Waudby, Paul D. Ezhilchelvan, Isi Mitrani, Jim Webber
2022 conf
EPEW
Paul D. Ezhilchelvan, Isi Mitrani
2022 conf
MedComNet
Simonetta Balsamo, Ivan Malakhov, Andrea Marin, Isi Mitrani
2021 J jnl
CoRR
Andrea Marin, Isi Mitrani
2021 J jnl
Simul. Model. Pract. Theory
Paul D. Ezhilchelvan, Isi Mitrani
2021 B conf
ICPE
Simonetta Balsamo, Andrea Marin, Isi Mitrani, Nicola Rebagliati
2020 conf
PaPoC@EuroSys
Jack Waudby, Paul D. Ezhilchelvan, Jim Webber, Isi Mitrani
2019 B conf
MASCOTS
Tom Cooper, Paul D. Ezhilchelvan, Isi Mitrani
2019 conf
EPEW
Paul D. Ezhilchelvan, Isi Mitrani, Jack Waudby, Jim Webber
2019 J jnl
CoRR
Jim Webber, Paul D. Ezhilchelvan, Isi Mitrani
2018 conf
QEST
Andrea Marin, Isi Mitrani, B. Maryam Elahi, Carey Williamson
2018 conf
EPEW
Paul D. Ezhilchelvan, Isi Mitrani, Jim Webber
2017 J jnl
IEEE Trans. Cloud Comput.
Paul Devadoss Ezhilchelvan, Isi Mitrani
2017 conf
QEST
Paul D. Ezhilchelvan, Isi Mitrani
2017 J jnl
Simul. Model. Pract. Theory
Paul D. Ezhilchelvan, Isi Mitrani
2016 B conf
MASCOTS
Paul D. Ezhilchelvan, Isi Mitrani
2015 conf
EPEW
Paul D. Ezhilchelvan, Isi Mitrani
2014 conf
EPEW
Andrew Stephen McGough, Isi Mitrani
2013 J jnl
Ann. Oper. Res.
Isi Mitrani
2012 J jnl
SIGMETRICS Perform. Evaluation Rev.
Michele Mazzucco, Isi Mitrani
2012 conf
PASM/PDMC
K. Aidarov, Paul D. Ezhilchelvan, Isi Mitrani
2012 J jnl
IET Comput. Digit. Tech.
Fei Xia, Andrey Mokhov, Yu Zhou, Yifan Chen, Isi Mitrani, Delong Shang, Danil Sokolov, Alexandre Yakovlev
2012 conf
EPEW/UKPEW
Isi Mitrani
2011 J jnl
CoRR
Michele Mazzucco, Isi Mitrani, Mike Fisher, Paul McKee
2011 J jnl
Perform. Evaluation
Isi Mitrani
2011 ch.
Network Performance Engineering
Isi Mitrani
2010 J jnl
Comput. J.
Isi Mitrani
2010 C conf
ISCAS
Yuan Chen, Isi Mitrani, Delong Shang, Fei Xia, Alexandre Yakovlev
2009 J jnl
Ad Hoc Networks
Dave E. Cooper, Paul D. Ezhilchelvan, Isi Mitrani
2009 J jnl
Perform. Evaluation
Joris Slegers, Isi Mitrani, Nigel Thomas
2009 B conf
OPODIS
Paul D. Ezhilchelvan, Dylan Clarke, Isi Mitrani, Santosh K. Shrivastava
2009 J jnl
Comput. Sci. Res. Dev.
Michele Mazzucco, Isi Mitrani, Jennie Palmer, Mike Fisher, Paul McKee
2009 J jnl
Ann. Oper. Res.
Joris Slegers, Isi Mitrani, Nigel Thomas
2008 B conf
MASCOTS
Michele Mazzucco, Isi Mitrani, Mike Fisher, Paul McKee
2008 J jnl
Ann. Oper. Res.
Simon P. Martin, Isi Mitrani
2008 conf
SIPEW
Joris Slegers, Nigel Thomas, Isi Mitrani
2007 conf
EPEW
Joris Slegers, Isi Mitrani, Nigel Thomas
2007 conf
EPEW
Isi Mitrani
2007 conf
ICE-B
Jennie Palmer, Isi Mitrani, Michele Mazzucco, Paul McKee, Mike Fisher
2007 conf
ECOWS
Michele Mazzucco, Isi Mitrani, Jennie Palmer, Mike Fisher, Paul McKee
2006 A conf
DSN
Jennie Palmer, Isi Mitrani
2006 conf
Annual Simulation Symposium
Giovanna Ferrari, Paul D. Ezhilchelvan, Isi Mitrani
2006 conf
ISPA Workshops
Joris Slegers, Isi Mitrani, Nigel Thomas
2005 J jnl
Perform. Evaluation
Isi Mitrani
2005 J jnl
J. Parallel Distributed Comput.
Jennie Palmer, Isi Mitrani
2005 B conf
MASCOTS
Dave E. Cooper, Paul D. Ezhilchelvan, Isi Mitrani, Einar Vollset
2004 conf
EuroNGI Workshop
Dave E. Cooper, Paul D. Ezhilchelvan, Isi Mitrani
2004 B conf
SRDS
Antonio Di Ferdinando, Paul D. Ezhilchelvan, Isi Mitrani
2004 conf
GRID
Mike Fisher, Charles Kubicek, Paul McKee, Isi Mitrani, Jennie Palmer, Rob Smith
2004 B conf
NETWORKING
Dave E. Cooper, Paul D. Ezhilchelvan, Isi Mitrani
2004 J jnl
Perform. Evaluation
Isi Mitrani, Philippe Robert
2004 conf
ICCSA (2)
Jennie Palmer, Isi Mitrani
2002 conf
Computer Performance Evaluation / TOOLS
L. Kumar, Manoj Misra, Isi Mitrani
2002 conf
Workshop on Software and Performance
Michael D. Hamilton, Paul McKee, Isi Mitrani
2002 J jnl
Perform. Evaluation
Andrew Stephen McGough, Isi Mitrani
2002 Misc conf
Performance
Isi Mitrani
2001 J jnl
Queueing Syst. Theory Appl.
Jean-François Dantzer, Isi Mitrani, Philippe Robert
2001 conf
HPCN Europe
Michael D. Hamilton, Paul McKee, Isi Mitrani
2000 B conf
PADS
Andrew Stephen McGough, Isi Mitrani
2000 conf
Computer Performance Evaluation / TOOLS
Michael D. Hamilton, Isi Mitrani
2000 J jnl
Perform. Evaluation
Andrew Stephen McGough, Isi Mitrani
1999 J jnl
J. Oper. Res. Soc.
P. S. Ansell, Kevin D. Glazebrook, Isi Mitrani, José Niño-Mora
1999 conf
MMB
Michael D. Hamilton, Bin Liu, Isi Mitrani
1999 J jnl
Perform. Evaluation
Manoj Misra, Isi Mitrani
1998 conf
ESM
Nigel Thomas, Isi Mitrani
1998 book
Probabilistic modelling, Second Edition.
Isi Mitrani
1996 J jnl
Perform. Evaluation
P. S. Ansell, Kevin D. Glazebrook, Isi Mitrani
1996 J jnl
ACM Trans. Model. Comput. Simul.
Albert G. Greenberg, Boris D. Lubachevsky, Isi Mitrani
1995 B conf
MASCOTS
Onno J. Boxma, Ger Koole, Isi Mitrani
1995 J jnl
Perform. Evaluation
Isi Mitrani, Ram Chakka
1994 J jnl
Ann. Oper. Res.
Debasis Mitra, Isi Mitrani
1994 J jnl
Theor. Comput. Sci.
Ram Chakka, Isi Mitrani
1994 J jnl
Perform. Evaluation
Isi Mitrani, Paul E. Wright
1993 J jnl
Queueing Syst. Theory Appl.
Isi Mitrani, Anatolii A. Puhalskii
1992 A* conf
SIGMETRICS
Ram Chakka, Isi Mitrani
1991 J jnl
Queueing Syst. Theory Appl.
Debasis Mitra, Isi Mitrani, K. G. Ramakrishnan, Judith B. Seery, Alan Weiss
1991 J jnl
ACM Trans. Comput. Syst.
Albert G. Greenberg, Boris D. Lubachevsky, Isi Mitrani
1991 J jnl
Oper. Res.
Debasis Mitra, Isi Mitrani
1991 J jnl
Queueing Syst. Theory Appl.
Debasis Mitra, Isi Mitrani
1991 conf
ICPP (3)
Albert G. Greenberg, Isi Mitrani
1990 J jnl
IEEE Trans. Parallel Distributed Syst.
Paul D. Ezhilchelvan, Isi Mitrani, Santosh K. Shrivastava
1990 Misc ed.
Performance
Peter J. B. King, Isi Mitrani, Rob Pooley
1990 A* conf
SIGMETRICS
Albert G. Greenberg, Boris D. Lubachevsky, Isi Mitrani
1990 Misc conf
WSC
Albert G. Greenberg, Boris D. Lubachevsky, Isi Mitrani
1989 A* conf
SIGMETRICS
Debasis Mitra, Isi Mitrani
1988 J jnl
Queueing Syst. Theory Appl.
Philippe Robert, Isi Mitrani, Peter J. B. King
1987 J jnl
Perform. Evaluation
Debasis Mitra, Isi Mitrani
1987 Misc conf
Performance
Albert G. Greenberg, Isi Mitrani, Larry Rudolph
1987 Misc conf
Performance
Philippe Robert, Isi Mitrani, Peter J. B. King
1987 J jnl
IEEE Trans. Computers
Peter J. B. King, Isi Mitrani
1987 J jnl
Queueing Syst. Theory Appl.
Isi Mitrani
1987 Misc conf
Performance
Edward G. Coffman Jr., Guy Fayolle, Isi Mitrani
1984 Misc conf
Performance
Debasis Mitra, Isi Mitrani
1983 conf
Computer Performance and Reliability
Isi Mitrani
1983 conf
Computer Performance and Reliability
Erol Gelenbe, Isi Mitrani
1983 J jnl
IEEE Trans. Computers
Isi Mitrani, Peter J. B. King
1983 Misc conf
Performance
Guy Fayolle, Peter J. B. King, Isi Mitrani
1983 J jnl
Commun. ACM
A. Chesnais, Erol Gelenbe, Isi Mitrani
1983 Misc conf
Performance
Guy Fayolle, R. Iasnogorodski, Isi Mitrani
1982 A* conf
SIGMETRICS
Erol Gelenbe, Isi Mitrani
1982 A* conf
SIGMETRICS
Peter J. B. King, Isi Mitrani
1981 J jnl
Perform. Evaluation
Isi Mitrani, Peter J. B. King
1981 J jnl
J. ACM
Kenneth C. Sevcik, Isi Mitrani
1980 J jnl
Oper. Res.
Edward G. Coffman Jr., Isi Mitrani
1980 Misc conf
Performance
Peter J. B. King, Isi Mitrani
1980 J jnl
J. ACM
Guy Fayolle, Isi Mitrani, R. Iasnogorodski
1980 Misc conf
Performance
Guy Fayolle, Peter J. B. King, Isi Mitrani
1979 J jnl
Commun. ACM
J. H. Hine, Isi Mitrani, Shalom Tsur
1979 Misc conf
Performance
Kenneth C. Sevcik, Isi Mitrani
1977 J jnl
Acta Informatica
Isi Mitrani, J. H. Hine
1976 Misc conf
Performance
J. H. Hine, Isi Mitrani, Shalom Tsur
1975 A* conf
SOSP
Edward G. Coffman Jr., Isi Mitrani
1972
Isi Mitrani
1972 J jnl
J. ACM
Isi Mitrani
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