From f2def8433717d57c65bd731df2bd42ea3bcd2f74 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Sun, 30 Apr 2023 14:59:50 +0200
Subject: [PATCH 01/67] Misc: Add script to accept `.expected` changes from CI
This script can be used to go over `codeql test run` expected/actual log
output from actions CI checks for a PR, and apply patches locally to
make the tests pass.
Designed for use by GitHub employees, since it needs access to internal
CI runs. Just run this tool while the branch for the PR is checked out!
You need the `gh` cli tool installed and authenticated.
Example can be seen in https://github.com/github/codeql/pull/12950
---
.vscode/tasks.json | 18 +-
CODEOWNERS | 3 +
.../accept-expected-changes-from-ci.py | 445 ++++++++++++++++++
3 files changed, 465 insertions(+), 1 deletion(-)
create mode 100755 misc/scripts/accept-expected-changes-from-ci.py
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 169b6bdd64d..68df2f6f498 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -22,6 +22,22 @@
"command": "${config:python.pythonPath}",
},
"problemMatcher": []
+ },
+ {
+ "label": "Accept .expected changes from CI",
+ "type": "process",
+ // Non-Windows OS will usually have Python 3 already installed at /usr/bin/python3.
+ "command": "python3",
+ "args": [
+ "misc/scripts/accept-expected-changes-from-ci.py"
+ ],
+ "group": "build",
+ "windows": {
+ // On Windows, use whatever Python interpreter is configured for this workspace. The default is
+ // just `python`, so if Python is already on the path, this will find it.
+ "command": "${config:python.pythonPath}",
+ },
+ "problemMatcher": []
}
]
-}
\ No newline at end of file
+}
diff --git a/CODEOWNERS b/CODEOWNERS
index 856d325b487..6e2dd9dc66b 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -40,3 +40,6 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
/.github/workflows/ruby-* @github/codeql-ruby
/.github/workflows/swift.yml @github/codeql-swift
+
+# Misc
+/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py
new file mode 100755
index 00000000000..7d85c1f7a1f
--- /dev/null
+++ b/misc/scripts/accept-expected-changes-from-ci.py
@@ -0,0 +1,445 @@
+#!/usr/bin/env python3
+"""
+This script can be used to go over `codeql test run` expected/actual log output from
+github actions, and apply patches locally to make the tests pass.
+
+It works by forming individual patches for each test-failure, and then applying them one
+by one. Since Python runs some tests twice (for both Python2 and Python3), we try to do
+some simple duplicate patch detection, to avoid failing to apply the same patch twice.
+
+Use it by checking out an up to date version of your branch, and just run the script (it
+will use `gh` cli to figure out what the PR number is). You must have the `gh` cli tool
+installed.
+
+The parsing of logs is somewhat tolerant of output being interleaved with other parallel
+execution, but it might fail in some cases ¯\_(ツ)_/¯
+
+Code written to hack things together until they work, so don't expect much :D
+"""
+
+
+import sys
+import re
+import tempfile
+from typing import List, Dict, Set, Optional, Any
+from pathlib import Path
+import subprocess
+import logging
+import json
+from dataclasses import dataclass, field
+from datetime import datetime
+import os.path
+import itertools
+
+LOGGER = logging.getLogger(Path(__file__).name)
+
+DEBUG_SAVE_PATCHES = False
+DEBUG_LOG_FILE = None
+
+
+def _get_codeql_repo_dir() -> Path:
+ return Path(__file__).parent.parent.parent
+
+
+CODEQL_REPO_DIR = _get_codeql_repo_dir()
+
+
+def _get_semmle_code_dir() -> Optional[Path]:
+ guess = CODEQL_REPO_DIR.parent
+ try:
+ out = subprocess.check_output(
+ ["git", "remote", "-v"],
+ cwd=guess,
+ ).decode("utf-8")
+ if "github/semmle-code" in out:
+ return guess
+ else:
+ return None
+ except subprocess.CalledProcessError:
+ return None
+
+
+SEMMLE_CODE_DIR = _get_semmle_code_dir()
+if SEMMLE_CODE_DIR is None:
+ LOGGER.warning("Could not find semmle-code repo, will not be able to apply patches for it")
+
+
+@dataclass(frozen=True, eq=True, order=True)
+class Patch:
+ filename: str
+ dir: Optional[str]
+ patch_first_line: str
+ patch: List[str] = field(hash=False)
+
+ def format_as_patch(self) -> str:
+ return (f"--- a/{self.filename}\n" +
+ f"+++ b/{self.filename}\n" +
+ "\n".join(self.patch) +
+ "\n"
+ )
+
+
+def parse_log_line(log_line: str) -> str:
+ if '\t' in log_line:
+ m = re.fullmatch(r"^(?:[^\t]+\t){2}\S+ ?(.*)$", log_line.strip())
+ else:
+ m = re.fullmatch(r"^(?:[^ ]+ )(.*)$", log_line.strip())
+
+ if not m:
+ return ""
+
+ return m.group(1)
+
+
+def make_patches_from_log_file(log_file_lines) -> List[Patch]:
+ # TODO: If the expected output contains `Password=123` this will be masked as `***`
+ # in the actions logs. We _could_ try to detect this and replace the line with the
+ # actual content from file (but it would require parsing the @@ lines, to understand
+ # what the old linenumber to read is)
+ patches = []
+
+ lines = iter(log_file_lines)
+
+ for raw_line in lines:
+ line = parse_log_line(raw_line)
+
+ if line == "--- expected":
+ while True:
+ next_line = parse_log_line(next(lines))
+ if next_line == "+++ actual":
+ break
+
+ lines_changed = []
+
+ while True:
+ next_line = parse_log_line(next(lines))
+ # it can be the case that
+ if next_line[0] in (" ", "-", "+", "@"):
+ lines_changed.append(next_line)
+ if "FAILED" in next_line:
+ break
+
+ # error line _should_ be next, but sometimes the output gets interleaved...
+ # so we just skip until we find the error line
+ error_line = next_line
+ while True:
+ # internal
+ filename_match = re.fullmatch(r"^##\[error\].*FAILED\(RESULT\) (.*)$", error_line)
+ if not filename_match:
+ # codeql action
+ filename_match = re.fullmatch(r"^.*FAILED\(RESULT\) (.*)$", error_line)
+ if filename_match:
+ break
+ error_line = parse_log_line(next(lines))
+
+ full_path = filename_match.group(1)
+
+ known_start_paths = {
+ # internal CI runs
+ "/home/runner/work/semmle-code/semmle-code/ql/": CODEQL_REPO_DIR,
+ "/home/runner/work/semmle-code/semmle-code/target/codeql-java-integration-tests/ql/": CODEQL_REPO_DIR,
+ "/home/runner/work/semmle-code/semmle-code/" : SEMMLE_CODE_DIR,
+ # github actions on codeql repo
+ "/home/runner/work/codeql/codeql/": CODEQL_REPO_DIR,
+ "/Users/runner/work/codeql/codeql/" : CODEQL_REPO_DIR, # MacOS
+ }
+ for known_start_path, dir in known_start_paths.items():
+ if full_path.startswith(known_start_path):
+ filename = Path(full_path[len(known_start_path):])
+ break
+ else:
+ raise Exception(f"Unknown path {full_path}, skipping")
+
+ expected_filename = filename.with_suffix(".expected")
+
+ # if the .expected file used to be empty, `codeql test run` outputs a diff
+ # that uses `@@ -1,1 ` but git wants it to be `@@ -0,0 ` (and not include
+ # the removal of the empty line)
+ if lines_changed[0].startswith("@@ -1,1 ") and lines_changed[1] == "-":
+ lines_changed[0] = lines_changed[0].replace("@@ -1,1 ", "@@ -0,0 ")
+ del lines_changed[1]
+
+ patch = Patch(
+ filename=expected_filename,
+ dir=dir,
+ patch_first_line=lines_changed[0],
+ patch=lines_changed,
+ )
+ patches.append(patch)
+
+ return patches
+
+def make_github_api_list_request(path: str) -> Any:
+ """Handles the way paginate currently works, which is to return multiple lists of
+ results, instead of merging them :(
+ """
+
+ s = subprocess.check_output(
+ ["gh", "api", "--paginate", path],
+ ).decode("utf-8")
+
+ try:
+ return json.loads(s)
+ except json.JSONDecodeError:
+ assert "][" in s
+ parts = s.split("][")
+ parts[0] = parts[0] + "]"
+ parts[-1] = "[" + parts[-1]
+ for i in range(1, len(parts) - 1):
+ parts[i] = "[" + parts[i] + "]"
+ return itertools.chain(*[json.loads(x) for x in parts])
+
+
+@dataclass
+class GithubStatus():
+ state: str
+ context: str
+ target_url: str
+ created_at: datetime
+ nwo: str
+ job_id: int = None
+
+
+def get_log_content(status: GithubStatus) -> str:
+ LOGGER.debug(f"'{status.context}': Getting logs")
+ if status.job_id:
+ content = subprocess.check_output(
+ ["gh", "api", f"/repos/{status.nwo}/actions/jobs/{status.job_id}/logs"],
+ ).decode("utf-8")
+ else:
+ m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", status.target_url)
+ nwo = m.group(1)
+ run_id = m.group(2)
+ content = subprocess.check_output(
+ ["gh", "run", "view", "--repo", nwo, run_id, "--log-failed"],
+ ).decode("utf-8")
+
+ if DEBUG_SAVE_PATCHES:
+ tmp = tempfile.NamedTemporaryFile(delete=False)
+ tmp.write(content.encode(encoding="utf-8"))
+ print(tmp.name)
+ return content
+
+
+def main(pr_number: int):
+ LOGGER.info(f"Getting status URL for codeql PR #{pr_number}")
+ github_sha = subprocess.check_output(
+ ["gh", "api", f"repos/github/codeql/pulls/{pr_number}", "--jq", ".head.sha"]
+ ).decode("utf-8").strip()
+ local_sha = subprocess.check_output(
+ ["git", "rev-parse", "HEAD"]
+ ).decode("utf-8").strip()
+
+ if local_sha != github_sha:
+ LOGGER.error(f"GitHub SHA ({github_sha}) different from your local SHA ({local_sha}), sync your changes first!")
+ sys.exit(1)
+ sha = github_sha
+
+ status_url = f"https://api.github.com/repos/github/codeql/commits/{sha}/statuses"
+ LOGGER.info(f"Getting status details ({status_url})")
+ statuses = make_github_api_list_request(status_url)
+ newest_status: Dict[str, GithubStatus] = dict()
+
+ for status in statuses:
+ created_at = datetime.fromisoformat(status["created_at"][:-1])
+ key = status["context"]
+ if key not in newest_status or created_at > newest_status[key].created_at:
+ m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", status["target_url"])
+
+ newest_status[key] = GithubStatus(
+ state=status["state"],
+ context=status["context"],
+ target_url=status["target_url"],
+ created_at=created_at,
+ nwo=m.group(1),
+ )
+
+ supported_internal_status_language_test_names = [
+ "Java Integration Tests Linux",
+ # "codeql-coding-standards Unit Tests Linux",
+ # TODO: Currently disabled, would just require support for figuring out where
+ # https://github.com/github/codeql-coding-standards/ is checked out locally
+ ]
+
+ lang_test_failures: List[GithubStatus] = list()
+ for status in newest_status.values():
+ if " Language Tests" in status.context or status.context in supported_internal_status_language_test_names:
+ if status.state == "failure":
+ lang_test_failures.append(status)
+ elif status.state == "pending":
+ LOGGER.error(f"Language tests ({status.context}) are still running, please wait for them to finish before running this script again")
+ sys.exit(1)
+
+ job_failure_urls = set()
+ for lang_test_failure in lang_test_failures:
+ job_failure_urls.add(lang_test_failure.target_url)
+
+ assert len(job_failure_urls) == 1, f"Multiple job failure URLs: {job_failure_urls}"
+ job_failure_url = job_failure_urls.pop()
+
+ # fixup URL. On the status, the target URL is the run, and it's really hard to
+ # change this to link to the full `/runs//jobs/` URL, since
+ # the `` is not available in a context: https://github.com/community/community/discussions/40291
+ m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)$", job_failure_url)
+ nwo = m.group(1)
+ run_id = m.group(2)
+ jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs"
+ LOGGER.info(f"Fixing up target url from looking at {jobs_url}")
+ jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8"))
+ for lang_test_failure in lang_test_failures:
+ workflow_translation = {
+ "codeql-coding-standards Unit Tests Linux": "Start codeql-coding-standards"
+ }
+ expected_workflow_name = workflow_translation.get(lang_test_failure.context, lang_test_failure.context)
+
+ for job in jobs["jobs"]:
+ api_name: str = job["name"]
+ if " / " not in api_name:
+ continue
+
+ workflow_name, job_name = api_name.split(" / ")
+ # The job names we're looking for looks like "Python2 Language Tests / Python2 Language Tests" or "Java Language Tests / Java Language Tests Linux"
+ # for "Java Integration Tests Linux / Java Integration tests Linux" we need to ignore case :|
+ if workflow_name == expected_workflow_name and job_name.lower().startswith(lang_test_failure.context.lower()):
+ lang_test_failure.job_id = job["id"]
+ break
+ else:
+ LOGGER.error(f"Could not find job for {lang_test_failure.context!r}")
+ sys.exit(1)
+
+ # Ruby/Swift/C#/Go use github actions, and not internal CI. These are not reported
+ # from the /statuses API, but from the /check-suites API
+ check_suites_url = f"https://api.github.com/repos/github/codeql/commits/{sha}/check-suites"
+ LOGGER.info(f"Getting check suites ({check_suites_url})")
+ check_suites = json.loads(subprocess.check_output(["gh", "api", "--paginate", check_suites_url]).decode("utf-8"))
+
+ check_failure_urls = []
+ for check in check_suites["check_suites"]:
+ if check["status"] != "completed":
+ print(check)
+ LOGGER.error("At least one check not completed yet!")
+ sys.exit(1)
+
+ if check["conclusion"] == "failure":
+ check_failure_urls.append(check["check_runs_url"])
+
+ for check_failure_url in check_failure_urls:
+ # run information: https://docs.github.com/en/rest/actions/workflow-jobs?apiVersion=2022-11-28#get-a-job-for-a-workflow-run
+ check_runs = json.loads(subprocess.check_output(["gh", "api", "--paginate", check_failure_url]).decode("utf-8"))
+ for check_run in check_runs["check_runs"]:
+ if check_run["conclusion"] == "failure":
+ m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)(?:/jobs/(\d+))?$", check_run["details_url"])
+ nwo = m.group(1)
+ run_id = m.group(2)
+ jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs"
+ LOGGER.debug(f"Looking into failure at {jobs_url}")
+ jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8"))
+
+ for job in jobs["jobs"]:
+ OK_WORKFLOW_NAMES = ["C#: Run QL Tests", "Go: Run Tests", "Ruby: Run QL Tests", "Swift"]
+ def ok_job_name(job_name: str) -> bool:
+ if job_name.startswith("qltest"):
+ return True
+ if job_name.startswith("Test Linux"):
+ return True
+ return False
+
+ if job["name"] == check_run['name'] and job["workflow_name"] in OK_WORKFLOW_NAMES and ok_job_name(job["name"]):
+ # print(check_run['name'], 'matched to', f"{job['workflow_name']} / {job['name']}")
+ lang_test_failures.append(GithubStatus(
+ state="failure",
+ context=f"{job['workflow_name']} / {job['name']}",
+ target_url=job["html_url"],
+ created_at=check_run["completed_at"],
+ nwo=nwo,
+ job_id=job["id"],
+ ))
+ break
+ else:
+ LOGGER.debug(f"Ignoring actions failure for '{check_run['name']}' ({check_run['details_url']})")
+
+ if not lang_test_failures:
+ LOGGER.info("No language test failures found")
+ return
+
+ patches_to_apply: Set[Patch] = set()
+
+ for failure in lang_test_failures:
+ log_content = get_log_content(failure)
+ LOGGER.info(f"'{failure.context}': Making patches")
+ patches = make_patches_from_log_file(log_content.splitlines())
+
+ if not patches:
+ LOGGER.warning(f"No patches generated for job {failure}")
+ continue
+
+ for patch in patches:
+ if patch in patches_to_apply:
+ LOGGER.debug(f"Skipping duplicate patch for {patch.filename}")
+ continue
+ patches_to_apply.add(patch)
+
+ if DEBUG_SAVE_PATCHES:
+ sys.exit("debug save patches")
+
+ if not patches_to_apply:
+ print("No patches to apply")
+ return
+
+ semmle_code_changed = False
+
+ for patch in patches_to_apply:
+ with tempfile.NamedTemporaryFile(prefix=f"patches-", suffix=".patch") as temp:
+ temp.write(patch.format_as_patch().encode(encoding="utf-8"))
+ temp.flush()
+ LOGGER.info(f"Applying patch for '{patch.filename}'")
+ try:
+ if patch.dir is None:
+ LOGGER.warning(f"Did not find local semmle-code directory, so skipping patch for '{patch.filename}'")
+ continue
+
+ subprocess.check_call(["git", "apply", temp.name], cwd=patch.dir)
+ if patch.dir == SEMMLE_CODE_DIR:
+ semmle_code_changed = True
+ except subprocess.CalledProcessError:
+ LOGGER.error(f"Could not apply patches for '{patch.filename}' '{patch.patch[0]}', skipping")
+ tmp_keep = tempfile.NamedTemporaryFile(delete=False)
+ tmp_keep.write(patch.format_as_patch().encode(encoding="utf-8"))
+ LOGGER.error(f"Patch saved to {tmp_keep.name}")
+
+ if semmle_code_changed:
+ print("Expected output in semmle-code changed!")
+
+def get_pr_number() -> int:
+ if len(sys.argv) < 2:
+ pr_number_response = subprocess.check_output([
+ "gh", "pr", "view", "--json", "number"
+ ]).decode("utf-8")
+
+ return json.loads(pr_number_response)["number"]
+ else:
+ return int(sys.argv[1])
+
+
+if __name__ == "__main__":
+
+ level = logging.INFO
+
+ try:
+ import coloredlogs
+ coloredlogs.install(level, fmt="%(levelname)s: %(message)s")
+ except ImportError:
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
+
+
+ if DEBUG_LOG_FILE:
+ patches = make_patches_from_log_file(open(DEBUG_LOG_FILE, "r").readlines())
+ for patch in patches:
+ if True:
+ tmp_keep = tempfile.NamedTemporaryFile(delete=False)
+ tmp_keep.write(patch.format_as_patch().encode(encoding="utf-8"))
+ LOGGER.info(f"Patch for {patch.filename} saved to {tmp_keep.name}")
+ sys.exit(1)
+
+ os.chdir(CODEQL_REPO_DIR)
+ main(get_pr_number())
From e3fc6d67cc49ee182023e01b5d1c79f88a7f14d7 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 3 May 2023 17:31:52 +0200
Subject: [PATCH 02/67] Misc: Allow no internal CI
---
.../accept-expected-changes-from-ci.py | 59 ++++++++++---------
1 file changed, 30 insertions(+), 29 deletions(-)
diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py
index 7d85c1f7a1f..3ce35d5ef56 100755
--- a/misc/scripts/accept-expected-changes-from-ci.py
+++ b/misc/scripts/accept-expected-changes-from-ci.py
@@ -274,38 +274,39 @@ def main(pr_number: int):
for lang_test_failure in lang_test_failures:
job_failure_urls.add(lang_test_failure.target_url)
- assert len(job_failure_urls) == 1, f"Multiple job failure URLs: {job_failure_urls}"
- job_failure_url = job_failure_urls.pop()
+ if job_failure_urls:
+ assert len(job_failure_urls) == 1, f"Multiple job failure URLs: {job_failure_urls}"
+ job_failure_url = job_failure_urls.pop()
- # fixup URL. On the status, the target URL is the run, and it's really hard to
- # change this to link to the full `/runs//jobs/` URL, since
- # the `` is not available in a context: https://github.com/community/community/discussions/40291
- m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)$", job_failure_url)
- nwo = m.group(1)
- run_id = m.group(2)
- jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs"
- LOGGER.info(f"Fixing up target url from looking at {jobs_url}")
- jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8"))
- for lang_test_failure in lang_test_failures:
- workflow_translation = {
- "codeql-coding-standards Unit Tests Linux": "Start codeql-coding-standards"
- }
- expected_workflow_name = workflow_translation.get(lang_test_failure.context, lang_test_failure.context)
+ # fixup URL. On the status, the target URL is the run, and it's really hard to
+ # change this to link to the full `/runs//jobs/` URL, since
+ # the `` is not available in a context: https://github.com/community/community/discussions/40291
+ m = re.fullmatch(r"^https://github\.com/([^/]+/[^/]+)/actions/runs/(\d+)$", job_failure_url)
+ nwo = m.group(1)
+ run_id = m.group(2)
+ jobs_url = f"https://api.github.com/repos/{nwo}/actions/runs/{run_id}/jobs"
+ LOGGER.info(f"Fixing up target url from looking at {jobs_url}")
+ jobs = json.loads(subprocess.check_output(["gh", "api", "--paginate", jobs_url]).decode("utf-8"))
+ for lang_test_failure in lang_test_failures:
+ workflow_translation = {
+ "codeql-coding-standards Unit Tests Linux": "Start codeql-coding-standards"
+ }
+ expected_workflow_name = workflow_translation.get(lang_test_failure.context, lang_test_failure.context)
- for job in jobs["jobs"]:
- api_name: str = job["name"]
- if " / " not in api_name:
- continue
+ for job in jobs["jobs"]:
+ api_name: str = job["name"]
+ if " / " not in api_name:
+ continue
- workflow_name, job_name = api_name.split(" / ")
- # The job names we're looking for looks like "Python2 Language Tests / Python2 Language Tests" or "Java Language Tests / Java Language Tests Linux"
- # for "Java Integration Tests Linux / Java Integration tests Linux" we need to ignore case :|
- if workflow_name == expected_workflow_name and job_name.lower().startswith(lang_test_failure.context.lower()):
- lang_test_failure.job_id = job["id"]
- break
- else:
- LOGGER.error(f"Could not find job for {lang_test_failure.context!r}")
- sys.exit(1)
+ workflow_name, job_name = api_name.split(" / ")
+ # The job names we're looking for looks like "Python2 Language Tests / Python2 Language Tests" or "Java Language Tests / Java Language Tests Linux"
+ # for "Java Integration Tests Linux / Java Integration tests Linux" we need to ignore case :|
+ if workflow_name == expected_workflow_name and job_name.lower().startswith(lang_test_failure.context.lower()):
+ lang_test_failure.job_id = job["id"]
+ break
+ else:
+ LOGGER.error(f"Could not find job for {lang_test_failure.context!r}")
+ sys.exit(1)
# Ruby/Swift/C#/Go use github actions, and not internal CI. These are not reported
# from the /statuses API, but from the /check-suites API
From b048f9d8c49f5883b00c3ebbb0001d78f7308c6d Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 3 May 2023 17:37:39 +0200
Subject: [PATCH 03/67] Misc: Allow specifying SHA directly to script
---
.../accept-expected-changes-from-ci.py | 32 +++++++++++++------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py
index 3ce35d5ef56..2441f8279d2 100755
--- a/misc/scripts/accept-expected-changes-from-ci.py
+++ b/misc/scripts/accept-expected-changes-from-ci.py
@@ -221,11 +221,18 @@ def get_log_content(status: GithubStatus) -> str:
return content
-def main(pr_number: int):
- LOGGER.info(f"Getting status URL for codeql PR #{pr_number}")
- github_sha = subprocess.check_output(
- ["gh", "api", f"repos/github/codeql/pulls/{pr_number}", "--jq", ".head.sha"]
- ).decode("utf-8").strip()
+def main(pr_number: Optional[int], sha_override: Optional[str] = None):
+ if not pr_number and not sha_override:
+ raise Exception("Must specify either a PR number or a SHA")
+
+ if sha_override:
+ github_sha = sha_override
+ else:
+ LOGGER.info(f"Getting status URL for codeql PR #{pr_number}")
+ github_sha = subprocess.check_output(
+ ["gh", "api", f"repos/github/codeql/pulls/{pr_number}", "--jq", ".head.sha"]
+ ).decode("utf-8").strip()
+
local_sha = subprocess.check_output(
["git", "rev-parse", "HEAD"]
).decode("utf-8").strip()
@@ -411,15 +418,22 @@ def main(pr_number: int):
if semmle_code_changed:
print("Expected output in semmle-code changed!")
-def get_pr_number() -> int:
+
+def call_main():
+ pr_number = None
+ override_sha = None
if len(sys.argv) < 2:
pr_number_response = subprocess.check_output([
"gh", "pr", "view", "--json", "number"
]).decode("utf-8")
- return json.loads(pr_number_response)["number"]
+ pr_number = json.loads(pr_number_response)["number"]
else:
- return int(sys.argv[1])
+ if len(sys.argv[1]) > 10:
+ override_sha = sys.argv[1]
+ else:
+ pr_number = int(sys.argv[1])
+ main(pr_number, override_sha)
if __name__ == "__main__":
@@ -443,4 +457,4 @@ if __name__ == "__main__":
sys.exit(1)
os.chdir(CODEQL_REPO_DIR)
- main(get_pr_number())
+ call_main()
From c9680b92022ebadd35317b90145608d31a9a0440 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 3 May 2023 17:40:21 +0200
Subject: [PATCH 04/67] Misc: Look for .expected changes from
`integration-tests...`
---
misc/scripts/accept-expected-changes-from-ci.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py
index 2441f8279d2..d4d57f26726 100755
--- a/misc/scripts/accept-expected-changes-from-ci.py
+++ b/misc/scripts/accept-expected-changes-from-ci.py
@@ -350,6 +350,8 @@ def main(pr_number: Optional[int], sha_override: Optional[str] = None):
return True
if job_name.startswith("Test Linux"):
return True
+ if job_name.startswith("integration-tests"):
+ return True
return False
if job["name"] == check_run['name'] and job["workflow_name"] in OK_WORKFLOW_NAMES and ok_job_name(job["name"]):
From 60b0f25a9a145556a896cc07c82926d18e787177 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 9 May 2023 11:03:52 +0200
Subject: [PATCH 05/67] Ruby: Improvements to `RegExpTracking`
---
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 6 +-
.../internal/TaintTrackingPrivate.qll | 9 +-
.../ruby/regexp/internal/RegExpTracking.qll | 221 ++++++++++++------
.../codeql/ruby/typetracking/TypeTracker.qll | 13 +-
4 files changed, 166 insertions(+), 83 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 6a5bc217303..96c015a6a4a 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -936,10 +936,10 @@ module ExprNodes {
}
/** A control-flow node that wraps a `StringLiteral` AST expression. */
- class StringLiteralCfgNode extends ExprCfgNode {
- override string getAPrimaryQlClass() { result = "StringLiteralCfgNode" }
+ class StringLiteralCfgNode extends StringlikeLiteralCfgNode {
+ StringLiteralCfgNode() { e instanceof StringLiteral }
- override StringLiteral e;
+ override string getAPrimaryQlClass() { result = "StringLiteralCfgNode" }
final override StringLiteral getExpr() { result = super.getExpr() }
}
diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll
index c89a629e198..3381187985a 100644
--- a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll
+++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll
@@ -112,6 +112,13 @@ private module Cached {
)
}
+ cached
+ predicate summaryThroughStepTaint(
+ DataFlow::Node arg, DataFlow::Node out, FlowSummaryImpl::Public::SummarizedCallable sc
+ ) {
+ FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(arg, out, sc)
+ }
+
/**
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
@@ -122,7 +129,7 @@ private module Cached {
defaultAdditionalTaintStep(nodeFrom, nodeTo) or
// Simple flow through library code is included in the exposed local
// step relation, even though flow is technically inter-procedural
- FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _)
+ summaryThroughStepTaint(nodeFrom, nodeTo, _)
}
}
diff --git a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
index e787ae358e1..648bc533046 100644
--- a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
+++ b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
@@ -21,6 +21,7 @@ private import codeql.ruby.typetracking.TypeTracker
private import codeql.ruby.ApiGraphs
private import codeql.ruby.Concepts
private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate
+private import codeql.ruby.dataflow.internal.TaintTrackingPrivate as TaintTrackingPrivate
private import codeql.ruby.TaintTracking
private import codeql.ruby.frameworks.core.String
@@ -37,43 +38,6 @@ DataFlow::LocalSourceNode strStart() {
/** Gets a dataflow node for a regular expression literal. */
DataFlow::LocalSourceNode regStart() { result.asExpr().getExpr() instanceof Ast::RegExpLiteral }
-/**
- * Holds if the analysis should track flow from `nodeFrom` to `nodeTo` on top of the ordinary type-tracking steps.
- * `nodeFrom` and `nodeTo` has type `fromType` and `toType` respectively.
- * The types are either "string" or "regexp".
- */
-predicate step(
- DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo, string fromType, string toType
-) {
- fromType = toType and
- fromType = "string" and
- (
- // include taint flow through `String` summaries
- TaintTracking::localTaintStep(nodeFrom, nodeTo) and
- nodeFrom.(DataFlowPrivate::SummaryNode).getSummarizedCallable() instanceof
- String::SummarizedCallable
- or
- // string concatenations, and
- exists(CfgNodes::ExprNodes::OperationCfgNode op |
- op = nodeTo.asExpr() and
- op.getAnOperand() = nodeFrom.asExpr() and
- op.getExpr().(Ast::BinaryOperation).getOperator() = "+"
- )
- or
- // string interpolations
- nodeFrom.asExpr() =
- nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent()
- )
- or
- fromType = "string" and
- toType = "reg" and
- exists(DataFlow::CallNode call |
- call = API::getTopLevelMember("Regexp").getAMethodCall(["compile", "new"]) and
- nodeFrom = call.getArgument(0) and
- nodeTo = call
- )
-}
-
/** Gets a node where string values that flow to the node are interpreted as regular expressions. */
DataFlow::Node stringSink() {
result instanceof RE::RegExpInterpretation::Range and
@@ -91,69 +55,172 @@ DataFlow::Node stringSink() {
/** Gets a node where regular expressions that flow to the node are used. */
DataFlow::Node regSink() { result = any(RegexExecution exec).getRegex() }
-/** Gets a node that is reachable by type-tracking from any string or regular expression. */
-DataFlow::LocalSourceNode forward(TypeTracker t) {
- t.start() and
- result = [strStart(), regStart()]
- or
- exists(TypeTracker t2 | result = forward(t2).track(t2, t))
- or
- exists(TypeTracker t2 | t2 = t.continue() | step(forward(t2).getALocalUse(), result, _, _))
+private signature module ReachInputSig {
+ DataFlow::LocalSourceNode start(TypeTracker t);
+
+ DataFlow::Node end();
+
+ predicate additionalStep(DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo);
}
-/**
- * Gets a node that is backwards reachable from any regular expression use,
- * where that use is reachable by type-tracking from any string or regular expression.
- */
-DataFlow::LocalSourceNode backwards(TypeBackTracker t) {
- t.start() and
- result.flowsTo([stringSink(), regSink()]) and
- result = forward(TypeTracker::end())
- or
- exists(TypeBackTracker t2 | result = backwards(t2).backtrack(t2, t))
- or
- exists(TypeBackTracker t2 | t2 = t.continue() | step(result.getALocalUse(), backwards(t2), _, _))
+private module Reach {
+ /** Gets a node that is forwards reachable by type-tracking. */
+ pragma[nomagic]
+ private DataFlow::LocalSourceNode forward(TypeTracker t) {
+ result = Input::start(t)
+ or
+ exists(TypeTracker t2 | result = forward(t2).track(t2, t))
+ or
+ exists(TypeTracker t2 | t2 = t.continue() | Input::additionalStep(forward(t2), result))
+ }
+
+ bindingset[result, tbt]
+ pragma[inline_late]
+ pragma[noopt]
+ private DataFlow::LocalSourceNode forwardLateInline(TypeBackTracker tbt) {
+ exists(TypeTracker tt |
+ result = forward(tt) and
+ tt = tbt.getACompatibleTypeTracker()
+ )
+ }
+
+ /** Gets a node that is backwards reachable by type-tracking. */
+ pragma[nomagic]
+ private DataFlow::LocalSourceNode backwards(TypeBackTracker t) {
+ result = forwardLateInline(t) and
+ (
+ t.start() and
+ result.flowsTo(Input::end())
+ or
+ exists(TypeBackTracker t2 | result = backwards(t2).backtrack(t2, t))
+ or
+ exists(TypeBackTracker t2 | t2 = t.continue() | Input::additionalStep(result, backwards(t2)))
+ )
+ }
+
+ bindingset[result, tt]
+ pragma[inline_late]
+ pragma[noopt]
+ private DataFlow::LocalSourceNode backwardsInlineLate(TypeTracker tt) {
+ exists(TypeBackTracker tbt |
+ result = backwards(tbt) and
+ tt = tbt.getACompatibleTypeTracker()
+ )
+ }
+
+ pragma[nomagic]
+ predicate reached(DataFlow::LocalSourceNode n, TypeTracker t) {
+ n = forward(t) and
+ n = backwardsInlineLate(t)
+ }
+
+ pragma[nomagic]
+ TypeTracker stepReached(
+ TypeTracker t, DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo
+ ) {
+ exists(StepSummary summary |
+ StepSummary::step(nodeFrom, nodeTo, summary) and
+ reached(nodeFrom, t) and
+ reached(nodeTo, result) and
+ result = t.append(summary)
+ )
+ or
+ Input::additionalStep(nodeFrom, nodeTo) and
+ reached(nodeFrom, pragma[only_bind_into](t)) and
+ reached(nodeTo, pragma[only_bind_into](t)) and
+ result = t.continue()
+ }
}
+pragma[nomagic]
+private predicate regFromString(DataFlow::LocalSourceNode n, DataFlow::CallNode call) {
+ exists(DataFlow::Node mid |
+ n.flowsTo(mid) and
+ call = API::getTopLevelMember("Regexp").getAMethodCall(["compile", "new"]) and
+ mid = call.getArgument(0)
+ )
+}
+
+private module StringReachInput implements ReachInputSig {
+ DataFlow::LocalSourceNode start(TypeTracker t) { result = strStart() and t.start() }
+
+ DataFlow::Node end() {
+ result = stringSink() or
+ regFromString(result, _)
+ }
+
+ predicate additionalStep(DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo) {
+ exists(DataFlow::Node mid | nodeFrom.flowsTo(mid) |
+ // include taint flow through `String` summaries
+ TaintTrackingPrivate::summaryThroughStepTaint(mid, nodeTo, any(String::SummarizedCallable c))
+ or
+ // string concatenations, and
+ exists(CfgNodes::ExprNodes::OperationCfgNode op |
+ op = nodeTo.asExpr() and
+ op.getAnOperand() = mid.asExpr() and
+ op.getExpr().(Ast::BinaryOperation).getOperator() = "+"
+ )
+ or
+ // string interpolations
+ mid.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent()
+ )
+ }
+}
+
+private module StringReach = Reach;
+
/**
* Gets a node that has been tracked from the string constant `start` to some node.
* This is used to figure out where `start` is evaluated as a regular expression against an input string,
* or where `start` is compiled into a regular expression.
*/
private DataFlow::LocalSourceNode trackStrings(DataFlow::Node start, TypeTracker t) {
- result = backwards(_) and
- (
- t.start() and
- start = result and
- result = strStart()
- or
- exists(TypeTracker t2 | result = trackStrings(start, t2).track(t2, t))
- or
- // an additional step from string to string
- exists(TypeTracker t2 | t2 = t.continue() |
- step(trackStrings(start, t2).getALocalUse(), result, "string", "string")
- )
- )
+ t.start() and
+ start = result and
+ result = strStart() and
+ StringReach::reached(result, t)
+ or
+ exists(TypeTracker t2 | t = StringReach::stepReached(t2, trackStrings(start, t2), result))
}
+pragma[nomagic]
+private predicate regFromStringStart(DataFlow::Node start, TypeTracker t, DataFlow::CallNode nodeTo) {
+ regFromString(trackStrings(start, t), nodeTo) and
+ exists(t.continue())
+}
+
+private module RegReachInput implements ReachInputSig {
+ DataFlow::LocalSourceNode start(TypeTracker t) {
+ result = regStart() and
+ t.start()
+ or
+ regFromStringStart(_, t, result)
+ }
+
+ DataFlow::Node end() { result = regSink() }
+
+ predicate additionalStep(DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo) {
+ none()
+ }
+}
+
+private module RegReach = Reach;
+
/**
* Gets a node that has been tracked from the regular expression `start` to some node.
* This is used to figure out where `start` is executed against an input string.
*/
private DataFlow::LocalSourceNode trackRegs(DataFlow::Node start, TypeTracker t) {
- result = backwards(_) and
+ RegReach::reached(result, t) and
(
t.start() and
start = result and
result = regStart()
or
- exists(TypeTracker t2 | result = trackRegs(start, t2).track(t2, t))
- or
- // an additional step where a string is converted to a regular expression
- exists(TypeTracker t2 | t2 = t.continue() |
- step(trackStrings(start, t2).getALocalUse(), result, "string", "reg")
- )
+ regFromStringStart(start, t, result)
)
+ or
+ exists(TypeTracker t2 | t = RegReach::stepReached(t2, trackRegs(start, t2), result))
}
/** Gets a node that references a regular expression. */
diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll
index 52807799c2c..d4d9e1f31f5 100644
--- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll
+++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll
@@ -613,8 +613,17 @@ class TypeBackTracker extends TTypeBackTracker {
* also flow to `sink`.
*/
TypeTracker getACompatibleTypeTracker() {
- exists(boolean hasCall | result = MkTypeTracker(hasCall, content) |
- hasCall = false or this.hasReturn() = false
+ exists(boolean hasCall, OptionalTypeTrackerContent c |
+ result = MkTypeTracker(hasCall, c) and
+ (
+ compatibleContents(c, content)
+ or
+ content = noContent() and c = content
+ )
+ |
+ hasCall = false
+ or
+ this.hasReturn() = false
)
}
}
From 211a1e188cb15b0d009879fced378afe8fb73791 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 9 May 2023 15:15:53 +0200
Subject: [PATCH 06/67] Sync files
---
.../python/dataflow/new/internal/TypeTracker.qll | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll
index 52807799c2c..d4d9e1f31f5 100644
--- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll
+++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll
@@ -613,8 +613,17 @@ class TypeBackTracker extends TTypeBackTracker {
* also flow to `sink`.
*/
TypeTracker getACompatibleTypeTracker() {
- exists(boolean hasCall | result = MkTypeTracker(hasCall, content) |
- hasCall = false or this.hasReturn() = false
+ exists(boolean hasCall, OptionalTypeTrackerContent c |
+ result = MkTypeTracker(hasCall, c) and
+ (
+ compatibleContents(c, content)
+ or
+ content = noContent() and c = content
+ )
+ |
+ hasCall = false
+ or
+ this.hasReturn() = false
)
}
}
From 51087d090b493810e2b634f201237c0cd412c661 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 10 May 2023 09:42:41 +0200
Subject: [PATCH 07/67] Address review comments
---
.../codeql/ruby/regexp/internal/RegExpTracking.qll | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
index 648bc533046..9df923e2d86 100644
--- a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
+++ b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
@@ -108,6 +108,7 @@ private module Reach {
)
}
+ /** Holds if `n` is forwards and backwards reachable with type tracker `t`. */
pragma[nomagic]
predicate reached(DataFlow::LocalSourceNode n, TypeTracker t) {
n = forward(t) and
@@ -132,10 +133,11 @@ private module Reach {
}
}
+/** Holds if `inputStr` is compiled to a regular expression that is returned at `call`. */
pragma[nomagic]
-private predicate regFromString(DataFlow::LocalSourceNode n, DataFlow::CallNode call) {
+private predicate regFromString(DataFlow::LocalSourceNode inputStr, DataFlow::CallNode call) {
exists(DataFlow::Node mid |
- n.flowsTo(mid) and
+ inputStr.flowsTo(mid) and
call = API::getTopLevelMember("Regexp").getAMethodCall(["compile", "new"]) and
mid = call.getArgument(0)
)
@@ -183,9 +185,10 @@ private DataFlow::LocalSourceNode trackStrings(DataFlow::Node start, TypeTracker
exists(TypeTracker t2 | t = StringReach::stepReached(t2, trackStrings(start, t2), result))
}
+/** Holds if `strConst` flows to a regex compilation (tracked by `t`), where the resulting regular expression is stored in `reg`. */
pragma[nomagic]
-private predicate regFromStringStart(DataFlow::Node start, TypeTracker t, DataFlow::CallNode nodeTo) {
- regFromString(trackStrings(start, t), nodeTo) and
+private predicate regFromStringStart(DataFlow::Node strConst, TypeTracker t, DataFlow::CallNode reg) {
+ regFromString(trackStrings(strConst, t), reg) and
exists(t.continue())
}
From 425ebba2783a80ec57f6a13da5517e4161406807 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 10 May 2023 14:04:41 +0200
Subject: [PATCH 08/67] Address review comments
---
.../ruby/regexp/internal/RegExpTracking.qll | 128 +++++++++---------
1 file changed, 63 insertions(+), 65 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
index 9df923e2d86..d4f8f17db34 100644
--- a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
+++ b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpTracking.qll
@@ -55,23 +55,33 @@ DataFlow::Node stringSink() {
/** Gets a node where regular expressions that flow to the node are used. */
DataFlow::Node regSink() { result = any(RegexExecution exec).getRegex() }
-private signature module ReachInputSig {
- DataFlow::LocalSourceNode start(TypeTracker t);
+private signature module TypeTrackInputSig {
+ DataFlow::LocalSourceNode start(TypeTracker t, DataFlow::Node start);
- DataFlow::Node end();
+ predicate end(DataFlow::Node n);
- predicate additionalStep(DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo);
+ predicate additionalStep(DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo);
}
-private module Reach {
+/**
+ * Provides a version of type tracking where we first prune for reachable nodes,
+ * before doing the type tracking computation.
+ */
+private module TypeTrack {
+ private predicate additionalStep(
+ DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo
+ ) {
+ Input::additionalStep(nodeFrom.getALocalUse(), nodeTo)
+ }
+
/** Gets a node that is forwards reachable by type-tracking. */
pragma[nomagic]
private DataFlow::LocalSourceNode forward(TypeTracker t) {
- result = Input::start(t)
+ result = Input::start(t, _)
or
exists(TypeTracker t2 | result = forward(t2).track(t2, t))
or
- exists(TypeTracker t2 | t2 = t.continue() | Input::additionalStep(forward(t2), result))
+ exists(TypeTracker t2 | t2 = t.continue() | additionalStep(forward(t2), result))
}
bindingset[result, tbt]
@@ -90,11 +100,11 @@ private module Reach {
result = forwardLateInline(t) and
(
t.start() and
- result.flowsTo(Input::end())
+ Input::end(result.getALocalUse())
or
exists(TypeBackTracker t2 | result = backwards(t2).backtrack(t2, t))
or
- exists(TypeBackTracker t2 | t2 = t.continue() | Input::additionalStep(result, backwards(t2)))
+ exists(TypeBackTracker t2 | t2 = t.continue() | additionalStep(result, backwards(t2)))
)
}
@@ -110,13 +120,13 @@ private module Reach {
/** Holds if `n` is forwards and backwards reachable with type tracker `t`. */
pragma[nomagic]
- predicate reached(DataFlow::LocalSourceNode n, TypeTracker t) {
+ private predicate reached(DataFlow::LocalSourceNode n, TypeTracker t) {
n = forward(t) and
n = backwardsInlineLate(t)
}
pragma[nomagic]
- TypeTracker stepReached(
+ private TypeTracker stepReached(
TypeTracker t, DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo
) {
exists(StepSummary summary |
@@ -126,11 +136,20 @@ private module Reach {
result = t.append(summary)
)
or
- Input::additionalStep(nodeFrom, nodeTo) and
+ additionalStep(nodeFrom, nodeTo) and
reached(nodeFrom, pragma[only_bind_into](t)) and
reached(nodeTo, pragma[only_bind_into](t)) and
result = t.continue()
}
+
+ /** Gets a node that has been tracked from the start node `start`. */
+ DataFlow::LocalSourceNode track(DataFlow::Node start, TypeTracker t) {
+ t.start() and
+ result = Input::start(t, start) and
+ reached(result, t)
+ or
+ exists(TypeTracker t2 | t = stepReached(t2, track(start, t2), result))
+ }
}
/** Holds if `inputStr` is compiled to a regular expression that is returned at `call`. */
@@ -143,47 +162,40 @@ private predicate regFromString(DataFlow::LocalSourceNode inputStr, DataFlow::Ca
)
}
-private module StringReachInput implements ReachInputSig {
- DataFlow::LocalSourceNode start(TypeTracker t) { result = strStart() and t.start() }
-
- DataFlow::Node end() {
- result = stringSink() or
- regFromString(result, _)
+private module StringTypeTrackInput implements TypeTrackInputSig {
+ DataFlow::LocalSourceNode start(TypeTracker t, DataFlow::Node start) {
+ start = strStart() and t.start() and result = start
}
- predicate additionalStep(DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo) {
- exists(DataFlow::Node mid | nodeFrom.flowsTo(mid) |
- // include taint flow through `String` summaries
- TaintTrackingPrivate::summaryThroughStepTaint(mid, nodeTo, any(String::SummarizedCallable c))
- or
- // string concatenations, and
- exists(CfgNodes::ExprNodes::OperationCfgNode op |
- op = nodeTo.asExpr() and
- op.getAnOperand() = mid.asExpr() and
- op.getExpr().(Ast::BinaryOperation).getOperator() = "+"
- )
- or
- // string interpolations
- mid.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent()
+ predicate end(DataFlow::Node n) {
+ n = stringSink() or
+ regFromString(n, _)
+ }
+
+ predicate additionalStep(DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo) {
+ // include taint flow through `String` summaries
+ TaintTrackingPrivate::summaryThroughStepTaint(nodeFrom, nodeTo,
+ any(String::SummarizedCallable c))
+ or
+ // string concatenations, and
+ exists(CfgNodes::ExprNodes::OperationCfgNode op |
+ op = nodeTo.asExpr() and
+ op.getAnOperand() = nodeFrom.asExpr() and
+ op.getExpr().(Ast::BinaryOperation).getOperator() = "+"
)
+ or
+ // string interpolations
+ nodeFrom.asExpr() =
+ nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent()
}
}
-private module StringReach = Reach;
-
/**
* Gets a node that has been tracked from the string constant `start` to some node.
* This is used to figure out where `start` is evaluated as a regular expression against an input string,
* or where `start` is compiled into a regular expression.
*/
-private DataFlow::LocalSourceNode trackStrings(DataFlow::Node start, TypeTracker t) {
- t.start() and
- start = result and
- result = strStart() and
- StringReach::reached(result, t)
- or
- exists(TypeTracker t2 | t = StringReach::stepReached(t2, trackStrings(start, t2), result))
-}
+private predicate trackStrings = TypeTrack::track/2;
/** Holds if `strConst` flows to a regex compilation (tracked by `t`), where the resulting regular expression is stored in `reg`. */
pragma[nomagic]
@@ -192,39 +204,25 @@ private predicate regFromStringStart(DataFlow::Node strConst, TypeTracker t, Dat
exists(t.continue())
}
-private module RegReachInput implements ReachInputSig {
- DataFlow::LocalSourceNode start(TypeTracker t) {
- result = regStart() and
- t.start()
+private module RegTypeTrackInput implements TypeTrackInputSig {
+ DataFlow::LocalSourceNode start(TypeTracker t, DataFlow::Node start) {
+ start = regStart() and
+ t.start() and
+ result = start
or
- regFromStringStart(_, t, result)
+ regFromStringStart(start, t, result)
}
- DataFlow::Node end() { result = regSink() }
+ predicate end(DataFlow::Node n) { n = regSink() }
- predicate additionalStep(DataFlow::LocalSourceNode nodeFrom, DataFlow::LocalSourceNode nodeTo) {
- none()
- }
+ predicate additionalStep(DataFlow::Node nodeFrom, DataFlow::LocalSourceNode nodeTo) { none() }
}
-private module RegReach = Reach;
-
/**
* Gets a node that has been tracked from the regular expression `start` to some node.
* This is used to figure out where `start` is executed against an input string.
*/
-private DataFlow::LocalSourceNode trackRegs(DataFlow::Node start, TypeTracker t) {
- RegReach::reached(result, t) and
- (
- t.start() and
- start = result and
- result = regStart()
- or
- regFromStringStart(start, t, result)
- )
- or
- exists(TypeTracker t2 | t = RegReach::stepReached(t2, trackRegs(start, t2), result))
-}
+private predicate trackRegs = TypeTrack::track/2;
/** Gets a node that references a regular expression. */
private DataFlow::LocalSourceNode trackRegexpType(TypeTracker t) {
From cb8c4094fc4e330fcf94c07e7b2035abb9d0786c Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 10 May 2023 17:20:32 +0200
Subject: [PATCH 09/67] Misc: Add `--force` option
---
.../accept-expected-changes-from-ci.py | 45 ++++++++++---------
1 file changed, 24 insertions(+), 21 deletions(-)
diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py
index d4d57f26726..8eefcdc8f9a 100755
--- a/misc/scripts/accept-expected-changes-from-ci.py
+++ b/misc/scripts/accept-expected-changes-from-ci.py
@@ -17,7 +17,7 @@ execution, but it might fail in some cases ¯\_(ツ)_/¯
Code written to hack things together until they work, so don't expect much :D
"""
-
+import argparse
import sys
import re
import tempfile
@@ -221,7 +221,7 @@ def get_log_content(status: GithubStatus) -> str:
return content
-def main(pr_number: Optional[int], sha_override: Optional[str] = None):
+def main(pr_number: Optional[int], sha_override: Optional[str] = None, force=False):
if not pr_number and not sha_override:
raise Exception("Must specify either a PR number or a SHA")
@@ -237,7 +237,7 @@ def main(pr_number: Optional[int], sha_override: Optional[str] = None):
["git", "rev-parse", "HEAD"]
).decode("utf-8").strip()
- if local_sha != github_sha:
+ if local_sha != github_sha and not force:
LOGGER.error(f"GitHub SHA ({github_sha}) different from your local SHA ({local_sha}), sync your changes first!")
sys.exit(1)
sha = github_sha
@@ -421,23 +421,6 @@ def main(pr_number: Optional[int], sha_override: Optional[str] = None):
print("Expected output in semmle-code changed!")
-def call_main():
- pr_number = None
- override_sha = None
- if len(sys.argv) < 2:
- pr_number_response = subprocess.check_output([
- "gh", "pr", "view", "--json", "number"
- ]).decode("utf-8")
-
- pr_number = json.loads(pr_number_response)["number"]
- else:
- if len(sys.argv[1]) > 10:
- override_sha = sys.argv[1]
- else:
- pr_number = int(sys.argv[1])
- main(pr_number, override_sha)
-
-
if __name__ == "__main__":
level = logging.INFO
@@ -448,6 +431,10 @@ if __name__ == "__main__":
except ImportError:
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
+ # parse command line arguments
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--force", action="store_true", help="Apply patches even if the local SHA is different from the GitHub PR SHA")
+ parser.add_argument("posarg", nargs="?", default=None)
if DEBUG_LOG_FILE:
patches = make_patches_from_log_file(open(DEBUG_LOG_FILE, "r").readlines())
@@ -459,4 +446,20 @@ if __name__ == "__main__":
sys.exit(1)
os.chdir(CODEQL_REPO_DIR)
- call_main()
+
+ pr_number = None
+ override_sha = None
+ args = parser.parse_args()
+
+ if args.posarg is None:
+ pr_number_response = subprocess.check_output([
+ "gh", "pr", "view", "--json", "number"
+ ]).decode("utf-8")
+ pr_number = json.loads(pr_number_response)["number"]
+ else:
+ if len(args.posarg) > 10:
+ override_sha = args.posarg
+ else:
+ pr_number = int(args.posarg)
+
+ main(pr_number, override_sha, force=args.force)
From 54d35dbc0b7374469fa05c44fb9063bd562b051a Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 10 May 2023 17:37:16 +0200
Subject: [PATCH 10/67] Misc: Delete empty CONSISTENCY files
As requested by `@hvitved`
---
misc/scripts/accept-expected-changes-from-ci.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/misc/scripts/accept-expected-changes-from-ci.py b/misc/scripts/accept-expected-changes-from-ci.py
index 8eefcdc8f9a..12c1bb21763 100755
--- a/misc/scripts/accept-expected-changes-from-ci.py
+++ b/misc/scripts/accept-expected-changes-from-ci.py
@@ -66,7 +66,7 @@ if SEMMLE_CODE_DIR is None:
@dataclass(frozen=True, eq=True, order=True)
class Patch:
- filename: str
+ filename: Path
dir: Optional[str]
patch_first_line: str
patch: List[str] = field(hash=False)
@@ -409,6 +409,13 @@ def main(pr_number: Optional[int], sha_override: Optional[str] = None, force=Fal
continue
subprocess.check_call(["git", "apply", temp.name], cwd=patch.dir)
+
+ if "CONSISTENCY" in patch.filename.parts:
+ # delete if empty
+ if os.path.getsize(patch.filename) == 1 and patch.filename.read_text() == "\n":
+ os.remove(patch.filename)
+ LOGGER.info(f"Deleted empty CONSISTENCY file '{patch.filename}'")
+
if patch.dir == SEMMLE_CODE_DIR:
semmle_code_changed = True
except subprocess.CalledProcessError:
From 760ba82c7acdd8c52eddc455afc9cd35c2869e16 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 11 May 2023 16:40:59 +0100
Subject: [PATCH 11/67] Fix unit tests
---
.../cli/go-autobuilder/go-autobuilder_test.go | 60 ++++++++-----------
1 file changed, 26 insertions(+), 34 deletions(-)
diff --git a/go/extractor/cli/go-autobuilder/go-autobuilder_test.go b/go/extractor/cli/go-autobuilder/go-autobuilder_test.go
index caaa06e234d..8cb97be17ec 100644
--- a/go/extractor/cli/go-autobuilder/go-autobuilder_test.go
+++ b/go/extractor/cli/go-autobuilder/go-autobuilder_test.go
@@ -36,45 +36,37 @@ func TestParseGoVersion(t *testing.T) {
func TestGetVersionToInstall(t *testing.T) {
tests := map[versionInfo]string{
- // checkForUnsupportedVersions()
-
- // go.mod version below minGoVersion
- {"0.0", true, "1.20.3", true}: "",
- {"0.0", true, "9999.0", true}: "",
- {"0.0", true, "1.2.2", true}: "",
- {"0.0", true, "", false}: "",
- // go.mod version above maxGoVersion
- {"9999.0", true, "1.20.3", true}: "",
- {"9999.0", true, "9999.0.1", true}: "",
- {"9999.0", true, "1.1", true}: "",
- {"9999.0", true, "", false}: "",
- // Go installation found with version below minGoVersion
- {"1.20", true, "1.2.2", true}: "1.20",
- {"1.11", true, "1.2.2", true}: "1.11",
+ // getVersionWhenGoModVersionNotFound()
+ {"", false, "", false}: maxGoVersion,
{"", false, "1.2.2", true}: maxGoVersion,
- // Go installation found with version above maxGoVersion
+ {"", false, "9999.0.1", true}: maxGoVersion,
+ {"", false, "1.11.13", true}: "",
+ {"", false, "1.20.3", true}: "",
+
+ // getVersionWhenGoModVersionTooHigh()
+ {"9999.0", true, "", false}: maxGoVersion,
+ {"9999.0", true, "9999.0.1", true}: "",
+ {"9999.0", true, "1.1", true}: maxGoVersion,
+ {"9999.0", true, minGoVersion, false}: maxGoVersion,
+ {"9999.0", true, maxGoVersion, true}: "",
+
+ // getVersionWhenGoModVersionTooLow()
+ {"0.0", true, "", false}: minGoVersion,
+ {"0.0", true, "9999.0", true}: minGoVersion,
+ {"0.0", true, "1.2.2", true}: minGoVersion,
+ {"0.0", true, "1.20.3", true}: "",
+
+ // getVersionWhenGoModVersionSupported()
+ {"1.20", true, "", false}: "1.20",
+ {"1.11", true, "", false}: "1.11",
+ {"1.20", true, "1.2.2", true}: "1.20",
+ {"1.11", true, "1.2.2", true}: "1.11",
{"1.20", true, "9999.0.1", true}: "1.20",
{"1.11", true, "9999.0.1", true}: "1.11",
- {"", false, "9999.0.1", true}: maxGoVersion,
-
- // checkForVersionsNotFound()
-
- // Go installation not found, go.mod version in supported range
- {"1.20", true, "", false}: "1.20",
- {"1.11", true, "", false}: "1.11",
- // Go installation not found, go.mod not found
- {"", false, "", false}: maxGoVersion,
- // Go installation found with version in supported range, go.mod not found
- {"", false, "1.11.13", true}: "",
- {"", false, "1.20.3", true}: "",
-
- // compareVersions()
-
- // Go installation found with version in supported range, go.mod version in supported range and go.mod version > go installation version
+ // go.mod version > go installation version
{"1.20", true, "1.11.13", true}: "1.20",
{"1.20", true, "1.12", true}: "1.20",
- // Go installation found with version in supported range, go.mod version in supported range and go.mod version <= go installation version
- // (Note comparisons ignore the patch version)
+ // go.mod version <= go installation version (Note comparisons ignore the patch version)
{"1.11", true, "1.20", true}: "",
{"1.11", true, "1.20.3", true}: "",
{"1.20", true, "1.20.3", true}: "",
From 3981bb1f58f6f8514123f160771d1be2388ef288 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 11 May 2023 17:10:02 +0100
Subject: [PATCH 12/67] Indent comment in Makefile better
---
go/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/go/Makefile b/go/Makefile
index 8950bac6a21..60a47fd09d6 100644
--- a/go/Makefile
+++ b/go/Makefile
@@ -113,7 +113,7 @@ ql/lib/go.dbscheme.stats: ql/lib/go.dbscheme build/stats/src.stamp extractor
test: all build/testdb/check-upgrade-path
codeql test run -j0 ql/test --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache)
- # use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported
+# use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported
env GOOS=linux GOARCH=386 codeql$(EXE) test run -j0 ql/test/query-tests/Security/CWE-681 --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache)
cd extractor; go test -mod=vendor ./... | grep -vF "[no test files]"
bash extractor-smoke-test/test.sh || (echo "Extractor smoke test FAILED"; exit 1)
From 77c83577052ff79e839ebf8017cdb07425010254 Mon Sep 17 00:00:00 2001
From: Owen Mansel-Chan
Date: Thu, 11 May 2023 17:07:47 +0100
Subject: [PATCH 13/67] Do not obscure exit code with call to grep
The output is a bit more verbose, but this is hard to avoid
---
go/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/go/Makefile b/go/Makefile
index 60a47fd09d6..7e119b36f03 100644
--- a/go/Makefile
+++ b/go/Makefile
@@ -115,7 +115,7 @@ test: all build/testdb/check-upgrade-path
codeql test run -j0 ql/test --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache)
# use GOOS=linux because GOOS=darwin GOARCH=386 is no longer supported
env GOOS=linux GOARCH=386 codeql$(EXE) test run -j0 ql/test/query-tests/Security/CWE-681 --search-path build/codeql-extractor-go --consistency-queries ql/test/consistency --compilation-cache=$(cache)
- cd extractor; go test -mod=vendor ./... | grep -vF "[no test files]"
+ cd extractor; go test -mod=vendor ./...
bash extractor-smoke-test/test.sh || (echo "Extractor smoke test FAILED"; exit 1)
.PHONY: build/testdb/check-upgrade-path
From 75e36e89de6ab7c1ff71235a7ab9297ee23f60fe Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 10:34:48 +0100
Subject: [PATCH 14/67] C++: Precompute the set of necessary states.
---
.../Likely Bugs/OverrunWriteProductFlow.ql | 111 +++++++-
.../CWE-119/OverrunWriteProductFlow.expected | 248 +-----------------
2 files changed, 110 insertions(+), 249 deletions(-)
diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
index 79a5497f46d..e35c48c9d9b 100644
--- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
+++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
@@ -78,6 +78,113 @@ predicate isSinkPairImpl(
)
}
+module ValidState {
+ /**
+ * In the `StringSizeConfig` configuration we use an integer as the flow state for the second
+ * projection of the dataflow graph. The integer represents an offset that is added to the
+ * size of the allocation. For example, given:
+ * ```cpp
+ * char* p = new char[size + 1];
+ * size += 1;
+ * memset(p, 0, size);
+ * ```
+ * the initial flow state is `1`. This represents the fact that `size + 1` is a valid bound
+ * for the size of the allocation pointed to by `p`. After updating the size using `+=`, the
+ * flow state changes to `0`, which represents the fact that `size + 0` is a valid bound for
+ * the allocation.
+ *
+ * So we need to compute a set of valid integers that represent the offset applied to the
+ * size. We do this in two steps:
+ * 1. We first perform the dataflow traversal that the second projection of the product-flow
+ * library will perform, and visit all the places where the size argument is modified.
+ * 2. Once that dataflow traversal is done, we accumulate the offsets added at each places
+ * where the offset is modified (see `validStateImpl`).
+ *
+ * Because we want to guarantee that each place where we modify the offset has a `PathNode`
+ * we "flip" a boolean flow state in each `isAdditionalFlowStep`. This ensures that the node
+ * has a corresponding `PathNode`.
+ */
+ private module ValidStateConfig implements DataFlow::StateConfigSig {
+ class FlowState = boolean;
+
+ predicate isSource(DataFlow::Node source, FlowState state) {
+ hasSize(_, source, _) and
+ state = false
+ }
+
+ predicate isSink(DataFlow::Node sink, FlowState state) {
+ isSinkPairImpl(_, _, sink, _, _) and
+ state = [false, true]
+ }
+
+ predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
+
+ predicate isAdditionalFlowStep(
+ DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
+ ) {
+ exists(AddInstruction add, Operand op, int delta |
+ add.hasOperands(node1.asOperand(), op) and
+ semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
+ node2.asInstruction() = add and
+ state1 = [false, true] and
+ state2 = state1.booleanNot()
+ )
+ }
+
+ predicate includeHiddenNodes() { any() }
+ }
+
+ private import DataFlow::GlobalWithState
+
+ private predicate inLoop(PathNode n) { n.getASuccessor+() = n }
+
+ /**
+ * Holds if `value` is a possible offset for `n`.
+ *
+ * To ensure termination, we limit `value` to be in the
+ * range `[-2, 2]` if the node is part of a loop. Without
+ * this restriction we wouldn't terminate on an example like:
+ * ```cpp
+ * while(unknown()) { size++; }
+ * ```
+ */
+ private predicate validStateImpl(PathNode n, int value) {
+ (inLoop(n) implies value = [-2 .. 2]) and
+ (
+ hasSize(_, n.getNode(), value)
+ or
+ exists(int delta, PathNode n0 |
+ n0.getASuccessor() = n and
+ validStateImpl(n0, value) and
+ isSinkPairImpl(_, _, n.getNode(), delta, _) and
+ delta > value
+ )
+ or
+ exists(PathNode n0, DataFlow::Node node, int value0 |
+ n0.getASuccessor() = n and
+ validStateImpl(n0, value0) and
+ node = n.getNode()
+ |
+ exists(AddInstruction add, Operand op1, Operand op2, int delta |
+ add = node.asInstruction() and
+ add.hasOperands(op1, op2) and
+ value0 = value + delta and
+ semBounded(getSemanticExpr([op1, op2].getDef()), any(SemZeroBound zero), delta, true, _)
+ )
+ or
+ not node.asInstruction() instanceof AddInstruction and
+ value = value0
+ )
+ )
+ }
+
+ predicate validState(DataFlow::Node n, int value) {
+ validStateImpl(any(PathNode pn | pn.getNode() = n), value)
+ }
+}
+
+import ValidState
+
module StringSizeConfig implements ProductFlow::StateConfigSig {
class FlowState1 = Unit;
@@ -100,7 +207,7 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
DataFlow::Node bufSink, FlowState1 state1, DataFlow::Node sizeSink, FlowState2 state2
) {
exists(state1) and
- state2 = [-32 .. 32] and // An arbitrary bound because we need to bound `state2`
+ validState(sizeSink, state2) and
exists(int delta |
isSinkPairImpl(_, bufSink, sizeSink, delta, _) and
delta > state2
@@ -120,8 +227,8 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
predicate isAdditionalFlowStep2(
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
+ validState(node2, state2) and
exists(AddInstruction add, Operand op, int delta, int s1, int s2 |
- s1 = [-32 .. 32] and // An arbitrary bound because we need to bound `state`
state1 = s1 and
state2 = s2 and
add.hasOperands(node1.asOperand(), op) and
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
index 3b450ac9b8f..b8d75b618c6 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
@@ -1,202 +1,62 @@
edges
-| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:24:21:24:31 | call to mk_string_t indirection [string] |
-| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:34:21:34:31 | call to mk_string_t indirection [string] |
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] |
| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... |
-| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | test.cpp:26:13:26:15 | str indirection [string] |
-| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string |
-| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string indirection |
-| test.cpp:26:18:26:23 | string indirection | test.cpp:26:18:26:23 | string |
-| test.cpp:29:32:29:34 | str indirection [string] | test.cpp:30:13:30:15 | str indirection [string] |
-| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string |
-| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string indirection |
-| test.cpp:30:18:30:23 | string indirection | test.cpp:30:18:30:23 | string |
-| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | test.cpp:35:21:35:23 | str indirection [string] |
-| test.cpp:35:21:35:23 | str indirection [string] | test.cpp:29:32:29:34 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:41:13:41:15 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:44:13:44:15 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:45:13:45:15 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:48:17:48:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:52:17:52:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:56:17:56:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:60:17:60:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:64:17:64:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:68:17:68:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:76:17:76:19 | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] |
-| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:84:17:84:19 | str indirection [string] |
-| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string |
-| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string indirection |
-| test.cpp:41:18:41:23 | string indirection | test.cpp:41:18:41:23 | string |
| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string |
| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string indirection |
| test.cpp:42:18:42:23 | string indirection | test.cpp:42:18:42:23 | string |
-| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string |
-| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string indirection |
-| test.cpp:44:18:44:23 | string indirection | test.cpp:44:18:44:23 | string |
-| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string |
-| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string indirection |
-| test.cpp:45:18:45:23 | string indirection | test.cpp:45:18:45:23 | string |
-| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string |
-| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string indirection |
-| test.cpp:48:22:48:27 | string indirection | test.cpp:48:22:48:27 | string |
-| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string |
-| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string indirection |
-| test.cpp:52:22:52:27 | string indirection | test.cpp:52:22:52:27 | string |
-| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string |
-| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string indirection |
-| test.cpp:56:22:56:27 | string indirection | test.cpp:56:22:56:27 | string |
-| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string |
-| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string indirection |
-| test.cpp:60:22:60:27 | string indirection | test.cpp:60:22:60:27 | string |
-| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string |
-| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string indirection |
-| test.cpp:64:22:64:27 | string indirection | test.cpp:64:22:64:27 | string |
-| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string |
-| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string indirection |
-| test.cpp:68:22:68:27 | string indirection | test.cpp:68:22:68:27 | string |
| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string |
| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string indirection |
| test.cpp:72:22:72:27 | string indirection | test.cpp:72:22:72:27 | string |
-| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string |
-| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string indirection |
-| test.cpp:76:22:76:27 | string indirection | test.cpp:76:22:76:27 | string |
| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string |
| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string indirection |
| test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string |
-| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string |
-| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string indirection |
-| test.cpp:84:22:84:27 | string indirection | test.cpp:84:22:84:27 | string |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] |
| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:98:13:98:15 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:101:13:101:15 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:102:13:102:15 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:105:17:105:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:109:17:109:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:113:17:113:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:117:17:117:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:121:17:121:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:125:17:125:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:133:17:133:19 | str indirection [string] |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] |
-| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:141:17:141:19 | str indirection [string] |
-| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string |
-| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string indirection |
-| test.cpp:98:18:98:23 | string indirection | test.cpp:98:18:98:23 | string |
| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string |
| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string indirection |
| test.cpp:99:18:99:23 | string indirection | test.cpp:99:18:99:23 | string |
-| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string |
-| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string indirection |
-| test.cpp:101:18:101:23 | string indirection | test.cpp:101:18:101:23 | string |
-| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string |
-| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string indirection |
-| test.cpp:102:18:102:23 | string indirection | test.cpp:102:18:102:23 | string |
-| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string |
-| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string indirection |
-| test.cpp:105:22:105:27 | string indirection | test.cpp:105:22:105:27 | string |
-| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string |
-| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string indirection |
-| test.cpp:109:22:109:27 | string indirection | test.cpp:109:22:109:27 | string |
-| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string |
-| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string indirection |
-| test.cpp:113:22:113:27 | string indirection | test.cpp:113:22:113:27 | string |
-| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string |
-| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string indirection |
-| test.cpp:117:22:117:27 | string indirection | test.cpp:117:22:117:27 | string |
-| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string |
-| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string indirection |
-| test.cpp:121:22:121:27 | string indirection | test.cpp:121:22:121:27 | string |
-| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string |
-| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string indirection |
-| test.cpp:125:22:125:27 | string indirection | test.cpp:125:22:125:27 | string |
| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string |
| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string indirection |
| test.cpp:129:22:129:27 | string indirection | test.cpp:129:22:129:27 | string |
-| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string |
-| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string indirection |
-| test.cpp:133:22:133:27 | string indirection | test.cpp:133:22:133:27 | string |
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string |
| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection |
| test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string |
-| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string |
-| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string indirection |
-| test.cpp:141:22:141:27 | string indirection | test.cpp:141:22:141:27 | string |
| test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:150:13:150:15 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:151:13:151:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:155:13:155:15 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:159:17:159:19 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:163:17:163:19 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:167:17:167:19 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:171:17:171:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:179:17:179:19 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:183:17:183:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] |
-| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:191:17:191:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] |
| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... |
-| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string |
-| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string indirection |
-| test.cpp:150:18:150:23 | string indirection | test.cpp:150:18:150:23 | string |
-| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string |
-| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string indirection |
-| test.cpp:151:18:151:23 | string indirection | test.cpp:151:18:151:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string |
| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection |
| test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string |
| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string |
| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string indirection |
| test.cpp:154:18:154:23 | string indirection | test.cpp:154:18:154:23 | string |
-| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string |
-| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string indirection |
-| test.cpp:155:18:155:23 | string indirection | test.cpp:155:18:155:23 | string |
| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string |
| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string indirection |
| test.cpp:156:18:156:23 | string indirection | test.cpp:156:18:156:23 | string |
-| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string |
-| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string indirection |
-| test.cpp:159:22:159:27 | string indirection | test.cpp:159:22:159:27 | string |
-| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string |
-| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string indirection |
-| test.cpp:163:22:163:27 | string indirection | test.cpp:163:22:163:27 | string |
-| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string |
-| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string indirection |
-| test.cpp:167:22:167:27 | string indirection | test.cpp:167:22:167:27 | string |
-| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string |
-| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string indirection |
-| test.cpp:171:22:171:27 | string indirection | test.cpp:171:22:171:27 | string |
| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string |
| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string indirection |
| test.cpp:175:22:175:27 | string indirection | test.cpp:175:22:175:27 | string |
-| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string |
-| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string indirection |
-| test.cpp:179:22:179:27 | string indirection | test.cpp:179:22:179:27 | string |
-| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string |
-| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string indirection |
-| test.cpp:183:22:183:27 | string indirection | test.cpp:183:22:183:27 | string |
| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string |
| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string indirection |
| test.cpp:187:22:187:27 | string indirection | test.cpp:187:22:187:27 | string |
-| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string |
-| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string indirection |
-| test.cpp:191:22:191:27 | string indirection | test.cpp:191:22:191:27 | string |
| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string |
| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string indirection |
| test.cpp:195:22:195:27 | string indirection | test.cpp:195:22:195:27 | string |
@@ -228,154 +88,48 @@ nodes
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
| test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc |
-| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
-| test.cpp:26:13:26:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:26:18:26:23 | string | semmle.label | string |
-| test.cpp:26:18:26:23 | string indirection | semmle.label | string indirection |
-| test.cpp:29:32:29:34 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:30:13:30:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:30:18:30:23 | string | semmle.label | string |
-| test.cpp:30:18:30:23 | string indirection | semmle.label | string indirection |
-| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
-| test.cpp:35:21:35:23 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] |
-| test.cpp:41:13:41:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:41:18:41:23 | string | semmle.label | string |
-| test.cpp:41:18:41:23 | string indirection | semmle.label | string indirection |
| test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:42:18:42:23 | string | semmle.label | string |
| test.cpp:42:18:42:23 | string indirection | semmle.label | string indirection |
-| test.cpp:44:13:44:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:44:18:44:23 | string | semmle.label | string |
-| test.cpp:44:18:44:23 | string indirection | semmle.label | string indirection |
-| test.cpp:45:13:45:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:45:18:45:23 | string | semmle.label | string |
-| test.cpp:45:18:45:23 | string indirection | semmle.label | string indirection |
-| test.cpp:48:17:48:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:48:22:48:27 | string | semmle.label | string |
-| test.cpp:48:22:48:27 | string indirection | semmle.label | string indirection |
-| test.cpp:52:17:52:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:52:22:52:27 | string | semmle.label | string |
-| test.cpp:52:22:52:27 | string indirection | semmle.label | string indirection |
-| test.cpp:56:17:56:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:56:22:56:27 | string | semmle.label | string |
-| test.cpp:56:22:56:27 | string indirection | semmle.label | string indirection |
-| test.cpp:60:17:60:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:60:22:60:27 | string | semmle.label | string |
-| test.cpp:60:22:60:27 | string indirection | semmle.label | string indirection |
-| test.cpp:64:17:64:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:64:22:64:27 | string | semmle.label | string |
-| test.cpp:64:22:64:27 | string indirection | semmle.label | string indirection |
-| test.cpp:68:17:68:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:68:22:68:27 | string | semmle.label | string |
-| test.cpp:68:22:68:27 | string indirection | semmle.label | string indirection |
| test.cpp:72:17:72:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:72:22:72:27 | string | semmle.label | string |
| test.cpp:72:22:72:27 | string indirection | semmle.label | string indirection |
-| test.cpp:76:17:76:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:76:22:76:27 | string | semmle.label | string |
-| test.cpp:76:22:76:27 | string indirection | semmle.label | string indirection |
| test.cpp:80:17:80:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:80:22:80:27 | string | semmle.label | string |
| test.cpp:80:22:80:27 | string indirection | semmle.label | string indirection |
-| test.cpp:84:17:84:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:84:22:84:27 | string | semmle.label | string |
-| test.cpp:84:22:84:27 | string indirection | semmle.label | string indirection |
| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | semmle.label | mk_string_t_plus_one indirection [string] |
| test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc |
| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] |
-| test.cpp:98:13:98:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:98:18:98:23 | string | semmle.label | string |
-| test.cpp:98:18:98:23 | string indirection | semmle.label | string indirection |
| test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:99:18:99:23 | string | semmle.label | string |
| test.cpp:99:18:99:23 | string indirection | semmle.label | string indirection |
-| test.cpp:101:13:101:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:101:18:101:23 | string | semmle.label | string |
-| test.cpp:101:18:101:23 | string indirection | semmle.label | string indirection |
-| test.cpp:102:13:102:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:102:18:102:23 | string | semmle.label | string |
-| test.cpp:102:18:102:23 | string indirection | semmle.label | string indirection |
-| test.cpp:105:17:105:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:105:22:105:27 | string | semmle.label | string |
-| test.cpp:105:22:105:27 | string indirection | semmle.label | string indirection |
-| test.cpp:109:17:109:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:109:22:109:27 | string | semmle.label | string |
-| test.cpp:109:22:109:27 | string indirection | semmle.label | string indirection |
-| test.cpp:113:17:113:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:113:22:113:27 | string | semmle.label | string |
-| test.cpp:113:22:113:27 | string indirection | semmle.label | string indirection |
-| test.cpp:117:17:117:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:117:22:117:27 | string | semmle.label | string |
-| test.cpp:117:22:117:27 | string indirection | semmle.label | string indirection |
-| test.cpp:121:17:121:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:121:22:121:27 | string | semmle.label | string |
-| test.cpp:121:22:121:27 | string indirection | semmle.label | string indirection |
-| test.cpp:125:17:125:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:125:22:125:27 | string | semmle.label | string |
-| test.cpp:125:22:125:27 | string indirection | semmle.label | string indirection |
| test.cpp:129:17:129:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:129:22:129:27 | string | semmle.label | string |
| test.cpp:129:22:129:27 | string indirection | semmle.label | string indirection |
-| test.cpp:133:17:133:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:133:22:133:27 | string | semmle.label | string |
-| test.cpp:133:22:133:27 | string indirection | semmle.label | string indirection |
| test.cpp:137:17:137:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:137:22:137:27 | string | semmle.label | string |
| test.cpp:137:22:137:27 | string indirection | semmle.label | string indirection |
-| test.cpp:141:17:141:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:141:22:141:27 | string | semmle.label | string |
-| test.cpp:141:22:141:27 | string indirection | semmle.label | string indirection |
| test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... |
| test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] |
| test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc |
-| test.cpp:150:13:150:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:150:18:150:23 | string | semmle.label | string |
-| test.cpp:150:18:150:23 | string indirection | semmle.label | string indirection |
-| test.cpp:151:13:151:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:151:18:151:23 | string | semmle.label | string |
-| test.cpp:151:18:151:23 | string indirection | semmle.label | string indirection |
| test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:152:18:152:23 | string | semmle.label | string |
| test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection |
| test.cpp:154:13:154:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:154:18:154:23 | string | semmle.label | string |
| test.cpp:154:18:154:23 | string indirection | semmle.label | string indirection |
-| test.cpp:155:13:155:15 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:155:18:155:23 | string | semmle.label | string |
-| test.cpp:155:18:155:23 | string indirection | semmle.label | string indirection |
| test.cpp:156:13:156:15 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:156:18:156:23 | string | semmle.label | string |
| test.cpp:156:18:156:23 | string indirection | semmle.label | string indirection |
-| test.cpp:159:17:159:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:159:22:159:27 | string | semmle.label | string |
-| test.cpp:159:22:159:27 | string indirection | semmle.label | string indirection |
-| test.cpp:163:17:163:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:163:22:163:27 | string | semmle.label | string |
-| test.cpp:163:22:163:27 | string indirection | semmle.label | string indirection |
-| test.cpp:167:17:167:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:167:22:167:27 | string | semmle.label | string |
-| test.cpp:167:22:167:27 | string indirection | semmle.label | string indirection |
-| test.cpp:171:17:171:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:171:22:171:27 | string | semmle.label | string |
-| test.cpp:171:22:171:27 | string indirection | semmle.label | string indirection |
| test.cpp:175:17:175:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:175:22:175:27 | string | semmle.label | string |
| test.cpp:175:22:175:27 | string indirection | semmle.label | string indirection |
-| test.cpp:179:17:179:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:179:22:179:27 | string | semmle.label | string |
-| test.cpp:179:22:179:27 | string indirection | semmle.label | string indirection |
-| test.cpp:183:17:183:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:183:22:183:27 | string | semmle.label | string |
-| test.cpp:183:22:183:27 | string indirection | semmle.label | string indirection |
| test.cpp:187:17:187:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:187:22:187:27 | string | semmle.label | string |
| test.cpp:187:22:187:27 | string indirection | semmle.label | string indirection |
-| test.cpp:191:17:191:19 | str indirection [string] | semmle.label | str indirection [string] |
-| test.cpp:191:22:191:27 | string | semmle.label | string |
-| test.cpp:191:22:191:27 | string indirection | semmle.label | string indirection |
| test.cpp:195:17:195:19 | str indirection [string] | semmle.label | str indirection [string] |
| test.cpp:195:22:195:27 | string | semmle.label | string |
| test.cpp:195:22:195:27 | string indirection | semmle.label | string indirection |
@@ -423,6 +177,6 @@ subpaths
| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string |
| test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string |
| test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string |
-| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer |
+| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 2 elements. | test.cpp:232:10:232:15 | buffer | buffer |
| test.cpp:243:5:243:10 | call to memset | test.cpp:241:27:241:32 | call to malloc | test.cpp:243:12:243:21 | string | This write may overflow $@ by 1 element. | test.cpp:243:16:243:21 | string | string |
| test.cpp:250:5:250:10 | call to memset | test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p | This write may overflow $@ by 1 element. | test.cpp:250:12:250:12 | p | p |
From e58b99ddd127d20194a6e0aeff0e2665e1306fbd Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 11:18:04 +0100
Subject: [PATCH 15/67] C++: Don't carry the sources around as columns during
the main loop of product flow.
---
.../semmle/code/cpp/dataflow/ProductFlow.qll | 87 +++++++++++++++----
1 file changed, 68 insertions(+), 19 deletions(-)
diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
index c2c27158434..12904fd6d0b 100644
--- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
+++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
@@ -324,25 +324,71 @@ module ProductFlow {
module Flow2 = DataFlow::GlobalWithState;
+ private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) {
+ Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
+ }
+
+ private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) {
+ Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
+ }
+
+ pragma[assume_small_delta]
pragma[nomagic]
- private predicate reachableInterprocEntry(
- Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2
- ) {
- Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and
- node1 = source1 and
- node2 = source2
+ private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
+ isSourcePair(node1, node2)
or
- exists(
- Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1,
- Flow2::PathNode midExit2
- |
- reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and
- interprocEdgePair(midExit1, midExit2, node1, node2) and
- localPathStep1*(midEntry1, midExit1) and
- localPathStep2*(midEntry2, midExit2)
+ exists(Flow1::PathNode pred1, Flow2::PathNode pred2 |
+ fwdReachableInterprocEntry(pred1, pred2) and
+ isSuccessor(pred1, pred2, node1, node2)
)
}
+ bindingset[pred1, pred2]
+ bindingset[succ1, succ2]
+ private predicate isSuccessor(
+ Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
+ ) {
+ exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
+ localPathStep1*(pred1, mid1) and
+ localPathStep2*(pred2, mid2)
+ |
+ isSinkPair(mid1, mid2) and
+ succ1 = mid1 and
+ succ2 = mid2
+ or
+ interprocEdgePair(mid1, mid2, succ1, succ2)
+ )
+ }
+
+ pragma[assume_small_delta]
+ pragma[nomagic]
+ private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
+ fwdReachableInterprocEntry(node1, node2) and
+ (
+ isSinkPair(node1, node2)
+ or
+ exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
+ revReachableInterprocEntry(succ1, succ2) and
+ isSuccessor(node1, node2, succ1, succ2)
+ )
+ )
+ }
+
+ private newtype TNodePair =
+ TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) {
+ revReachableInterprocEntry(node1, node2)
+ }
+
+ private predicate pathSucc(TNodePair n1, TNodePair n2) {
+ exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
+ n1 = TMkNodePair(n11, n12) and
+ n2 = TMkNodePair(n21, n22) and
+ isSuccessor(n11, n12, n21, n22)
+ )
+ }
+
+ private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
+
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
Flow1::PathGraph::edges(pred, succ) and
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
@@ -474,11 +520,14 @@ module ProductFlow {
private predicate reachable(
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
) {
- exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
- reachableInterprocEntry(source1, source2, mid1, mid2) and
- Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and
- localPathStep1*(mid1, sink1) and
- localPathStep2*(mid2, sink2)
+ isSourcePair(source1, source2) and
+ isSinkPair(sink1, sink2) and
+ exists(TNodePair n1, TNodePair n2 |
+ n1 = TMkNodePair(source1, source2) and
+ n2 = TMkNodePair(sink1, sink2)
+ |
+ pathSuccPlus(n1, n2) or
+ n1 = n2
)
}
}
From 594da1a21aa7a6ae271d23ba25724b8ab3399bd4 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 12:05:09 +0100
Subject: [PATCH 16/67] C++: Speedup 'isSuccessor'.
---
.../semmle/code/cpp/dataflow/ProductFlow.qll | 85 ++++++++++++++++++-
1 file changed, 83 insertions(+), 2 deletions(-)
diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
index 12904fd6d0b..3dafcd790c2 100644
--- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
+++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
@@ -343,14 +343,95 @@ module ProductFlow {
)
}
+ pragma[assume_small_delta]
+ pragma[nomagic]
+ private predicate fwdLocalPathStep1(Flow1::PathNode n) {
+ fwdReachableInterprocEntry(n, _)
+ or
+ exists(Flow1::PathNode mid |
+ fwdLocalPathStep1(mid) and
+ localPathStep1(mid, n)
+ )
+ }
+
+ pragma[assume_small_delta]
+ pragma[nomagic]
+ private predicate revLocalPathStep1(Flow1::PathNode n) {
+ fwdLocalPathStep1(n) and
+ (
+ isSinkPair(n, _)
+ or
+ interprocEdgePair(n, _, _, _)
+ or
+ exists(Flow1::PathNode mid |
+ revLocalPathStep1(mid) and
+ localPathStep1(n, mid)
+ )
+ )
+ }
+
+ pragma[assume_small_delta]
+ private predicate prunedLocalPathStep1(Flow1::PathNode n1, Flow1::PathNode n2) {
+ revLocalPathStep1(n1) and
+ revLocalPathStep1(n2) and
+ localPathStep1(n1, n2)
+ }
+
+ pragma[nomagic]
+ private predicate fwdLocalPathStep2(Flow2::PathNode n) {
+ fwdReachableInterprocEntry(_, n)
+ or
+ exists(Flow2::PathNode mid |
+ fwdLocalPathStep2(mid) and
+ localPathStep2(mid, n)
+ )
+ }
+
+ pragma[assume_small_delta]
+ pragma[nomagic]
+ private predicate revLocalPathStep2(Flow2::PathNode n) {
+ fwdLocalPathStep2(n) and
+ (
+ isSinkPair(_, n)
+ or
+ interprocEdgePair(_, n, _, _)
+ or
+ exists(Flow2::PathNode mid |
+ revLocalPathStep2(mid) and
+ localPathStep2(n, mid)
+ )
+ )
+ }
+
+ pragma[assume_small_delta]
+ private predicate prunedLocalPathStep2(Flow2::PathNode n1, Flow2::PathNode n2) {
+ revLocalPathStep2(n1) and
+ revLocalPathStep2(n2) and
+ localPathStep2(n1, n2)
+ }
+
+ private predicate localPathStep1SuccPlus(Flow1::PathNode n1, Flow1::PathNode n2) =
+ fastTC(prunedLocalPathStep1/2)(n1, n2)
+
+ private predicate localPathStep2SuccPlus(Flow2::PathNode n1, Flow2::PathNode n2) =
+ fastTC(prunedLocalPathStep2/2)(n1, n2)
+
+ private predicate localPathStep1Tc(Flow1::PathNode n1, Flow1::PathNode n2) {
+ localPathStep1SuccPlus(n1, n2) or n1 = n2
+ }
+
+ private predicate localPathStep2Tc(Flow2::PathNode n1, Flow2::PathNode n2) {
+ localPathStep2SuccPlus(n1, n2) or n1 = n2
+ }
+
bindingset[pred1, pred2]
bindingset[succ1, succ2]
private predicate isSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
- localPathStep1*(pred1, mid1) and
- localPathStep2*(pred2, mid2)
+ localPathStep1Tc(pred1, mid1) and
+ localPathStep2Tc(pred2, mid2)
|
isSinkPair(mid1, mid2) and
succ1 = mid1 and
From 2458fa0ab3aa598306d4aad57fc0809d31dbc7d9 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 12:50:40 +0100
Subject: [PATCH 17/67] C++: Push conjunct into 'isSuccessor' and rename it to
'fwdIsSuccessor'.
---
.../semmle/code/cpp/dataflow/ProductFlow.qll | 24 +++++++------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
index 3dafcd790c2..d21391bc93c 100644
--- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
+++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
@@ -337,10 +337,7 @@ module ProductFlow {
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
isSourcePair(node1, node2)
or
- exists(Flow1::PathNode pred1, Flow2::PathNode pred2 |
- fwdReachableInterprocEntry(pred1, pred2) and
- isSuccessor(pred1, pred2, node1, node2)
- )
+ fwdIsSuccessor(_, _, node1, node2)
}
pragma[assume_small_delta]
@@ -424,11 +421,10 @@ module ProductFlow {
localPathStep2SuccPlus(n1, n2) or n1 = n2
}
- bindingset[pred1, pred2]
- bindingset[succ1, succ2]
- private predicate isSuccessor(
+ private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
+ fwdReachableInterprocEntry(pred1, pred2) and
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
localPathStep1Tc(pred1, mid1) and
localPathStep2Tc(pred2, mid2)
@@ -445,13 +441,11 @@ module ProductFlow {
pragma[nomagic]
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
fwdReachableInterprocEntry(node1, node2) and
- (
- isSinkPair(node1, node2)
- or
- exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
- revReachableInterprocEntry(succ1, succ2) and
- isSuccessor(node1, node2, succ1, succ2)
- )
+ isSinkPair(node1, node2)
+ or
+ exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
+ revReachableInterprocEntry(succ1, succ2) and
+ fwdIsSuccessor(node1, node2, succ1, succ2)
)
}
@@ -464,7 +458,7 @@ module ProductFlow {
exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
n1 = TMkNodePair(n11, n12) and
n2 = TMkNodePair(n21, n22) and
- isSuccessor(n11, n12, n21, n22)
+ fwdIsSuccessor(n11, n12, n21, n22)
)
}
From 0b7fc3cbf758568b5b621d3d41bb8086788db4fa Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 13:00:39 +0100
Subject: [PATCH 18/67] C++: Add a FP testcase involving flow through
back-edges.
---
.../Security/CWE/CWE-119/OverrunWriteProductFlow.expected | 4 ++++
.../query-tests/Security/CWE/CWE-119/test.cpp | 8 ++++++++
2 files changed, 12 insertions(+)
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
index 3b450ac9b8f..eee8b698399 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
@@ -223,6 +223,7 @@ edges
| test.cpp:243:12:243:14 | str indirection [string] | test.cpp:243:16:243:21 | string indirection |
| test.cpp:243:16:243:21 | string indirection | test.cpp:243:12:243:21 | string |
| test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p |
+| test.cpp:256:17:256:22 | call to malloc | test.cpp:257:12:257:12 | p |
nodes
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] |
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
@@ -405,6 +406,8 @@ nodes
| test.cpp:243:16:243:21 | string indirection | semmle.label | string indirection |
| test.cpp:249:20:249:27 | call to my_alloc | semmle.label | call to my_alloc |
| test.cpp:250:12:250:12 | p | semmle.label | p |
+| test.cpp:256:17:256:22 | call to malloc | semmle.label | call to malloc |
+| test.cpp:257:12:257:12 | p | semmle.label | p |
subpaths
| test.cpp:242:22:242:27 | buffer | test.cpp:235:40:235:45 | buffer | test.cpp:236:12:236:17 | p_str indirection [post update] [string] | test.cpp:242:16:242:19 | set_string output argument [string] |
#select
@@ -426,3 +429,4 @@ subpaths
| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer |
| test.cpp:243:5:243:10 | call to memset | test.cpp:241:27:241:32 | call to malloc | test.cpp:243:12:243:21 | string | This write may overflow $@ by 1 element. | test.cpp:243:16:243:21 | string | string |
| test.cpp:250:5:250:10 | call to memset | test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p | This write may overflow $@ by 1 element. | test.cpp:250:12:250:12 | p | p |
+| test.cpp:257:5:257:10 | call to memset | test.cpp:256:17:256:22 | call to malloc | test.cpp:257:12:257:12 | p | This write may overflow $@ by 32 elements. | test.cpp:257:12:257:12 | p | p |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp
index 8a7afb1a4a3..23e9c364836 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp
@@ -248,4 +248,12 @@ void* my_alloc(unsigned size);
void foo(unsigned size) {
int* p = (int*)my_alloc(size); // BAD
memset(p, 0, size + 1);
+}
+
+void test6(unsigned long n, char *p) {
+ while (unknown()) {
+ n++;
+ p = (char *)malloc(n);
+ memset(p, 0, n); // GOOD [FALSE POSITIVE]
+ }
}
\ No newline at end of file
From f20a69074a768ef7972160aa7833aec9d476a941 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 13:01:29 +0100
Subject: [PATCH 19/67] C++: Remove flow through ssa phi back-edges.
---
.../src/experimental/Likely Bugs/OverrunWriteProductFlow.ql | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
index 79a5497f46d..025f39bd4a7 100644
--- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
+++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
@@ -111,6 +111,10 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
predicate isBarrier2(DataFlow::Node node, FlowState2 state) { none() }
+ predicate isBarrierOut2(DataFlow::Node node) {
+ node = any(DataFlow::SsaPhiNode phi).getAnInput(true)
+ }
+
predicate isAdditionalFlowStep1(
DataFlow::Node node1, FlowState1 state1, DataFlow::Node node2, FlowState1 state2
) {
From de1f81a4b9c079747d8a33dc6b3358002a15c431 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 13:01:42 +0100
Subject: [PATCH 20/67] C++: Accept test changes.
---
.../Security/CWE/CWE-119/OverrunWriteProductFlow.expected | 2 --
.../experimental/query-tests/Security/CWE/CWE-119/test.cpp | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
index eee8b698399..00b15ea5fac 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected
@@ -426,7 +426,5 @@ subpaths
| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string |
| test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string |
| test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string |
-| test.cpp:232:3:232:8 | call to memset | test.cpp:228:43:228:48 | call to malloc | test.cpp:232:10:232:15 | buffer | This write may overflow $@ by 32 elements. | test.cpp:232:10:232:15 | buffer | buffer |
| test.cpp:243:5:243:10 | call to memset | test.cpp:241:27:241:32 | call to malloc | test.cpp:243:12:243:21 | string | This write may overflow $@ by 1 element. | test.cpp:243:16:243:21 | string | string |
| test.cpp:250:5:250:10 | call to memset | test.cpp:249:20:249:27 | call to my_alloc | test.cpp:250:12:250:12 | p | This write may overflow $@ by 1 element. | test.cpp:250:12:250:12 | p | p |
-| test.cpp:257:5:257:10 | call to memset | test.cpp:256:17:256:22 | call to malloc | test.cpp:257:12:257:12 | p | This write may overflow $@ by 32 elements. | test.cpp:257:12:257:12 | p | p |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp
index 23e9c364836..7c73a357c55 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/test.cpp
@@ -229,7 +229,7 @@ void repeated_alerts(unsigned size, unsigned offset) {
while(unknown()) {
++size;
}
- memset(buffer, 0, size); // BAD
+ memset(buffer, 0, size); // BAD [NOT DETECTED]
}
void set_string(string_t* p_str, char* buffer) {
@@ -254,6 +254,6 @@ void test6(unsigned long n, char *p) {
while (unknown()) {
n++;
p = (char *)malloc(n);
- memset(p, 0, n); // GOOD [FALSE POSITIVE]
+ memset(p, 0, n); // GOOD
}
}
\ No newline at end of file
From 3f01a2157bffdc3771809d42d94173bbaa6c9e75 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 13:41:34 +0100
Subject: [PATCH 21/67] Revert "C++: Speedup 'isSuccessor'."
This reverts commit 594da1a21aa7a6ae271d23ba25724b8ab3399bd4.
---
.../semmle/code/cpp/dataflow/ProductFlow.qll | 85 +------------------
1 file changed, 2 insertions(+), 83 deletions(-)
diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
index d21391bc93c..c0226c9fd66 100644
--- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
+++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
@@ -340,94 +340,13 @@ module ProductFlow {
fwdIsSuccessor(_, _, node1, node2)
}
- pragma[assume_small_delta]
- pragma[nomagic]
- private predicate fwdLocalPathStep1(Flow1::PathNode n) {
- fwdReachableInterprocEntry(n, _)
- or
- exists(Flow1::PathNode mid |
- fwdLocalPathStep1(mid) and
- localPathStep1(mid, n)
- )
- }
-
- pragma[assume_small_delta]
- pragma[nomagic]
- private predicate revLocalPathStep1(Flow1::PathNode n) {
- fwdLocalPathStep1(n) and
- (
- isSinkPair(n, _)
- or
- interprocEdgePair(n, _, _, _)
- or
- exists(Flow1::PathNode mid |
- revLocalPathStep1(mid) and
- localPathStep1(n, mid)
- )
- )
- }
-
- pragma[assume_small_delta]
- private predicate prunedLocalPathStep1(Flow1::PathNode n1, Flow1::PathNode n2) {
- revLocalPathStep1(n1) and
- revLocalPathStep1(n2) and
- localPathStep1(n1, n2)
- }
-
- pragma[nomagic]
- private predicate fwdLocalPathStep2(Flow2::PathNode n) {
- fwdReachableInterprocEntry(_, n)
- or
- exists(Flow2::PathNode mid |
- fwdLocalPathStep2(mid) and
- localPathStep2(mid, n)
- )
- }
-
- pragma[assume_small_delta]
- pragma[nomagic]
- private predicate revLocalPathStep2(Flow2::PathNode n) {
- fwdLocalPathStep2(n) and
- (
- isSinkPair(_, n)
- or
- interprocEdgePair(_, n, _, _)
- or
- exists(Flow2::PathNode mid |
- revLocalPathStep2(mid) and
- localPathStep2(n, mid)
- )
- )
- }
-
- pragma[assume_small_delta]
- private predicate prunedLocalPathStep2(Flow2::PathNode n1, Flow2::PathNode n2) {
- revLocalPathStep2(n1) and
- revLocalPathStep2(n2) and
- localPathStep2(n1, n2)
- }
-
- private predicate localPathStep1SuccPlus(Flow1::PathNode n1, Flow1::PathNode n2) =
- fastTC(prunedLocalPathStep1/2)(n1, n2)
-
- private predicate localPathStep2SuccPlus(Flow2::PathNode n1, Flow2::PathNode n2) =
- fastTC(prunedLocalPathStep2/2)(n1, n2)
-
- private predicate localPathStep1Tc(Flow1::PathNode n1, Flow1::PathNode n2) {
- localPathStep1SuccPlus(n1, n2) or n1 = n2
- }
-
- private predicate localPathStep2Tc(Flow2::PathNode n1, Flow2::PathNode n2) {
- localPathStep2SuccPlus(n1, n2) or n1 = n2
- }
-
private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
fwdReachableInterprocEntry(pred1, pred2) and
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
- localPathStep1Tc(pred1, mid1) and
- localPathStep2Tc(pred2, mid2)
+ localPathStep1*(pred1, mid1) and
+ localPathStep2*(pred2, mid2)
|
isSinkPair(mid1, mid2) and
succ1 = mid1 and
From 41df8cafe58e0847da2a21f048b8be66f142dc8d Mon Sep 17 00:00:00 2001
From: Philip Ginsbach
Date: Fri, 12 May 2023 15:20:50 +0100
Subject: [PATCH 22/67] 'Expr' is more appropriate than 'Id' now that
instantiation can be involved
---
.../ql-language-specification.rst | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst
index ac60ea55c1b..f8c3637b735 100644
--- a/docs/codeql/ql-language-reference/ql-language-specification.rst
+++ b/docs/codeql/ql-language-reference/ql-language-specification.rst
@@ -208,12 +208,12 @@ An import directive refers to a module identifier:
::
- import ::= annotations "import" importModuleId ("as" modulename)?
+ import ::= annotations "import" importModuleExpr ("as" modulename)?
qualId ::= simpleId | qualId "." simpleId
- importModuleId ::= qualId
- | importModuleId "::" simpleId
+ importModuleExpr ::= qualId
+ | importModuleExpr "::" simpleId
An import directive may optionally name the imported module using an ``as`` declaration. If a name is defined, then the import directive adds to the declared module environment of the current module a mapping from the name to the declaration of the imported module. Otherwise, the current module *directly imports* the imported module.
@@ -280,9 +280,9 @@ With the exception of class domain types and character types (which cannot be re
::
- type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
+ type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
- moduleId ::= simpleId | moduleId "::" simpleId
+ moduleExpr ::= simpleId | moduleExpr "::" simpleId
A type reference is resolved to a type as follows:
@@ -597,7 +597,7 @@ Identifiers are used in following syntactic constructs:
modulename ::= simpleId
classname ::= upperId
dbasetype ::= atLowerId
- predicateRef ::= (moduleId "::")? literalId
+ predicateRef ::= (moduleExpr "::")? literalId
predicateName ::= lowerId
varname ::= lowerId
literalId ::= lowerId | atLowerId
@@ -1615,7 +1615,7 @@ Aliases define new names for existing QL entities.
alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";"
| qldoc? annotations "class" classname "=" type ";"
- | qldoc? annotations "module" modulename "=" moduleId ";"
+ | qldoc? annotations "module" modulename "=" moduleExpr ";"
An alias introduces a binding from the new name to the entity referred to by the right-hand side in the current module's declared predicate, type, or module environment respectively.
@@ -2068,12 +2068,12 @@ The complete grammar for QL is as follows:
moduleBody ::= (import | predicate | class | module | alias | select)*
- import ::= annotations "import" importModuleId ("as" modulename)?
+ import ::= annotations "import" importModuleExpr ("as" modulename)?
qualId ::= simpleId | qualId "." simpleId
- importModuleId ::= qualId
- | importModuleId "::" simpleId
+ importModuleExpr ::= qualId
+ | importModuleExpr "::" simpleId
select ::= ("from" var_decls)? ("where" formula)? "select" as_exprs ("order" "by" orderbys)?
@@ -2120,15 +2120,15 @@ The complete grammar for QL is as follows:
field ::= qldoc? annotations var_decl ";"
- moduleId ::= simpleId | moduleId "::" simpleId
+ moduleExpr ::= simpleId | moduleExpr "::" simpleId
- type ::= (moduleId "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
+ type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
exprs ::= expr ("," expr)*
alias ::= qldoc? annotations "predicate" literalId "=" predicateRef "/" int ";"
| qldoc? annotations "class" classname "=" type ";"
- | qldoc? annotations "module" modulename "=" moduleId ";"
+ | qldoc? annotations "module" modulename "=" moduleExpr ";"
var_decls ::= (var_decl ("," var_decl)*)?
@@ -2249,7 +2249,7 @@ The complete grammar for QL is as follows:
dbasetype ::= atLowerId
- predicateRef ::= (moduleId "::")? literalId
+ predicateRef ::= (moduleExpr "::")? literalId
predicateName ::= lowerId
From c5be3fb6c04373566b61c40af995b8b1c8457c17 Mon Sep 17 00:00:00 2001
From: Philip Ginsbach
Date: Fri, 12 May 2023 09:38:47 +0100
Subject: [PATCH 23/67] add missing syntax for parameterised module declaration
---
.../ql-language-specification.rst | 34 ++++++++++++++-----
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst
index f8c3637b735..744a21ceaf1 100644
--- a/docs/codeql/ql-language-reference/ql-language-specification.rst
+++ b/docs/codeql/ql-language-reference/ql-language-specification.rst
@@ -176,7 +176,11 @@ A QL module definition has the following syntax:
::
- module ::= annotation* "module" modulename "{" moduleBody "}"
+ module ::= annotation* "module" modulename parameters? implements? "{" moduleBody "}"
+
+ parameters ::= "<" signatureExpr simpleId ("," signatureExpr simpleId)* ">"
+
+ implements ::= "implements" moduleSignatureExpr ("," moduleSignatureExpr)*
moduleBody ::= (import | predicate | class | module | alias | select)*
@@ -212,8 +216,11 @@ An import directive refers to a module identifier:
qualId ::= simpleId | qualId "." simpleId
- importModuleExpr ::= qualId
- | importModuleExpr "::" simpleId
+ importModuleExpr ::= qualId | importModuleExpr "::" simpleId arguments?
+
+ arguments ::= "<" argument ("," argument)* ">"
+
+ argument ::= moduleExpr | type | predicateRef "/" int
An import directive may optionally name the imported module using an ``as`` declaration. If a name is defined, then the import directive adds to the declared module environment of the current module a mapping from the name to the declaration of the imported module. Otherwise, the current module *directly imports* the imported module.
@@ -282,7 +289,7 @@ With the exception of class domain types and character types (which cannot be re
type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
- moduleExpr ::= simpleId | moduleExpr "::" simpleId
+ moduleExpr ::= simpleId arguments? | moduleExpr "::" simpleId arguments?
A type reference is resolved to a type as follows:
@@ -2064,7 +2071,11 @@ The complete grammar for QL is as follows:
ql ::= qldoc? moduleBody
- module ::= annotation* "module" modulename "{" moduleBody "}"
+ module ::= annotation* "module" modulename parameters? implements? "{" moduleBody "}"
+
+ parameters ::= "<" signatureExpr simpleId ("," signatureExpr simpleId)* ">"
+
+ implements ::= "implements" moduleSignatureExpr ("," moduleSignatureExpr)*
moduleBody ::= (import | predicate | class | module | alias | select)*
@@ -2072,8 +2083,11 @@ The complete grammar for QL is as follows:
qualId ::= simpleId | qualId "." simpleId
- importModuleExpr ::= qualId
- | importModuleExpr "::" simpleId
+ importModuleExpr ::= qualId | importModuleExpr "::" simpleId arguments?
+
+ arguments ::= "<" argument ("," argument)* ">"
+
+ argument ::= moduleExpr | type | predicateRef "/" int
select ::= ("from" var_decls)? ("where" formula)? "select" as_exprs ("order" "by" orderbys)?
@@ -2120,7 +2134,11 @@ The complete grammar for QL is as follows:
field ::= qldoc? annotations var_decl ";"
- moduleExpr ::= simpleId | moduleExpr "::" simpleId
+ moduleExpr ::= simpleId arguments? | moduleExpr "::" simpleId arguments?
+
+ moduleSignatureExpr ::= (moduleExpr "::")? upperId arguments?
+
+ signatureExpr : (moduleExpr "::")? simpleId ("/" Integer | arguments)?;
type ::= (moduleExpr "::")? classname | dbasetype | "boolean" | "date" | "float" | "int" | "string"
From e1cc7dcdc162060d609828649040c9c8f84d36e5 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Fri, 12 May 2023 14:14:13 +0100
Subject: [PATCH 24/67] C++: Tweak join orders.
---
.../semmle/code/cpp/dataflow/ProductFlow.qll | 41 +++++++++++++++----
1 file changed, 32 insertions(+), 9 deletions(-)
diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
index c0226c9fd66..6977017dcbc 100644
--- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
+++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
@@ -340,19 +340,42 @@ module ProductFlow {
fwdIsSuccessor(_, _, node1, node2)
}
+ pragma[nomagic]
+ private predicate fwdIsSuccessorExit(
+ Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2
+ ) {
+ isSinkPair(mid1, mid2) and
+ succ1 = mid1 and
+ succ2 = mid2
+ or
+ interprocEdgePair(mid1, mid2, succ1, succ2)
+ }
+
+ private predicate fwdIsSuccessor1(
+ Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
+ Flow1::PathNode succ1, Flow2::PathNode succ2
+ ) {
+ fwdReachableInterprocEntry(pred1, pred2) and
+ localPathStep1*(pred1, mid1) and
+ fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
+ }
+
+ private predicate fwdIsSuccessor2(
+ Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
+ Flow1::PathNode succ1, Flow2::PathNode succ2
+ ) {
+ fwdReachableInterprocEntry(pred1, pred2) and
+ localPathStep2*(pred2, mid2) and
+ fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
+ }
+
+ pragma[assume_small_delta]
private predicate fwdIsSuccessor(
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
) {
- fwdReachableInterprocEntry(pred1, pred2) and
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
- localPathStep1*(pred1, mid1) and
- localPathStep2*(pred2, mid2)
- |
- isSinkPair(mid1, mid2) and
- succ1 = mid1 and
- succ2 = mid2
- or
- interprocEdgePair(mid1, mid2, succ1, succ2)
+ fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and
+ fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2)
)
}
From a7712b608a9b052df9ff3c3f2d6ddc8a2040d84e Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 15 May 2023 11:14:06 +0100
Subject: [PATCH 25/67] C++: Add more comments.
---
.../Likely Bugs/OverrunWriteProductFlow.ql | 28 +++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
index e35c48c9d9b..6d5acfcfa56 100644
--- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
+++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
@@ -149,10 +149,30 @@ module ValidState {
* ```
*/
private predicate validStateImpl(PathNode n, int value) {
+ // If the dataflow node depends recursively on itself we restrict the range.
(inLoop(n) implies value = [-2 .. 2]) and
(
+ // For the dataflow source we have an allocation such as `malloc(size + k)`,
+ // and the value of the flow-state is then `k`.
hasSize(_, n.getNode(), value)
or
+ // For a dataflow sink any `value` that is strictly smaller than the delta
+ // needs to be a valid flow-state. That is, for a snippet like:
+ // ```
+ // p = new char[size];
+ // memset(p, 0, size + 2);
+ // ```
+ // the valid flow-states at the `memset` must include `0` since the flow-state
+ // at the source is `0`. Similarly, for an example such as:
+ // ```
+ // p = new char[size + 1];
+ // memset(p, 0, size + 2);
+ // ```
+ // the flow-state at the `memset` must include `1` since `1` is the flow-state
+ // after the source.
+ //
+ // So we find a valid flow-state at the sink's predecessor, and use the definition
+ // of our sink predicate to compute the valid flow-states at the sink.
exists(int delta, PathNode n0 |
n0.getASuccessor() = n and
validStateImpl(n0, value) and
@@ -160,6 +180,14 @@ module ValidState {
delta > value
)
or
+ // For a non-source and non-sink node there is two cases to consider.
+ // 1. A node where we have to update the flow-state, or
+ // 2. A node that doesn't update the flow-state.
+ //
+ // For case 1, we compute the new flow-state by adding the constant operand of the
+ // `AddInstruction` to the flow-state of any predecessor node.
+ // For case 2 we simply propagate the valid flow-states from the predecessor node to
+ // the next one.
exists(PathNode n0, DataFlow::Node node, int value0 |
n0.getASuccessor() = n and
validStateImpl(n0, value0) and
From cfcd26cf0db67e8d957508708fd015b132678b9f Mon Sep 17 00:00:00 2001
From: Paolo Tranquilli
Date: Mon, 15 May 2023 12:41:30 +0200
Subject: [PATCH 26/67] Swift: support markdown TSP diagnostics
---
.../unsupported-os/diagnostics.expected | 8 +++----
swift/logging/SwiftDiagnostics.cpp | 3 ++-
swift/logging/SwiftDiagnostics.h | 22 +++++++++++++++----
.../IncompatibleOs.cpp | 17 ++++++++------
.../CustomizingBuildDiagnostics.h | 2 +-
swift/xcode-autobuilder/XcodeBuildRunner.cpp | 3 ++-
swift/xcode-autobuilder/xcode-autobuilder.cpp | 9 +++++---
7 files changed, 42 insertions(+), 22 deletions(-)
diff --git a/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected b/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected
index 6b5e3b71bbc..2d3c70daab3 100644
--- a/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected
+++ b/swift/integration-tests/linux-only/autobuilder/unsupported-os/diagnostics.expected
@@ -1,15 +1,13 @@
{
"helpLinks": [
- "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on",
- "https://docs.github.com/en/enterprise-server/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning",
- "https://docs.github.com/en/enterprise-server/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language"
+ ""
],
- "plaintextMessage": "CodeQL Swift analysis is currently only officially supported on macOS.\n\nChange the action runner to a macOS one. Analysis on Linux might work, but requires setting up a custom build command.",
+ "markdownMessage": "Currently, `autobuild` for Swift analysis is only supported on macOS.\n\n[Change the Actions runner][1] to run on macOS.\n\nYou may be able to run analysis on Linux by setting up a [manual build command][2].\n\n[1]: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on\n[2]: https://docs.github.com/en/enterprise-server/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language",
"severity": "error",
"source": {
"extractorName": "swift",
"id": "swift/autobuilder/incompatible-os",
- "name": "Incompatible operating system for autobuild (expected macOS)"
+ "name": "Incompatible operating system (expected macOS)"
},
"visibility": {
"cliSummaryTable": true,
diff --git a/swift/logging/SwiftDiagnostics.cpp b/swift/logging/SwiftDiagnostics.cpp
index 4c490486a26..690d03cbbaf 100644
--- a/swift/logging/SwiftDiagnostics.cpp
+++ b/swift/logging/SwiftDiagnostics.cpp
@@ -25,7 +25,8 @@ nlohmann::json SwiftDiagnostic::json(const std::chrono::system_clock::time_point
}},
{"severity", "error"},
{"helpLinks", std::vector(absl::StrSplit(helpLinks, ' '))},
- {"plaintextMessage", absl::StrCat(message, ".\n\n", action, ".")},
+ {format == Format::markdown ? "markdownMessage" : "plaintextMessage",
+ absl::StrCat(message, ".\n\n", action)},
{"timestamp", fmt::format("{:%FT%T%z}", timestamp)},
};
if (location) {
diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h
index 6e539b0330b..34854c6ab65 100644
--- a/swift/logging/SwiftDiagnostics.h
+++ b/swift/logging/SwiftDiagnostics.h
@@ -33,6 +33,11 @@ struct SwiftDiagnosticsLocation {
// These are internally stored into a map on id's. A specific error log can use binlog's category
// as id, which will then be used to recover the diagnostic source while dumping.
struct SwiftDiagnostic {
+ enum class Format {
+ plaintext,
+ markdown,
+ };
+
enum class Visibility : unsigned char {
none = 0b000,
statusPage = 0b001,
@@ -44,6 +49,7 @@ struct SwiftDiagnostic {
std::string_view id;
std::string_view name;
static constexpr std::string_view extractorName = "swift";
+ Format format;
std::string_view action;
// space separated if more than 1. Not a vector to allow constexpr
// TODO(C++20) with vector going constexpr this can be turned to `std::vector`
@@ -54,15 +60,20 @@ struct SwiftDiagnostic {
std::optional location{};
+ // notice help links are really required only for plaintext messages, otherwise they should be
+ // directly embedded in the markdown message
constexpr SwiftDiagnostic(std::string_view id,
std::string_view name,
+ Format format,
std::string_view action = "",
std::string_view helpLinks = "",
Visibility visibility = Visibility::all)
- : id{id}, name{name}, action{action}, helpLinks{helpLinks}, visibility{visibility} {}
-
- constexpr SwiftDiagnostic(std::string_view id, std::string_view name, Visibility visibility)
- : SwiftDiagnostic(id, name, "", "", visibility) {}
+ : id{id},
+ name{name},
+ format{format},
+ action{action},
+ helpLinks{helpLinks},
+ visibility{visibility} {}
// create a JSON diagnostics for this source with the given timestamp and message to out
// A plaintextMessage is used that includes both the message and the action to take. Dots are
@@ -103,6 +114,9 @@ inline constexpr SwiftDiagnostic::Visibility operator&(SwiftDiagnostic::Visibili
constexpr SwiftDiagnostic internalError{
"internal-error",
"Internal error",
+ SwiftDiagnostic::Format::plaintext,
+ /* action=*/"",
+ /* helpLinks=*/"",
SwiftDiagnostic::Visibility::telemetry,
};
} // namespace codeql
diff --git a/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp b/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp
index 6dd010036cf..c949c360c26 100644
--- a/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp
+++ b/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp
@@ -9,13 +9,16 @@
const std::string_view codeql::programName = "autobuilder";
constexpr codeql::SwiftDiagnostic incompatibleOs{
- "incompatible-os", "Incompatible operating system for autobuild (expected macOS)",
- "Change the action runner to a macOS one. Analysis on Linux might work, but requires setting "
- "up a custom build command",
+ "incompatible-os", "Incompatible operating system (expected macOS)",
+ codeql::SwiftDiagnostic::Format::markdown,
+ "[Change the Actions runner][1] to run on macOS.\n"
+ "\n"
+ "You may be able to run analysis on Linux by setting up a [manual build command][2].\n"
+ "\n"
+ "[1]: "
"https://docs.github.com/en/actions/using-workflows/"
- "workflow-syntax-for-github-actions#jobsjob_idruns-on "
- "https://docs.github.com/en/enterprise-server/code-security/code-scanning/"
- "automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning "
+ "workflow-syntax-for-github-actions#jobsjob_idruns-on\n"
+ "[2]: "
"https://docs.github.com/en/enterprise-server/code-security/code-scanning/"
"automatically-scanning-your-code-for-vulnerabilities-and-errors/"
"configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-"
@@ -28,6 +31,6 @@ static codeql::Logger& logger() {
int main() {
DIAGNOSE_ERROR(incompatibleOs,
- "CodeQL Swift analysis is currently only officially supported on macOS");
+ "Currently, `autobuild` for Swift analysis is only supported on macOS");
return 1;
}
diff --git a/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h b/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h
index d8c68136e2f..c1d7809054c 100644
--- a/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h
+++ b/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h
@@ -1,7 +1,7 @@
#include
namespace codeql {
-constexpr std::string_view customizingBuildAction = "Set up a manual build command";
+constexpr std::string_view customizingBuildAction = "Set up a manual build command.";
constexpr std::string_view customizingBuildHelpLinks =
"https://docs.github.com/en/enterprise-server/code-security/code-scanning/"
"automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning "
diff --git a/swift/xcode-autobuilder/XcodeBuildRunner.cpp b/swift/xcode-autobuilder/XcodeBuildRunner.cpp
index 163a639db00..aedd1ada0b7 100644
--- a/swift/xcode-autobuilder/XcodeBuildRunner.cpp
+++ b/swift/xcode-autobuilder/XcodeBuildRunner.cpp
@@ -9,7 +9,8 @@
#include "swift/xcode-autobuilder/CustomizingBuildDiagnostics.h"
constexpr codeql::SwiftDiagnostic buildCommandFailed{
- "build-command-failed", "Detected build command failed", codeql::customizingBuildAction,
+ "build-command-failed", "Detected build command failed",
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
codeql::customizingBuildHelpLinks};
static codeql::Logger& logger() {
diff --git a/swift/xcode-autobuilder/xcode-autobuilder.cpp b/swift/xcode-autobuilder/xcode-autobuilder.cpp
index 5a00c885880..54973fe0114 100644
--- a/swift/xcode-autobuilder/xcode-autobuilder.cpp
+++ b/swift/xcode-autobuilder/xcode-autobuilder.cpp
@@ -13,16 +13,19 @@ static const char* unitTest = "com.apple.product-type.bundle.unit-test";
const std::string_view codeql::programName = "autobuilder";
constexpr codeql::SwiftDiagnostic noProjectFound{
- "no-project-found", "No Xcode project or workspace detected", codeql::customizingBuildAction,
+ "no-project-found", "No Xcode project or workspace detected",
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
codeql::customizingBuildHelpLinks};
constexpr codeql::SwiftDiagnostic noSwiftTarget{
- "no-swift-target", "No Swift compilation target found", codeql::customizingBuildAction,
+ "no-swift-target", "No Swift compilation target found",
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
codeql::customizingBuildHelpLinks};
constexpr codeql::SwiftDiagnostic spmNotSupported{
"spm-not-supported", "Swift Package Manager build unsupported by autobuild",
- codeql::customizingBuildAction, codeql::customizingBuildHelpLinks};
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
+ codeql::customizingBuildHelpLinks};
static codeql::Logger& logger() {
static codeql::Logger ret{"main"};
From 10d084fbbf42ecc7565c29925608f1e42cae1f86 Mon Sep 17 00:00:00 2001
From: Paolo Tranquilli
Date: Mon, 15 May 2023 13:47:00 +0200
Subject: [PATCH 27/67] Swift: update comment
---
swift/logging/SwiftDiagnostics.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h
index 34854c6ab65..ab227aae873 100644
--- a/swift/logging/SwiftDiagnostics.h
+++ b/swift/logging/SwiftDiagnostics.h
@@ -75,10 +75,10 @@ struct SwiftDiagnostic {
helpLinks{helpLinks},
visibility{visibility} {}
- // create a JSON diagnostics for this source with the given timestamp and message to out
- // A plaintextMessage is used that includes both the message and the action to take. Dots are
- // appended to both. The id is used to construct the source id in the form
- // `swift//`
+ // create a JSON diagnostics for this source with the given `timestamp` and `message`
+ // Depending on format, either a plaintextMessage or markdownMessage is used that includes both
+ // the message and the action to take. A dot '.' is appended to `message`. The id is used to
+ // construct the source id in the form `swift//`
nlohmann::json json(const std::chrono::system_clock::time_point& timestamp,
std::string_view message) const;
From f31709fb29764a83f5801d68543c2ab886b45751 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 15 May 2023 13:36:29 +0100
Subject: [PATCH 28/67] C++: Make comment more clear.
---
.../Likely Bugs/OverrunWriteProductFlow.ql | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
index 6d5acfcfa56..38682ac6a01 100644
--- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
+++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
@@ -159,17 +159,12 @@ module ValidState {
// For a dataflow sink any `value` that is strictly smaller than the delta
// needs to be a valid flow-state. That is, for a snippet like:
// ```
- // p = new char[size];
+ // p = b ? new char[size] : new char[size + 1];
// memset(p, 0, size + 2);
// ```
- // the valid flow-states at the `memset` must include `0` since the flow-state
- // at the source is `0`. Similarly, for an example such as:
- // ```
- // p = new char[size + 1];
- // memset(p, 0, size + 2);
- // ```
- // the flow-state at the `memset` must include `1` since `1` is the flow-state
- // after the source.
+ // the valid flow-states at the `memset` must include set set `{0, 1}` since the
+ // flow-state at `new char[size]` is `0`, and the flow-state at `new char[size + 1]`
+ // is `1`.
//
// So we find a valid flow-state at the sink's predecessor, and use the definition
// of our sink predicate to compute the valid flow-states at the sink.
From dba951111a2d75b83a04302ae209a162b840c7fd Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 12 May 2023 11:31:27 +0100
Subject: [PATCH 29/67] Swift: Add more sensitive data test cases.
---
.../CWE-311/CleartextTransmission.expected | 42 ++++++++++++-------
.../Security/CWE-311/SensitiveExprs.expected | 17 +++++---
.../Security/CWE-311/testSend.swift | 14 ++++++-
3 files changed, 50 insertions(+), 23 deletions(-)
diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
index ed65adcc9b6..459d3cba917 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
@@ -7,11 +7,11 @@ edges
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) |
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:33:14:33:32 | call to Data.init(_:) |
| testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data |
-| testSend.swift:45:13:45:13 | password | testSend.swift:52:27:52:27 | str1 |
-| testSend.swift:46:13:46:13 | password | testSend.swift:53:27:53:27 | str2 |
-| testSend.swift:47:13:47:25 | call to pad(_:) | testSend.swift:54:27:54:27 | str3 |
-| testSend.swift:47:17:47:17 | password | testSend.swift:41:10:41:18 | data |
-| testSend.swift:47:17:47:17 | password | testSend.swift:47:13:47:25 | call to pad(_:) |
+| testSend.swift:52:13:52:13 | password | testSend.swift:59:27:59:27 | str1 |
+| testSend.swift:53:13:53:13 | password | testSend.swift:60:27:60:27 | str2 |
+| testSend.swift:54:13:54:25 | call to pad(_:) | testSend.swift:61:27:61:27 | str3 |
+| testSend.swift:54:17:54:17 | password | testSend.swift:41:10:41:18 | data |
+| testSend.swift:54:17:54:17 | password | testSend.swift:54:13:54:25 | call to pad(_:) |
| testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... |
| testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... |
nodes
@@ -29,13 +29,18 @@ nodes
| testSend.swift:37:19:37:19 | data2 | semmle.label | data2 |
| testSend.swift:41:10:41:18 | data | semmle.label | data |
| testSend.swift:41:45:41:45 | data | semmle.label | data |
-| testSend.swift:45:13:45:13 | password | semmle.label | password |
-| testSend.swift:46:13:46:13 | password | semmle.label | password |
-| testSend.swift:47:13:47:25 | call to pad(_:) | semmle.label | call to pad(_:) |
-| testSend.swift:47:17:47:17 | password | semmle.label | password |
-| testSend.swift:52:27:52:27 | str1 | semmle.label | str1 |
-| testSend.swift:53:27:53:27 | str2 | semmle.label | str2 |
-| testSend.swift:54:27:54:27 | str3 | semmle.label | str3 |
+| testSend.swift:52:13:52:13 | password | semmle.label | password |
+| testSend.swift:53:13:53:13 | password | semmle.label | password |
+| testSend.swift:54:13:54:25 | call to pad(_:) | semmle.label | call to pad(_:) |
+| testSend.swift:54:17:54:17 | password | semmle.label | password |
+| testSend.swift:59:27:59:27 | str1 | semmle.label | str1 |
+| testSend.swift:60:27:60:27 | str2 | semmle.label | str2 |
+| testSend.swift:61:27:61:27 | str3 | semmle.label | str3 |
+| testSend.swift:65:27:65:27 | license_key | semmle.label | license_key |
+| testSend.swift:66:27:66:30 | .mobileNumber | semmle.label | .mobileNumber |
+| testSend.swift:67:27:67:30 | .mobileUrl | semmle.label | .mobileUrl |
+| testSend.swift:68:27:68:30 | .mobilePlayer | semmle.label | .mobilePlayer |
+| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | semmle.label | .passwordFeatureEnabled |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| testURL.swift:13:54:13:54 | passwd | semmle.label | passwd |
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
@@ -43,16 +48,21 @@ nodes
| testURL.swift:20:22:20:22 | passwd | semmle.label | passwd |
subpaths
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | testSend.swift:33:14:33:32 | call to Data.init(_:) |
-| testSend.swift:47:17:47:17 | password | testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data | testSend.swift:47:13:47:25 | call to pad(_:) |
+| testSend.swift:54:17:54:17 | password | testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data | testSend.swift:54:13:54:25 | call to pad(_:) |
#select
| testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | testAlamofire.swift:150:45:150:45 | password | testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:150:45:150:45 | password | password |
| testAlamofire.swift:152:19:152:51 | ... .+(_:_:) ... | testAlamofire.swift:152:51:152:51 | password | testAlamofire.swift:152:19:152:51 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:152:51:152:51 | password | password |
| testAlamofire.swift:154:14:154:46 | ... .+(_:_:) ... | testAlamofire.swift:154:38:154:38 | email | testAlamofire.swift:154:14:154:46 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:154:38:154:38 | email | email |
| testSend.swift:29:19:29:19 | passwordPlain | testSend.swift:29:19:29:19 | passwordPlain | testSend.swift:29:19:29:19 | passwordPlain | This operation transmits 'passwordPlain', which may contain unencrypted sensitive data from $@. | testSend.swift:29:19:29:19 | passwordPlain | passwordPlain |
| testSend.swift:37:19:37:19 | data2 | testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:37:19:37:19 | data2 | This operation transmits 'data2', which may contain unencrypted sensitive data from $@. | testSend.swift:33:19:33:19 | passwordPlain | passwordPlain |
-| testSend.swift:52:27:52:27 | str1 | testSend.swift:45:13:45:13 | password | testSend.swift:52:27:52:27 | str1 | This operation transmits 'str1', which may contain unencrypted sensitive data from $@. | testSend.swift:45:13:45:13 | password | password |
-| testSend.swift:53:27:53:27 | str2 | testSend.swift:46:13:46:13 | password | testSend.swift:53:27:53:27 | str2 | This operation transmits 'str2', which may contain unencrypted sensitive data from $@. | testSend.swift:46:13:46:13 | password | password |
-| testSend.swift:54:27:54:27 | str3 | testSend.swift:47:17:47:17 | password | testSend.swift:54:27:54:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@. | testSend.swift:47:17:47:17 | password | password |
+| testSend.swift:59:27:59:27 | str1 | testSend.swift:52:13:52:13 | password | testSend.swift:59:27:59:27 | str1 | This operation transmits 'str1', which may contain unencrypted sensitive data from $@. | testSend.swift:52:13:52:13 | password | password |
+| testSend.swift:60:27:60:27 | str2 | testSend.swift:53:13:53:13 | password | testSend.swift:60:27:60:27 | str2 | This operation transmits 'str2', which may contain unencrypted sensitive data from $@. | testSend.swift:53:13:53:13 | password | password |
+| testSend.swift:61:27:61:27 | str3 | testSend.swift:54:17:54:17 | password | testSend.swift:61:27:61:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@. | testSend.swift:54:17:54:17 | password | password |
+| testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | testSend.swift:65:27:65:27 | license_key | license_key |
+| testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | This operation transmits '.mobileNumber', which may contain unencrypted sensitive data from $@. | testSend.swift:66:27:66:30 | .mobileNumber | .mobileNumber |
+| testSend.swift:67:27:67:30 | .mobileUrl | testSend.swift:67:27:67:30 | .mobileUrl | testSend.swift:67:27:67:30 | .mobileUrl | This operation transmits '.mobileUrl', which may contain unencrypted sensitive data from $@. | testSend.swift:67:27:67:30 | .mobileUrl | .mobileUrl |
+| testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | This operation transmits '.mobilePlayer', which may contain unencrypted sensitive data from $@. | testSend.swift:68:27:68:30 | .mobilePlayer | .mobilePlayer |
+| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | This operation transmits '.passwordFeatureEnabled', which may contain unencrypted sensitive data from $@. | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | .passwordFeatureEnabled |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:13:54:13:54 | passwd | passwd |
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:16:55:16:55 | credit_card_no | credit_card_no |
| testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | This operation transmits 'passwd', which may contain unencrypted sensitive data from $@. | testURL.swift:20:22:20:22 | passwd | passwd |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
index ef794d4004a..9e06f8f7314 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
@@ -120,12 +120,17 @@
| testRealm.swift:73:15:73:15 | myPassword | label:myPassword, type:credential |
| testSend.swift:29:19:29:19 | passwordPlain | label:passwordPlain, type:credential |
| testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential |
-| testSend.swift:45:13:45:13 | password | label:password, type:credential |
-| testSend.swift:46:13:46:13 | password | label:password, type:credential |
-| testSend.swift:47:17:47:17 | password | label:password, type:credential |
-| testSend.swift:48:23:48:23 | password | label:password, type:credential |
-| testSend.swift:49:27:49:27 | password | label:password, type:credential |
-| testSend.swift:50:27:50:27 | password | label:password, type:credential |
+| testSend.swift:52:13:52:13 | password | label:password, type:credential |
+| testSend.swift:53:13:53:13 | password | label:password, type:credential |
+| testSend.swift:54:17:54:17 | password | label:password, type:credential |
+| testSend.swift:55:23:55:23 | password | label:password, type:credential |
+| testSend.swift:56:27:56:27 | password | label:password, type:credential |
+| testSend.swift:57:27:57:27 | password | label:password, type:credential |
+| testSend.swift:65:27:65:27 | license_key | label:license_key, type:credential |
+| testSend.swift:66:27:66:30 | .mobileNumber | label:mobileNumber, type:private information |
+| testSend.swift:67:27:67:30 | .mobileUrl | label:mobileUrl, type:private information |
+| testSend.swift:68:27:68:30 | .mobilePlayer | label:mobilePlayer, type:private information |
+| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | label:passwordFeatureEnabled, type:credential |
| testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential |
| testURL.swift:16:55:16:55 | credit_card_no | label:credit_card_no, type:private information |
| testURL.swift:20:22:20:22 | passwd | label:passwd, type:credential |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
index aaf2e3487f2..6ba78ede6e7 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
@@ -41,7 +41,14 @@ func test1(passwordPlain : String, passwordHash : String) {
func pad(_ data: String) -> String { return data }
func aes_crypt(_ data: String) -> String { return data }
-func test2(password : String, connection : NWConnection) {
+struct MyStruct {
+ var mobileNumber: String
+ var mobileUrl: String
+ var mobilePlayer: String
+ var passwordFeatureEnabled: Bool
+}
+
+func test2(password : String, license_key: String, ms: MyStruct, connection : NWConnection) {
let str1 = password
let str2 = password + " "
let str3 = pad(password)
@@ -55,4 +62,9 @@ func test2(password : String, connection : NWConnection) {
connection.send(content: str4, completion: .idempotent) // GOOD (encrypted)
connection.send(content: str5, completion: .idempotent) // GOOD (encrypted)
connection.send(content: str6, completion: .idempotent) // GOOD (encrypted)
+ connection.send(content: license_key, completion: .idempotent) // BAD
+ connection.send(content: ms.mobileNumber, completion: .idempotent) // BAD
+ connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
+ connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
+ connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
}
From e59d7e03456b1b0b8d3bc57098b1d7032224cd59 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 12 May 2023 11:37:38 +0100
Subject: [PATCH 30/67] Swift: Remove assumption that 'username' is not
sensitive (in the tests).
---
swift/ql/test/query-tests/Security/CWE-311/testRealm.swift | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift
index 8bcf9ce83f5..94bc9e07800 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift
@@ -30,11 +30,11 @@ class MyRealmSwiftObject : RealmSwiftObject {
class MyRealmSwiftObject2 : Object {
override init() { password = "" }
- var username: String?
+ var harmless: String?
var password: String?
}
-func test1(realm : Realm, myUsername: String, myPassword : String, myHashedPassword : String) {
+func test1(realm : Realm, myHarmless: String, myPassword : String, myHashedPassword : String) {
// add objects (within a transaction) ...
let a = MyRealmSwiftObject()
@@ -69,7 +69,7 @@ func test1(realm : Realm, myUsername: String, myPassword : String, myHashedPassw
// MyRealmSwiftObject2...
let h = MyRealmSwiftObject2()
- h.username = myUsername // GOOD (not sensitive)
+ h.harmless = myHarmless // GOOD (not sensitive)
h.password = myPassword // BAD
realm.add(h)
}
From f1c124a3da3ffd8e1d91cae95fd6d779b7481c9d Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 15 May 2023 14:01:17 +0100
Subject: [PATCH 31/67] C++: Share more code between 'ValidState' and
'StringSizeConfig'.
---
.../Likely Bugs/OverrunWriteProductFlow.ql | 39 ++++++++++++-------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
index 38682ac6a01..c6941ccc15c 100644
--- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
+++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
@@ -183,19 +183,18 @@ module ValidState {
// `AddInstruction` to the flow-state of any predecessor node.
// For case 2 we simply propagate the valid flow-states from the predecessor node to
// the next one.
- exists(PathNode n0, DataFlow::Node node, int value0 |
+ exists(PathNode n0, DataFlow::Node node0, DataFlow::Node node, int value0 |
n0.getASuccessor() = n and
validStateImpl(n0, value0) and
- node = n.getNode()
+ node = n.getNode() and
+ node0 = n0.getNode()
|
- exists(AddInstruction add, Operand op1, Operand op2, int delta |
- add = node.asInstruction() and
- add.hasOperands(op1, op2) and
- value0 = value + delta and
- semBounded(getSemanticExpr([op1, op2].getDef()), any(SemZeroBound zero), delta, true, _)
+ exists(int delta |
+ isAdditionalFlowStep2(node0, node, delta) and
+ value0 = value + delta
)
or
- not node.asInstruction() instanceof AddInstruction and
+ not isAdditionalFlowStep2(node0, node, _) and
value = value0
)
)
@@ -208,6 +207,20 @@ module ValidState {
import ValidState
+/**
+ * Holds if `node2` is a dataflow node that represents an addition of two operands `op1`
+ * and `op2` such that:
+ * 1. `node1` is the dataflow node that represents `op1`, and
+ * 2. the value of `op2` can be upper bounded by `delta.`
+ */
+predicate isAdditionalFlowStep2(DataFlow::Node node1, DataFlow::Node node2, int delta) {
+ exists(AddInstruction add, Operand op |
+ add.hasOperands(node1.asOperand(), op) and
+ semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
+ node2.asInstruction() = add
+ )
+}
+
module StringSizeConfig implements ProductFlow::StateConfigSig {
class FlowState1 = Unit;
@@ -251,13 +264,9 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
DataFlow::Node node1, FlowState2 state1, DataFlow::Node node2, FlowState2 state2
) {
validState(node2, state2) and
- exists(AddInstruction add, Operand op, int delta, int s1, int s2 |
- state1 = s1 and
- state2 = s2 and
- add.hasOperands(node1.asOperand(), op) and
- semBounded(getSemanticExpr(op.getDef()), any(SemZeroBound zero), delta, true, _) and
- node2.asInstruction() = add and
- s1 = s2 + delta
+ exists(int delta |
+ isAdditionalFlowStep2(node1, node2, delta) and
+ state1 = state2 + delta
)
}
}
From 650e9e1088ac400888ef98c70980ba215640e532 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Mon, 15 May 2023 14:05:41 +0100
Subject: [PATCH 32/67] C++: Fix Code Scanning error.
---
cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
index c6941ccc15c..2485048a84a 100644
--- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
+++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql
@@ -162,7 +162,7 @@ module ValidState {
// p = b ? new char[size] : new char[size + 1];
// memset(p, 0, size + 2);
// ```
- // the valid flow-states at the `memset` must include set set `{0, 1}` since the
+ // the valid flow-states at the `memset` must include the set `{0, 1}` since the
// flow-state at `new char[size]` is `0`, and the flow-state at `new char[size + 1]`
// is `1`.
//
From 27c8eb301e0a1876cb6803954d52bd0b22a6e3cb Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 15 May 2023 14:08:22 +0100
Subject: [PATCH 33/67] Swift: Fix URL-related FPs.
---
swift/ql/lib/codeql/swift/security/SensitiveExprs.qll | 2 +-
.../query-tests/Security/CWE-311/CleartextTransmission.expected | 2 --
.../test/query-tests/Security/CWE-311/SensitiveExprs.expected | 1 -
swift/ql/test/query-tests/Security/CWE-311/testSend.swift | 2 +-
4 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
index aa66f6d93fd..c1bc5d0bd50 100644
--- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
+++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
@@ -69,7 +69,7 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo {
* contain hashed or encrypted data, or are only a reference to data that is
* actually stored elsewhere.
*/
-private string regexpProbablySafe() { result = ".*(hash|crypt|file|path|invalid).*" }
+private string regexpProbablySafe() { result = ".*(hash|crypt|file|path|url|invalid).*" }
/**
* A `VarDecl` that might be used to contain sensitive data.
diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
index 459d3cba917..13c8c921f2d 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
@@ -38,7 +38,6 @@ nodes
| testSend.swift:61:27:61:27 | str3 | semmle.label | str3 |
| testSend.swift:65:27:65:27 | license_key | semmle.label | license_key |
| testSend.swift:66:27:66:30 | .mobileNumber | semmle.label | .mobileNumber |
-| testSend.swift:67:27:67:30 | .mobileUrl | semmle.label | .mobileUrl |
| testSend.swift:68:27:68:30 | .mobilePlayer | semmle.label | .mobilePlayer |
| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | semmle.label | .passwordFeatureEnabled |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
@@ -60,7 +59,6 @@ subpaths
| testSend.swift:61:27:61:27 | str3 | testSend.swift:54:17:54:17 | password | testSend.swift:61:27:61:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@. | testSend.swift:54:17:54:17 | password | password |
| testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | testSend.swift:65:27:65:27 | license_key | license_key |
| testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | This operation transmits '.mobileNumber', which may contain unencrypted sensitive data from $@. | testSend.swift:66:27:66:30 | .mobileNumber | .mobileNumber |
-| testSend.swift:67:27:67:30 | .mobileUrl | testSend.swift:67:27:67:30 | .mobileUrl | testSend.swift:67:27:67:30 | .mobileUrl | This operation transmits '.mobileUrl', which may contain unencrypted sensitive data from $@. | testSend.swift:67:27:67:30 | .mobileUrl | .mobileUrl |
| testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | This operation transmits '.mobilePlayer', which may contain unencrypted sensitive data from $@. | testSend.swift:68:27:68:30 | .mobilePlayer | .mobilePlayer |
| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | This operation transmits '.passwordFeatureEnabled', which may contain unencrypted sensitive data from $@. | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | .passwordFeatureEnabled |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:13:54:13:54 | passwd | passwd |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
index 9e06f8f7314..ebda7360324 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
@@ -128,7 +128,6 @@
| testSend.swift:57:27:57:27 | password | label:password, type:credential |
| testSend.swift:65:27:65:27 | license_key | label:license_key, type:credential |
| testSend.swift:66:27:66:30 | .mobileNumber | label:mobileNumber, type:private information |
-| testSend.swift:67:27:67:30 | .mobileUrl | label:mobileUrl, type:private information |
| testSend.swift:68:27:68:30 | .mobilePlayer | label:mobilePlayer, type:private information |
| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | label:passwordFeatureEnabled, type:credential |
| testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
index 6ba78ede6e7..4504b09c4e0 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
@@ -64,7 +64,7 @@ func test2(password : String, license_key: String, ms: MyStruct, connection : NW
connection.send(content: str6, completion: .idempotent) // GOOD (encrypted)
connection.send(content: license_key, completion: .idempotent) // BAD
connection.send(content: ms.mobileNumber, completion: .idempotent) // BAD
- connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
+ connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive)
connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
}
From a0cba8cb6b2eca1ee48a5a3f6412187dda5dc8b2 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Fri, 12 May 2023 22:47:03 +0100
Subject: [PATCH 34/67] Swift: Address boolean value FPs.
---
.../swift/security/CleartextLoggingExtensions.qll | 12 ++++++++++++
.../security/CleartextStorageDatabaseExtensions.qll | 11 ++++++++---
.../CleartextStoragePreferencesExtensions.qll | 12 ++++++++----
.../security/CleartextTransmissionExtensions.qll | 11 ++++++++---
.../Security/CWE-311/CleartextTransmission.expected | 2 --
.../test/query-tests/Security/CWE-311/testSend.swift | 2 +-
6 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
index 1adc157fb6f..8f36a95e99d 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextLoggingExtensions.qll
@@ -29,6 +29,18 @@ private class DefaultCleartextLoggingSink extends CleartextLoggingSink {
DefaultCleartextLoggingSink() { sinkNode(this, "log-injection") }
}
+/**
+ * An barrier for cleartext logging vulnerabilities.
+ * - encryption; encrypted values are not cleartext.
+ * - booleans; these are more likely to be settings, rather than actual sensitive data.
+ */
+private class CleartextLoggingDefaultBarrier extends CleartextLoggingBarrier {
+ CleartextLoggingDefaultBarrier() {
+ this.asExpr() instanceof EncryptedExpr or
+ this.asExpr().getType().getUnderlyingType() instanceof BoolType
+ }
+}
+
/**
* A barrier for `OSLogMessage`s configured with the appropriate privacy option.
* Numeric and boolean arguments aren't redacted unless the `private` or `sensitive` options are used.
diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll
index 4d024ced959..cb7e8c53ec8 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll
@@ -114,10 +114,15 @@ private class CleartextStorageDatabaseSinks extends SinkModelCsv {
}
/**
- * An encryption barrier for cleartext database storage vulnerabilities.
+ * An barrier for cleartext database storage vulnerabilities.
+ * - encryption; encrypted values are not cleartext.
+ * - booleans; these are more likely to be settings, rather than actual sensitive data.
*/
-private class CleartextStorageDatabaseEncryptionBarrier extends CleartextStorageDatabaseBarrier {
- CleartextStorageDatabaseEncryptionBarrier() { this.asExpr() instanceof EncryptedExpr }
+private class CleartextStorageDatabaseDefaultBarrier extends CleartextStorageDatabaseBarrier {
+ CleartextStorageDatabaseDefaultBarrier() {
+ this.asExpr() instanceof EncryptedExpr or
+ this.asExpr().getType().getUnderlyingType() instanceof BoolType
+ }
}
/**
diff --git a/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll
index cc7a443e8e2..b3306dabc9f 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextStoragePreferencesExtensions.qll
@@ -74,11 +74,15 @@ private class NSUserDefaultsControllerStore extends CleartextStoragePreferencesS
}
/**
- * An encryption barrier for cleartext preferences storage vulnerabilities.
+ * An barrier for cleartext preferences storage vulnerabilities.
+ * - encryption; encrypted values are not cleartext.
+ * - booleans; these are more likely to be settings, rather than actual sensitive data.
*/
-private class CleartextStoragePreferencesEncryptionBarrier extends CleartextStoragePreferencesBarrier
-{
- CleartextStoragePreferencesEncryptionBarrier() { this.asExpr() instanceof EncryptedExpr }
+private class CleartextStoragePreferencesDefaultBarrier extends CleartextStoragePreferencesBarrier {
+ CleartextStoragePreferencesDefaultBarrier() {
+ this.asExpr() instanceof EncryptedExpr or
+ this.asExpr().getType().getUnderlyingType() instanceof BoolType
+ }
}
/**
diff --git a/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll
index 760a2f3500b..a9dedff2f6c 100644
--- a/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll
+++ b/swift/ql/lib/codeql/swift/security/CleartextTransmissionExtensions.qll
@@ -81,10 +81,15 @@ private class AlamofireTransmittedSink extends CleartextTransmissionSink {
}
/**
- * An encryption barrier for cleartext transmission vulnerabilities.
+ * An barrier for cleartext transmission vulnerabilities.
+ * - encryption; encrypted values are not cleartext.
+ * - booleans; these are more likely to be settings, rather than actual sensitive data.
*/
-private class CleartextTransmissionEncryptionBarrier extends CleartextTransmissionBarrier {
- CleartextTransmissionEncryptionBarrier() { this.asExpr() instanceof EncryptedExpr }
+private class CleartextTransmissionDefaultBarrier extends CleartextTransmissionBarrier {
+ CleartextTransmissionDefaultBarrier() {
+ this.asExpr() instanceof EncryptedExpr or
+ this.asExpr().getType().getUnderlyingType() instanceof BoolType
+ }
}
/**
diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
index 13c8c921f2d..32a04544c2f 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
@@ -39,7 +39,6 @@ nodes
| testSend.swift:65:27:65:27 | license_key | semmle.label | license_key |
| testSend.swift:66:27:66:30 | .mobileNumber | semmle.label | .mobileNumber |
| testSend.swift:68:27:68:30 | .mobilePlayer | semmle.label | .mobilePlayer |
-| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | semmle.label | .passwordFeatureEnabled |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| testURL.swift:13:54:13:54 | passwd | semmle.label | passwd |
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
@@ -60,7 +59,6 @@ subpaths
| testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | testSend.swift:65:27:65:27 | license_key | license_key |
| testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | This operation transmits '.mobileNumber', which may contain unencrypted sensitive data from $@. | testSend.swift:66:27:66:30 | .mobileNumber | .mobileNumber |
| testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | This operation transmits '.mobilePlayer', which may contain unencrypted sensitive data from $@. | testSend.swift:68:27:68:30 | .mobilePlayer | .mobilePlayer |
-| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | This operation transmits '.passwordFeatureEnabled', which may contain unencrypted sensitive data from $@. | testSend.swift:69:27:69:30 | .passwordFeatureEnabled | .passwordFeatureEnabled |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:13:54:13:54 | passwd | passwd |
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:16:55:16:55 | credit_card_no | credit_card_no |
| testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | This operation transmits 'passwd', which may contain unencrypted sensitive data from $@. | testURL.swift:20:22:20:22 | passwd | passwd |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
index 4504b09c4e0..ee6bf6beaf5 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
@@ -66,5 +66,5 @@ func test2(password : String, license_key: String, ms: MyStruct, connection : NW
connection.send(content: ms.mobileNumber, completion: .idempotent) // BAD
connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive)
connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
- connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
+ connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive)
}
From 3cdb27725ad3d20a1ac82712c2682cd37c5b6249 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 8 May 2023 12:40:47 +0200
Subject: [PATCH 35/67] Ruby: Add more call graph tests
---
.../library-tests/modules/ancestors.expected | 42 +-
.../library-tests/modules/callgraph.expected | 430 ++--
ruby/ql/test/library-tests/modules/calls.rb | 16 +
.../library-tests/modules/methods.expected | 974 ++++----
.../library-tests/modules/modules.expected | 1984 +++++++++--------
.../modules/superclasses.expected | 42 +-
6 files changed, 1798 insertions(+), 1690 deletions(-)
diff --git a/ruby/ql/test/library-tests/modules/ancestors.expected b/ruby/ql/test/library-tests/modules/ancestors.expected
index 2ebc068459f..042808a34f0 100644
--- a/ruby/ql/test/library-tests/modules/ancestors.expected
+++ b/ruby/ql/test/library-tests/modules/ancestors.expected
@@ -94,64 +94,64 @@ calls.rb:
# 325| C1
#-----| super -> Object
-# 331| C2
+# 335| C2
#-----| super -> C1
-# 337| C3
+# 341| C3
#-----| super -> C2
-# 377| SingletonOverride1
+# 385| SingletonOverride1
#-----| super -> Object
-# 412| SingletonOverride2
+# 420| SingletonOverride2
#-----| super -> SingletonOverride1
-# 433| ConditionalInstanceMethods
+# 441| ConditionalInstanceMethods
#-----| super -> Object
-# 496| ExtendSingletonMethod
+# 504| ExtendSingletonMethod
-# 506| ExtendSingletonMethod2
+# 514| ExtendSingletonMethod2
-# 512| ExtendSingletonMethod3
+# 520| ExtendSingletonMethod3
-# 525| ProtectedMethodInModule
+# 533| ProtectedMethodInModule
-# 531| ProtectedMethods
+# 539| ProtectedMethods
#-----| super -> Object
#-----| include -> ProtectedMethodInModule
-# 550| ProtectedMethodsSub
+# 558| ProtectedMethodsSub
#-----| super -> ProtectedMethods
-# 564| SingletonUpCall_Base
+# 572| SingletonUpCall_Base
#-----| super -> Object
-# 568| SingletonUpCall_Sub
+# 576| SingletonUpCall_Sub
#-----| super -> SingletonUpCall_Base
-# 576| SingletonUpCall_SubSub
+# 584| SingletonUpCall_SubSub
#-----| super -> SingletonUpCall_Sub
-# 583| SingletonA
+# 591| SingletonA
#-----| super -> Object
-# 596| SingletonB
+# 604| SingletonB
#-----| super -> SingletonA
-# 605| SingletonC
+# 613| SingletonC
#-----| super -> SingletonA
-# 618| Included
+# 626| Included
-# 626| IncludesIncluded
+# 634| IncludesIncluded
#-----| super -> Object
#-----| include -> Included
-# 633| CustomNew1
+# 641| CustomNew1
#-----| super -> Object
-# 641| CustomNew2
+# 649| CustomNew2
#-----| super -> Object
hello.rb:
diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected
index d888b8b2474..01b57aab2f8 100644
--- a/ruby/ql/test/library-tests/modules/callgraph.expected
+++ b/ruby/ql/test/library-tests/modules/callgraph.expected
@@ -117,134 +117,145 @@ getTarget
| calls.rb:320:5:320:16 | call to instance | calls.rb:311:5:314:7 | instance |
| calls.rb:323:1:323:17 | call to singleton | calls.rb:316:5:318:7 | singleton |
| calls.rb:327:9:327:26 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:333:9:333:26 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:339:9:339:26 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:346:9:346:18 | call to instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:348:9:348:18 | call to instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:348:9:348:18 | call to instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:350:9:350:18 | call to instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:350:9:350:18 | call to instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:350:9:350:18 | call to instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:355:20:355:29 | call to instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:356:26:356:36 | call to instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:356:26:356:36 | call to instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:357:26:357:36 | call to instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:357:26:357:36 | call to instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:357:26:357:36 | call to instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:361:6:361:11 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:362:1:362:11 | call to instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:363:19:363:24 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:364:19:364:24 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:365:19:365:24 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:369:9:369:28 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:373:6:373:11 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:375:1:375:11 | call to instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:375:1:375:11 | call to instance | calls.rb:368:5:370:7 | instance |
-| calls.rb:380:13:380:48 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:388:13:388:20 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:388:13:388:30 | call to instance1 | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:388:13:388:30 | call to instance1 | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:393:9:393:44 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:400:5:400:14 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:403:9:403:43 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 |
-| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:396:5:398:7 | call_singleton2 |
-| calls.rb:415:13:415:48 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:420:9:420:44 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:424:9:424:43 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:383:9:385:11 | call_singleton1 |
-| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:396:5:398:7 | call_singleton2 |
-| calls.rb:436:13:436:48 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:441:9:441:44 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:337:9:337:26 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:343:9:343:26 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:350:9:350:18 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:352:9:352:18 | call to instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:352:9:352:18 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:354:9:354:18 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:354:9:354:18 | call to instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:354:9:354:18 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:359:20:359:29 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:360:26:360:36 | call to instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:360:26:360:36 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:361:26:361:36 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:361:26:361:36 | call to instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:361:26:361:36 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:365:6:365:11 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:366:1:366:11 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:368:1:368:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:368:19:368:24 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:369:1:369:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:369:19:369:24 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:370:1:370:25 | call to pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:370:19:370:24 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:372:1:372:6 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:372:1:372:18 | call to return_self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:372:1:372:27 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:372:1:372:27 | call to instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:372:1:372:27 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:376:9:376:28 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:380:6:380:11 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:381:1:381:16 | call to add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:382:1:382:11 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:382:1:382:11 | call to instance | calls.rb:375:5:377:7 | instance |
+| calls.rb:383:1:383:14 | call to return_self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:383:1:383:23 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:383:1:383:23 | call to instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:383:1:383:23 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:388:13:388:48 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:396:13:396:20 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:396:13:396:30 | call to instance1 | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:396:13:396:30 | call to instance1 | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:401:9:401:44 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:408:5:408:14 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:411:9:411:43 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:415:1:415:29 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:416:1:416:29 | call to singleton2 | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:417:1:417:34 | call to call_singleton1 | calls.rb:391:9:393:11 | call_singleton1 |
+| calls.rb:418:1:418:34 | call to call_singleton2 | calls.rb:404:5:406:7 | call_singleton2 |
+| calls.rb:423:13:423:48 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:428:9:428:44 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:432:9:432:43 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:436:1:436:29 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:437:1:437:29 | call to singleton2 | calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:438:1:438:34 | call to call_singleton1 | calls.rb:391:9:393:11 | call_singleton1 |
+| calls.rb:439:1:439:34 | call to call_singleton2 | calls.rb:404:5:406:7 | call_singleton2 |
| calls.rb:444:13:444:48 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:447:17:447:52 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:455:9:459:11 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:455:9:459:15 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:457:17:457:40 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:463:1:463:30 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:463:1:463:33 | call to m1 | calls.rb:435:9:437:11 | m1 |
-| calls.rb:464:1:464:30 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:465:1:465:30 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:465:1:465:33 | call to m2 | calls.rb:440:5:452:7 | m2 |
-| calls.rb:466:1:466:30 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:467:1:467:30 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:468:1:468:30 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:470:27:488:3 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:473:13:473:22 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:477:5:481:7 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:477:5:481:11 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:479:13:479:22 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:485:13:485:27 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:490:1:490:27 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:491:1:491:27 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:492:1:492:27 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:493:1:493:27 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:494:1:494:27 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:504:1:504:31 | call to singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:510:1:510:32 | call to singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:517:1:517:32 | call to singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:523:1:523:13 | call to singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:532:5:532:35 | call to include | calls.rb:108:5:110:7 | include |
-| calls.rb:535:9:535:35 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:539:9:539:11 | call to foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:540:9:540:11 | call to bar | calls.rb:534:15:536:7 | bar |
-| calls.rb:541:9:541:28 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:541:9:541:32 | call to foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:542:9:542:28 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:542:9:542:32 | call to bar | calls.rb:534:15:536:7 | bar |
-| calls.rb:546:1:546:20 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:547:1:547:20 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:548:1:548:20 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:548:1:548:24 | call to baz | calls.rb:538:5:543:7 | baz |
-| calls.rb:552:9:552:11 | call to foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:553:9:553:31 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:553:9:553:35 | call to foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:557:1:557:23 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:558:1:558:23 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:559:1:559:23 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:559:1:559:27 | call to baz | calls.rb:551:5:554:7 | baz |
-| calls.rb:561:2:561:6 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:561:20:561:24 | call to baz | calls.rb:51:5:57:7 | baz |
-| calls.rb:562:26:562:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize |
-| calls.rb:569:5:569:13 | call to singleton | calls.rb:565:5:566:7 | singleton |
-| calls.rb:572:9:572:17 | call to singleton | calls.rb:565:5:566:7 | singleton |
-| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:577:5:578:7 | singleton2 |
-| calls.rb:580:5:580:14 | call to mid_method | calls.rb:571:5:574:7 | mid_method |
-| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:584:5:585:7 | singleton1 |
-| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:597:5:598:7 | singleton1 |
-| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:606:5:607:7 | singleton1 |
-| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:587:5:589:7 | call_singleton1 |
-| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:600:5:602:7 | call_singleton1 |
-| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:609:5:611:7 | call_singleton1 |
-| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:597:5:598:7 | singleton1 |
-| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:606:5:607:7 | singleton1 |
-| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
-| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
-| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
-| calls.rb:620:9:620:16 | call to bar | calls.rb:622:5:623:7 | bar |
-| calls.rb:620:9:620:16 | call to bar | calls.rb:628:5:630:7 | bar |
-| calls.rb:627:5:627:20 | call to include | calls.rb:108:5:110:7 | include |
-| calls.rb:629:9:629:13 | super call to bar | calls.rb:622:5:623:7 | bar |
-| calls.rb:635:9:635:14 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:639:1:639:14 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:639:1:639:14 | call to new | calls.rb:634:5:636:7 | new |
-| calls.rb:639:1:639:23 | call to instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:647:9:647:34 | call to puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:651:1:651:14 | call to new | calls.rb:117:5:117:16 | new |
-| calls.rb:651:1:651:14 | call to new | calls.rb:642:5:644:7 | new |
-| calls.rb:651:1:651:23 | call to instance | calls.rb:646:5:648:7 | instance |
+| calls.rb:449:9:449:44 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:452:13:452:48 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:455:17:455:52 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:463:9:467:11 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:463:9:467:15 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:465:17:465:40 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:471:1:471:30 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:471:1:471:33 | call to m1 | calls.rb:443:9:445:11 | m1 |
+| calls.rb:472:1:472:30 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:473:1:473:30 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:473:1:473:33 | call to m2 | calls.rb:448:5:460:7 | m2 |
+| calls.rb:474:1:474:30 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:475:1:475:30 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:476:1:476:30 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:478:27:496:3 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:481:13:481:22 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:485:5:489:7 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:485:5:489:11 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:487:13:487:22 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:493:13:493:27 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:498:1:498:27 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:499:1:499:27 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:500:1:500:27 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:501:1:501:27 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:502:1:502:27 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:512:1:512:31 | call to singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:518:1:518:32 | call to singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:525:1:525:32 | call to singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:531:1:531:13 | call to singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:540:5:540:35 | call to include | calls.rb:108:5:110:7 | include |
+| calls.rb:543:9:543:35 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:547:9:547:11 | call to foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:548:9:548:11 | call to bar | calls.rb:542:15:544:7 | bar |
+| calls.rb:549:9:549:28 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:549:9:549:32 | call to foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:550:9:550:28 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:550:9:550:32 | call to bar | calls.rb:542:15:544:7 | bar |
+| calls.rb:554:1:554:20 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:555:1:555:20 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:556:1:556:20 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:556:1:556:24 | call to baz | calls.rb:546:5:551:7 | baz |
+| calls.rb:560:9:560:11 | call to foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:561:9:561:31 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:561:9:561:35 | call to foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:565:1:565:23 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:566:1:566:23 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:567:1:567:23 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:567:1:567:27 | call to baz | calls.rb:559:5:562:7 | baz |
+| calls.rb:569:2:569:6 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:569:20:569:24 | call to baz | calls.rb:51:5:57:7 | baz |
+| calls.rb:570:26:570:37 | call to capitalize | calls.rb:97:5:97:23 | capitalize |
+| calls.rb:577:5:577:13 | call to singleton | calls.rb:573:5:574:7 | singleton |
+| calls.rb:580:9:580:17 | call to singleton | calls.rb:573:5:574:7 | singleton |
+| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:585:5:586:7 | singleton2 |
+| calls.rb:588:5:588:14 | call to mid_method | calls.rb:579:5:582:7 | mid_method |
+| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:592:5:593:7 | singleton1 |
+| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:605:5:606:7 | singleton1 |
+| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:614:5:615:7 | singleton1 |
+| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:595:5:597:7 | call_singleton1 |
+| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:608:5:610:7 | call_singleton1 |
+| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:617:5:619:7 | call_singleton1 |
+| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:605:5:606:7 | singleton1 |
+| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:614:5:615:7 | singleton1 |
+| calls.rb:622:1:622:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
+| calls.rb:623:1:623:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
+| calls.rb:624:1:624:31 | call to call_call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
+| calls.rb:628:9:628:16 | call to bar | calls.rb:630:5:631:7 | bar |
+| calls.rb:628:9:628:16 | call to bar | calls.rb:636:5:638:7 | bar |
+| calls.rb:635:5:635:20 | call to include | calls.rb:108:5:110:7 | include |
+| calls.rb:637:9:637:13 | super call to bar | calls.rb:630:5:631:7 | bar |
+| calls.rb:643:9:643:14 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:647:1:647:14 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:647:1:647:14 | call to new | calls.rb:642:5:644:7 | new |
+| calls.rb:647:1:647:23 | call to instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:655:9:655:34 | call to puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:659:1:659:14 | call to new | calls.rb:117:5:117:16 | new |
+| calls.rb:659:1:659:14 | call to new | calls.rb:650:5:652:7 | new |
+| calls.rb:659:1:659:23 | call to instance | calls.rb:654:5:656:7 | instance |
+| calls.rb:667:2:667:25 | call to capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:667:20:667:25 | call to new | calls.rb:117:5:117:16 | new |
| hello.rb:12:5:12:24 | call to include | calls.rb:108:5:110:7 | include |
| hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello |
| hello.rb:20:16:20:20 | super call to message | hello.rb:13:5:15:7 | message |
@@ -330,46 +341,49 @@ unresolvedCall
| calls.rb:274:1:274:14 | call to singleton_g |
| calls.rb:276:1:276:14 | call to singleton_g |
| calls.rb:313:9:313:20 | call to instance |
-| calls.rb:434:8:434:13 | call to rand |
-| calls.rb:434:8:434:17 | ... > ... |
-| calls.rb:451:9:451:10 | call to m3 |
-| calls.rb:454:8:454:13 | call to rand |
-| calls.rb:454:8:454:17 | ... > ... |
-| calls.rb:455:9:459:18 | call to m5 |
-| calls.rb:464:1:464:33 | call to m3 |
-| calls.rb:466:1:466:33 | call to m3 |
-| calls.rb:467:1:467:33 | call to m4 |
-| calls.rb:468:1:468:33 | call to m5 |
-| calls.rb:471:5:471:11 | call to [] |
-| calls.rb:471:5:475:7 | call to each |
-| calls.rb:477:5:481:15 | call to bar |
-| calls.rb:483:5:483:11 | call to [] |
-| calls.rb:483:5:487:7 | call to each |
-| calls.rb:484:9:486:11 | call to define_method |
-| calls.rb:490:1:490:31 | call to foo |
-| calls.rb:491:1:491:31 | call to bar |
-| calls.rb:492:1:492:33 | call to baz_0 |
-| calls.rb:493:1:493:33 | call to baz_1 |
-| calls.rb:494:1:494:33 | call to baz_2 |
-| calls.rb:498:9:498:46 | call to puts |
-| calls.rb:501:5:501:15 | call to extend |
-| calls.rb:507:5:507:32 | call to extend |
-| calls.rb:515:1:515:51 | call to extend |
-| calls.rb:520:1:520:13 | call to singleton |
-| calls.rb:521:1:521:32 | call to extend |
-| calls.rb:526:5:528:7 | call to protected |
-| calls.rb:527:9:527:42 | call to puts |
+| calls.rb:442:8:442:13 | call to rand |
+| calls.rb:442:8:442:17 | ... > ... |
+| calls.rb:459:9:459:10 | call to m3 |
+| calls.rb:462:8:462:13 | call to rand |
+| calls.rb:462:8:462:17 | ... > ... |
+| calls.rb:463:9:467:18 | call to m5 |
+| calls.rb:472:1:472:33 | call to m3 |
+| calls.rb:474:1:474:33 | call to m3 |
+| calls.rb:475:1:475:33 | call to m4 |
+| calls.rb:476:1:476:33 | call to m5 |
+| calls.rb:479:5:479:11 | call to [] |
+| calls.rb:479:5:483:7 | call to each |
+| calls.rb:485:5:489:15 | call to bar |
+| calls.rb:491:5:491:11 | call to [] |
+| calls.rb:491:5:495:7 | call to each |
+| calls.rb:492:9:494:11 | call to define_method |
+| calls.rb:498:1:498:31 | call to foo |
+| calls.rb:499:1:499:31 | call to bar |
+| calls.rb:500:1:500:33 | call to baz_0 |
+| calls.rb:501:1:501:33 | call to baz_1 |
+| calls.rb:502:1:502:33 | call to baz_2 |
+| calls.rb:506:9:506:46 | call to puts |
+| calls.rb:509:5:509:15 | call to extend |
+| calls.rb:515:5:515:32 | call to extend |
+| calls.rb:523:1:523:51 | call to extend |
+| calls.rb:528:1:528:13 | call to singleton |
+| calls.rb:529:1:529:32 | call to extend |
| calls.rb:534:5:536:7 | call to protected |
-| calls.rb:546:1:546:24 | call to foo |
-| calls.rb:547:1:547:24 | call to bar |
-| calls.rb:557:1:557:27 | call to foo |
-| calls.rb:558:1:558:27 | call to bar |
-| calls.rb:561:1:561:7 | call to [] |
-| calls.rb:561:1:561:26 | call to each |
-| calls.rb:562:1:562:13 | call to [] |
-| calls.rb:562:1:562:39 | call to each |
-| calls.rb:570:5:570:14 | call to singleton2 |
-| calls.rb:643:9:643:21 | call to allocate |
+| calls.rb:535:9:535:42 | call to puts |
+| calls.rb:542:5:544:7 | call to protected |
+| calls.rb:554:1:554:24 | call to foo |
+| calls.rb:555:1:555:24 | call to bar |
+| calls.rb:565:1:565:27 | call to foo |
+| calls.rb:566:1:566:27 | call to bar |
+| calls.rb:569:1:569:7 | call to [] |
+| calls.rb:569:1:569:26 | call to each |
+| calls.rb:570:1:570:13 | call to [] |
+| calls.rb:570:1:570:39 | call to each |
+| calls.rb:578:5:578:14 | call to singleton2 |
+| calls.rb:651:9:651:21 | call to allocate |
+| calls.rb:662:5:662:11 | call to [] |
+| calls.rb:662:5:664:7 | call to each |
+| calls.rb:667:1:667:35 | call to instance |
| hello.rb:20:16:20:26 | ... + ... |
| hello.rb:20:16:20:34 | ... + ... |
| hello.rb:20:16:20:40 | ... + ... |
@@ -397,10 +411,11 @@ privateMethod
| calls.rb:158:1:160:3 | indirect |
| calls.rb:185:1:186:3 | private_on_main |
| calls.rb:278:1:286:3 | create |
-| calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:472:9:474:11 | foo |
-| calls.rb:478:9:480:11 | bar |
+| calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:480:9:482:11 | foo |
+| calls.rb:486:9:488:11 | bar |
+| calls.rb:661:1:665:3 | capture_parameter |
| private.rb:2:11:3:5 | private1 |
| private.rb:8:3:9:5 | private2 |
| private.rb:14:3:15:5 | private3 |
@@ -459,42 +474,43 @@ publicMethod
| calls.rb:311:5:314:7 | instance |
| calls.rb:316:5:318:7 | singleton |
| calls.rb:326:5:328:7 | instance |
-| calls.rb:332:5:334:7 | instance |
-| calls.rb:338:5:340:7 | instance |
-| calls.rb:368:5:370:7 | instance |
-| calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:383:9:385:11 | call_singleton1 |
-| calls.rb:387:9:389:11 | factory |
-| calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:396:5:398:7 | call_singleton2 |
-| calls.rb:402:5:404:7 | instance1 |
-| calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:423:5:425:7 | instance1 |
-| calls.rb:435:9:437:11 | m1 |
-| calls.rb:440:5:452:7 | m2 |
-| calls.rb:443:9:449:11 | m3 |
-| calls.rb:446:13:448:15 | m4 |
-| calls.rb:456:13:458:15 | m5 |
-| calls.rb:497:5:499:7 | singleton |
-| calls.rb:538:5:543:7 | baz |
-| calls.rb:551:5:554:7 | baz |
-| calls.rb:565:5:566:7 | singleton |
-| calls.rb:571:5:574:7 | mid_method |
-| calls.rb:577:5:578:7 | singleton2 |
-| calls.rb:584:5:585:7 | singleton1 |
-| calls.rb:587:5:589:7 | call_singleton1 |
-| calls.rb:591:5:593:7 | call_call_singleton1 |
-| calls.rb:597:5:598:7 | singleton1 |
-| calls.rb:600:5:602:7 | call_singleton1 |
-| calls.rb:606:5:607:7 | singleton1 |
-| calls.rb:609:5:611:7 | call_singleton1 |
-| calls.rb:619:5:621:7 | foo |
-| calls.rb:622:5:623:7 | bar |
-| calls.rb:628:5:630:7 | bar |
-| calls.rb:634:5:636:7 | new |
+| calls.rb:330:5:332:7 | return_self |
+| calls.rb:336:5:338:7 | instance |
+| calls.rb:342:5:344:7 | instance |
+| calls.rb:375:5:377:7 | instance |
+| calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:391:9:393:11 | call_singleton1 |
+| calls.rb:395:9:397:11 | factory |
+| calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:404:5:406:7 | call_singleton2 |
+| calls.rb:410:5:412:7 | instance1 |
+| calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:431:5:433:7 | instance1 |
+| calls.rb:443:9:445:11 | m1 |
+| calls.rb:448:5:460:7 | m2 |
+| calls.rb:451:9:457:11 | m3 |
+| calls.rb:454:13:456:15 | m4 |
+| calls.rb:464:13:466:15 | m5 |
+| calls.rb:505:5:507:7 | singleton |
+| calls.rb:546:5:551:7 | baz |
+| calls.rb:559:5:562:7 | baz |
+| calls.rb:573:5:574:7 | singleton |
+| calls.rb:579:5:582:7 | mid_method |
+| calls.rb:585:5:586:7 | singleton2 |
+| calls.rb:592:5:593:7 | singleton1 |
+| calls.rb:595:5:597:7 | call_singleton1 |
+| calls.rb:599:5:601:7 | call_call_singleton1 |
+| calls.rb:605:5:606:7 | singleton1 |
+| calls.rb:608:5:610:7 | call_singleton1 |
+| calls.rb:614:5:615:7 | singleton1 |
+| calls.rb:617:5:619:7 | call_singleton1 |
+| calls.rb:627:5:629:7 | foo |
+| calls.rb:630:5:631:7 | bar |
+| calls.rb:636:5:638:7 | bar |
| calls.rb:642:5:644:7 | new |
-| calls.rb:646:5:648:7 | instance |
+| calls.rb:650:5:652:7 | new |
+| calls.rb:654:5:656:7 | instance |
| hello.rb:2:5:4:7 | hello |
| hello.rb:5:5:7:7 | world |
| hello.rb:13:5:15:7 | message |
@@ -522,7 +538,7 @@ publicMethod
| toplevel_self_singleton.rb:26:9:27:11 | call_me |
| toplevel_self_singleton.rb:29:9:32:11 | call_you |
protectedMethod
-| calls.rb:526:15:528:7 | foo |
-| calls.rb:534:15:536:7 | bar |
+| calls.rb:534:15:536:7 | foo |
+| calls.rb:542:15:544:7 | bar |
| private.rb:32:3:33:5 | protected1 |
| private.rb:35:3:36:5 | protected2 |
diff --git a/ruby/ql/test/library-tests/modules/calls.rb b/ruby/ql/test/library-tests/modules/calls.rb
index 27d90f84e93..ed0ee9528d6 100644
--- a/ruby/ql/test/library-tests/modules/calls.rb
+++ b/ruby/ql/test/library-tests/modules/calls.rb
@@ -326,6 +326,10 @@ class C1
def instance
puts "C1#instance"
end
+
+ def return_self
+ self
+ end
end
class C2 < C1
@@ -360,10 +364,13 @@ end
c1 = C1.new
c1.instance
+
pattern_dispatch (C1.new)
pattern_dispatch (C2.new)
pattern_dispatch (C3.new)
+C3.new.return_self.instance
+
def add_singleton x
def x.instance
puts "instance_on x"
@@ -373,6 +380,7 @@ end
c3 = C1.new
add_singleton c3
c3.instance
+c3.return_self.instance
class SingletonOverride1
class << self
@@ -649,3 +657,11 @@ class CustomNew2
end
CustomNew2.new.instance
+
+def capture_parameter x
+ [0,1,2].each do
+ x
+ end
+end
+
+(capture_parameter C1.new).instance # NoMethodError
diff --git a/ruby/ql/test/library-tests/modules/methods.expected b/ruby/ql/test/library-tests/modules/methods.expected
index cb936f30778..19d39d0ed6a 100644
--- a/ruby/ql/test/library-tests/modules/methods.expected
+++ b/ruby/ql/test/library-tests/modules/methods.expected
@@ -10,9 +10,10 @@ getMethod
| calls.rb:105:1:113:3 | Module | module_eval | calls.rb:107:5:107:24 | module_eval |
| calls.rb:105:1:113:3 | Module | prepend | calls.rb:111:5:111:20 | prepend |
| calls.rb:105:1:113:3 | Module | private | calls.rb:112:5:112:20 | private |
-| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:115:1:118:3 | Object | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:115:1:118:3 | Object | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:115:1:118:3 | Object | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:115:1:118:3 | Object | create | calls.rb:278:1:286:3 | create |
| calls.rb:115:1:118:3 | Object | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:115:1:118:3 | Object | foo | calls.rb:85:1:89:3 | foo |
@@ -20,7 +21,7 @@ getMethod
| calls.rb:115:1:118:3 | Object | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:115:1:118:3 | Object | new | calls.rb:117:5:117:16 | new |
| calls.rb:115:1:118:3 | Object | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:115:1:118:3 | Object | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:115:1:118:3 | Object | private_on_main | private.rb:51:1:52:3 | private_on_main |
| calls.rb:120:1:123:3 | Hash | [] | calls.rb:122:5:122:31 | [] |
@@ -33,22 +34,23 @@ getMethod
| calls.rb:190:1:226:3 | Singletons | call_singleton_g | calls.rb:223:5:225:7 | call_singleton_g |
| calls.rb:190:1:226:3 | Singletons | instance | calls.rb:210:5:215:7 | instance |
| calls.rb:310:1:321:3 | SelfNew | instance | calls.rb:311:5:314:7 | instance |
-| calls.rb:325:1:329:3 | C1 | instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:331:1:335:3 | C2 | instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:337:1:341:3 | C3 | instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:377:1:405:3 | SingletonOverride1 | instance1 | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:412:1:426:3 | SingletonOverride2 | instance1 | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m1 | calls.rb:435:9:437:11 | m1 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m2 | calls.rb:440:5:452:7 | m2 |
-| calls.rb:496:1:502:3 | ExtendSingletonMethod | singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:525:1:529:3 | ProtectedMethodInModule | foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:531:1:544:3 | ProtectedMethods | bar | calls.rb:534:15:536:7 | bar |
-| calls.rb:531:1:544:3 | ProtectedMethods | baz | calls.rb:538:5:543:7 | baz |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | baz | calls.rb:551:5:554:7 | baz |
-| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
-| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
-| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
-| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance |
+| calls.rb:325:1:333:3 | C1 | instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:325:1:333:3 | C1 | return_self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:335:1:339:3 | C2 | instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:341:1:345:3 | C3 | instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:385:1:413:3 | SingletonOverride1 | instance1 | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:420:1:434:3 | SingletonOverride2 | instance1 | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m1 | calls.rb:443:9:445:11 | m1 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m2 | calls.rb:448:5:460:7 | m2 |
+| calls.rb:504:1:510:3 | ExtendSingletonMethod | singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:533:1:537:3 | ProtectedMethodInModule | foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:539:1:552:3 | ProtectedMethods | bar | calls.rb:542:15:544:7 | bar |
+| calls.rb:539:1:552:3 | ProtectedMethods | baz | calls.rb:546:5:551:7 | baz |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | baz | calls.rb:559:5:562:7 | baz |
+| calls.rb:626:1:632:3 | Included | bar | calls.rb:630:5:631:7 | bar |
+| calls.rb:626:1:632:3 | Included | foo | calls.rb:627:5:629:7 | foo |
+| calls.rb:634:1:639:3 | IncludesIncluded | bar | calls.rb:636:5:638:7 | bar |
+| calls.rb:649:1:657:3 | CustomNew2 | instance | calls.rb:654:5:656:7 | instance |
| hello.rb:1:1:8:3 | EnglishWords | hello | hello.rb:2:5:4:7 | hello |
| hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world |
| hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message |
@@ -81,10 +83,11 @@ getMethod
| private.rb:96:1:102:3 | PrivateOverride2 | m1 | private.rb:97:11:101:5 | m1 |
lookupMethod
| calls.rb:21:1:34:3 | M | instance_m | calls.rb:22:5:24:7 | instance_m |
-| calls.rb:43:1:58:3 | C | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:43:1:58:3 | C | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:43:1:58:3 | C | baz | calls.rb:51:5:57:7 | baz |
| calls.rb:43:1:58:3 | C | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:43:1:58:3 | C | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:43:1:58:3 | C | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:43:1:58:3 | C | create | calls.rb:278:1:286:3 | create |
| calls.rb:43:1:58:3 | C | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:43:1:58:3 | C | foo | calls.rb:85:1:89:3 | foo |
@@ -93,14 +96,15 @@ lookupMethod
| calls.rb:43:1:58:3 | C | instance_m | calls.rb:22:5:24:7 | instance_m |
| calls.rb:43:1:58:3 | C | new | calls.rb:117:5:117:16 | new |
| calls.rb:43:1:58:3 | C | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:43:1:58:3 | C | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:43:1:58:3 | C | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:43:1:58:3 | C | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:43:1:58:3 | C | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:43:1:58:3 | C | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:65:1:69:3 | D | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:65:1:69:3 | D | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:65:1:69:3 | D | baz | calls.rb:66:5:68:7 | baz |
| calls.rb:65:1:69:3 | D | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:65:1:69:3 | D | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:65:1:69:3 | D | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:65:1:69:3 | D | create | calls.rb:278:1:286:3 | create |
| calls.rb:65:1:69:3 | D | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:65:1:69:3 | D | foo | calls.rb:85:1:89:3 | foo |
@@ -109,7 +113,7 @@ lookupMethod
| calls.rb:65:1:69:3 | D | instance_m | calls.rb:22:5:24:7 | instance_m |
| calls.rb:65:1:69:3 | D | new | calls.rb:117:5:117:16 | new |
| calls.rb:65:1:69:3 | D | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:65:1:69:3 | D | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:65:1:69:3 | D | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:65:1:69:3 | D | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:65:1:69:3 | D | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:65:1:69:3 | D | to_s | calls.rb:172:5:173:7 | to_s |
@@ -118,10 +122,11 @@ lookupMethod
| calls.rb:91:1:94:3 | Integer | new | calls.rb:117:5:117:16 | new |
| calls.rb:91:1:94:3 | Integer | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:91:1:94:3 | Integer | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:96:1:98:3 | String | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:96:1:98:3 | String | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:96:1:98:3 | String | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:96:1:98:3 | String | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
| calls.rb:96:1:98:3 | String | capitalize | calls.rb:97:5:97:23 | capitalize |
+| calls.rb:96:1:98:3 | String | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:96:1:98:3 | String | create | calls.rb:278:1:286:3 | create |
| calls.rb:96:1:98:3 | String | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:96:1:98:3 | String | foo | calls.rb:85:1:89:3 | foo |
@@ -129,14 +134,15 @@ lookupMethod
| calls.rb:96:1:98:3 | String | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:96:1:98:3 | String | new | calls.rb:117:5:117:16 | new |
| calls.rb:96:1:98:3 | String | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:96:1:98:3 | String | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:96:1:98:3 | String | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:96:1:98:3 | String | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:96:1:98:3 | String | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:96:1:98:3 | String | to_s | calls.rb:172:5:173:7 | to_s |
| calls.rb:100:1:103:3 | Kernel | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:105:1:113:3 | Module | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:105:1:113:3 | Module | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:105:1:113:3 | Module | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:105:1:113:3 | Module | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:105:1:113:3 | Module | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:105:1:113:3 | Module | create | calls.rb:278:1:286:3 | create |
| calls.rb:105:1:113:3 | Module | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:105:1:113:3 | Module | foo | calls.rb:85:1:89:3 | foo |
@@ -146,15 +152,16 @@ lookupMethod
| calls.rb:105:1:113:3 | Module | module_eval | calls.rb:107:5:107:24 | module_eval |
| calls.rb:105:1:113:3 | Module | new | calls.rb:117:5:117:16 | new |
| calls.rb:105:1:113:3 | Module | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:105:1:113:3 | Module | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:105:1:113:3 | Module | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:105:1:113:3 | Module | prepend | calls.rb:111:5:111:20 | prepend |
| calls.rb:105:1:113:3 | Module | private | calls.rb:112:5:112:20 | private |
| calls.rb:105:1:113:3 | Module | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:105:1:113:3 | Module | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:105:1:113:3 | Module | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:115:1:118:3 | Object | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:115:1:118:3 | Object | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:115:1:118:3 | Object | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:115:1:118:3 | Object | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:115:1:118:3 | Object | create | calls.rb:278:1:286:3 | create |
| calls.rb:115:1:118:3 | Object | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:115:1:118:3 | Object | foo | calls.rb:85:1:89:3 | foo |
@@ -162,15 +169,16 @@ lookupMethod
| calls.rb:115:1:118:3 | Object | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:115:1:118:3 | Object | new | calls.rb:117:5:117:16 | new |
| calls.rb:115:1:118:3 | Object | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:115:1:118:3 | Object | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:115:1:118:3 | Object | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:115:1:118:3 | Object | private_on_main | private.rb:51:1:52:3 | private_on_main |
| calls.rb:115:1:118:3 | Object | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:115:1:118:3 | Object | to_s | calls.rb:172:5:173:7 | to_s |
| calls.rb:120:1:123:3 | Hash | [] | calls.rb:122:5:122:31 | [] |
-| calls.rb:120:1:123:3 | Hash | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:120:1:123:3 | Hash | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:120:1:123:3 | Hash | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:120:1:123:3 | Hash | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:120:1:123:3 | Hash | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:120:1:123:3 | Hash | create | calls.rb:278:1:286:3 | create |
| calls.rb:120:1:123:3 | Hash | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:120:1:123:3 | Hash | foo | calls.rb:85:1:89:3 | foo |
@@ -178,14 +186,15 @@ lookupMethod
| calls.rb:120:1:123:3 | Hash | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:120:1:123:3 | Hash | new | calls.rb:117:5:117:16 | new |
| calls.rb:120:1:123:3 | Hash | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:120:1:123:3 | Hash | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:120:1:123:3 | Hash | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:120:1:123:3 | Hash | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:120:1:123:3 | Hash | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:120:1:123:3 | Hash | to_s | calls.rb:172:5:173:7 | to_s |
| calls.rb:125:1:138:3 | Array | [] | calls.rb:127:3:127:29 | [] |
-| calls.rb:125:1:138:3 | Array | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:125:1:138:3 | Array | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:125:1:138:3 | Array | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:125:1:138:3 | Array | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:125:1:138:3 | Array | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:125:1:138:3 | Array | create | calls.rb:278:1:286:3 | create |
| calls.rb:125:1:138:3 | Array | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:125:1:138:3 | Array | foo | calls.rb:85:1:89:3 | foo |
@@ -195,13 +204,14 @@ lookupMethod
| calls.rb:125:1:138:3 | Array | length | calls.rb:129:3:129:17 | length |
| calls.rb:125:1:138:3 | Array | new | calls.rb:117:5:117:16 | new |
| calls.rb:125:1:138:3 | Array | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:125:1:138:3 | Array | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:125:1:138:3 | Array | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:125:1:138:3 | Array | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:125:1:138:3 | Array | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:125:1:138:3 | Array | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:165:1:169:3 | S | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:165:1:169:3 | S | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:165:1:169:3 | S | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:165:1:169:3 | S | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:165:1:169:3 | S | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:165:1:169:3 | S | create | calls.rb:278:1:286:3 | create |
| calls.rb:165:1:169:3 | S | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:165:1:169:3 | S | foo | calls.rb:85:1:89:3 | foo |
@@ -209,14 +219,15 @@ lookupMethod
| calls.rb:165:1:169:3 | S | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:165:1:169:3 | S | new | calls.rb:117:5:117:16 | new |
| calls.rb:165:1:169:3 | S | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:165:1:169:3 | S | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:165:1:169:3 | S | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:165:1:169:3 | S | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:165:1:169:3 | S | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:165:1:169:3 | S | s_method | calls.rb:166:5:168:7 | s_method |
| calls.rb:165:1:169:3 | S | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:171:1:174:3 | A | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:171:1:174:3 | A | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:171:1:174:3 | A | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:171:1:174:3 | A | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:171:1:174:3 | A | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:171:1:174:3 | A | create | calls.rb:278:1:286:3 | create |
| calls.rb:171:1:174:3 | A | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:171:1:174:3 | A | foo | calls.rb:85:1:89:3 | foo |
@@ -224,14 +235,15 @@ lookupMethod
| calls.rb:171:1:174:3 | A | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:171:1:174:3 | A | new | calls.rb:117:5:117:16 | new |
| calls.rb:171:1:174:3 | A | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:171:1:174:3 | A | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:171:1:174:3 | A | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:171:1:174:3 | A | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:171:1:174:3 | A | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:171:1:174:3 | A | s_method | calls.rb:166:5:168:7 | s_method |
| calls.rb:171:1:174:3 | A | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:176:1:179:3 | B | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:176:1:179:3 | B | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:176:1:179:3 | B | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:176:1:179:3 | B | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:176:1:179:3 | B | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:176:1:179:3 | B | create | calls.rb:278:1:286:3 | create |
| calls.rb:176:1:179:3 | B | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:176:1:179:3 | B | foo | calls.rb:85:1:89:3 | foo |
@@ -239,15 +251,16 @@ lookupMethod
| calls.rb:176:1:179:3 | B | indirect | calls.rb:158:1:160:3 | indirect |
| calls.rb:176:1:179:3 | B | new | calls.rb:117:5:117:16 | new |
| calls.rb:176:1:179:3 | B | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:176:1:179:3 | B | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:176:1:179:3 | B | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:176:1:179:3 | B | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:176:1:179:3 | B | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:176:1:179:3 | B | s_method | calls.rb:166:5:168:7 | s_method |
| calls.rb:176:1:179:3 | B | to_s | calls.rb:177:5:178:7 | to_s |
-| calls.rb:190:1:226:3 | Singletons | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:190:1:226:3 | Singletons | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:190:1:226:3 | Singletons | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:190:1:226:3 | Singletons | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
| calls.rb:190:1:226:3 | Singletons | call_singleton_g | calls.rb:223:5:225:7 | call_singleton_g |
+| calls.rb:190:1:226:3 | Singletons | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:190:1:226:3 | Singletons | create | calls.rb:278:1:286:3 | create |
| calls.rb:190:1:226:3 | Singletons | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:190:1:226:3 | Singletons | foo | calls.rb:85:1:89:3 | foo |
@@ -256,13 +269,14 @@ lookupMethod
| calls.rb:190:1:226:3 | Singletons | instance | calls.rb:210:5:215:7 | instance |
| calls.rb:190:1:226:3 | Singletons | new | calls.rb:117:5:117:16 | new |
| calls.rb:190:1:226:3 | Singletons | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:190:1:226:3 | Singletons | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:190:1:226:3 | Singletons | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:190:1:226:3 | Singletons | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:190:1:226:3 | Singletons | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:190:1:226:3 | Singletons | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:310:1:321:3 | SelfNew | add_singleton | calls.rb:367:1:371:3 | add_singleton |
+| calls.rb:310:1:321:3 | SelfNew | add_singleton | calls.rb:374:1:378:3 | add_singleton |
| calls.rb:310:1:321:3 | SelfNew | call_block | calls.rb:81:1:83:3 | call_block |
| calls.rb:310:1:321:3 | SelfNew | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:310:1:321:3 | SelfNew | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
| calls.rb:310:1:321:3 | SelfNew | create | calls.rb:278:1:286:3 | create |
| calls.rb:310:1:321:3 | SelfNew | foo | calls.rb:1:1:3:3 | foo |
| calls.rb:310:1:321:3 | SelfNew | foo | calls.rb:85:1:89:3 | foo |
@@ -271,262 +285,282 @@ lookupMethod
| calls.rb:310:1:321:3 | SelfNew | instance | calls.rb:311:5:314:7 | instance |
| calls.rb:310:1:321:3 | SelfNew | new | calls.rb:117:5:117:16 | new |
| calls.rb:310:1:321:3 | SelfNew | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:310:1:321:3 | SelfNew | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
+| calls.rb:310:1:321:3 | SelfNew | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
| calls.rb:310:1:321:3 | SelfNew | private_on_main | calls.rb:185:1:186:3 | private_on_main |
| calls.rb:310:1:321:3 | SelfNew | puts | calls.rb:102:5:102:30 | puts |
| calls.rb:310:1:321:3 | SelfNew | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:325:1:329:3 | C1 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:325:1:329:3 | C1 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:325:1:329:3 | C1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:325:1:329:3 | C1 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:325:1:329:3 | C1 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:325:1:329:3 | C1 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:325:1:329:3 | C1 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:325:1:329:3 | C1 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:325:1:329:3 | C1 | instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:325:1:329:3 | C1 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:325:1:329:3 | C1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:325:1:329:3 | C1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:325:1:329:3 | C1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:325:1:329:3 | C1 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:325:1:329:3 | C1 | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:331:1:335:3 | C2 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:331:1:335:3 | C2 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:331:1:335:3 | C2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:331:1:335:3 | C2 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:331:1:335:3 | C2 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:331:1:335:3 | C2 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:331:1:335:3 | C2 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:331:1:335:3 | C2 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:331:1:335:3 | C2 | instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:331:1:335:3 | C2 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:331:1:335:3 | C2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:331:1:335:3 | C2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:331:1:335:3 | C2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:331:1:335:3 | C2 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:331:1:335:3 | C2 | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:337:1:341:3 | C3 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:337:1:341:3 | C3 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:337:1:341:3 | C3 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:337:1:341:3 | C3 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:337:1:341:3 | C3 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:337:1:341:3 | C3 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:337:1:341:3 | C3 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:337:1:341:3 | C3 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:337:1:341:3 | C3 | instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:337:1:341:3 | C3 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:337:1:341:3 | C3 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:337:1:341:3 | C3 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:337:1:341:3 | C3 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:337:1:341:3 | C3 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:337:1:341:3 | C3 | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:377:1:405:3 | SingletonOverride1 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:377:1:405:3 | SingletonOverride1 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:377:1:405:3 | SingletonOverride1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:377:1:405:3 | SingletonOverride1 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:377:1:405:3 | SingletonOverride1 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:377:1:405:3 | SingletonOverride1 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:377:1:405:3 | SingletonOverride1 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:377:1:405:3 | SingletonOverride1 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:377:1:405:3 | SingletonOverride1 | instance1 | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:377:1:405:3 | SingletonOverride1 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:377:1:405:3 | SingletonOverride1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:377:1:405:3 | SingletonOverride1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:377:1:405:3 | SingletonOverride1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:377:1:405:3 | SingletonOverride1 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:377:1:405:3 | SingletonOverride1 | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:412:1:426:3 | SingletonOverride2 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:412:1:426:3 | SingletonOverride2 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:412:1:426:3 | SingletonOverride2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:412:1:426:3 | SingletonOverride2 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:412:1:426:3 | SingletonOverride2 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:412:1:426:3 | SingletonOverride2 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:412:1:426:3 | SingletonOverride2 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:412:1:426:3 | SingletonOverride2 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:412:1:426:3 | SingletonOverride2 | instance1 | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:412:1:426:3 | SingletonOverride2 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:412:1:426:3 | SingletonOverride2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:412:1:426:3 | SingletonOverride2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:412:1:426:3 | SingletonOverride2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:412:1:426:3 | SingletonOverride2 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:412:1:426:3 | SingletonOverride2 | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | create | calls.rb:278:1:286:3 | create |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m1 | calls.rb:435:9:437:11 | m1 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | m2 | calls.rb:440:5:452:7 | m2 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | new | calls.rb:117:5:117:16 | new |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:496:1:502:3 | ExtendSingletonMethod | singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:525:1:529:3 | ProtectedMethodInModule | foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:531:1:544:3 | ProtectedMethods | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:531:1:544:3 | ProtectedMethods | bar | calls.rb:534:15:536:7 | bar |
-| calls.rb:531:1:544:3 | ProtectedMethods | baz | calls.rb:538:5:543:7 | baz |
-| calls.rb:531:1:544:3 | ProtectedMethods | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:531:1:544:3 | ProtectedMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:531:1:544:3 | ProtectedMethods | create | calls.rb:278:1:286:3 | create |
-| calls.rb:531:1:544:3 | ProtectedMethods | foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:531:1:544:3 | ProtectedMethods | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:531:1:544:3 | ProtectedMethods | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:531:1:544:3 | ProtectedMethods | new | calls.rb:117:5:117:16 | new |
-| calls.rb:531:1:544:3 | ProtectedMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:531:1:544:3 | ProtectedMethods | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:531:1:544:3 | ProtectedMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:531:1:544:3 | ProtectedMethods | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:531:1:544:3 | ProtectedMethods | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | bar | calls.rb:534:15:536:7 | bar |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | baz | calls.rb:551:5:554:7 | baz |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | create | calls.rb:278:1:286:3 | create |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | new | calls.rb:117:5:117:16 | new |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | create | calls.rb:278:1:286:3 | create |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | new | calls.rb:117:5:117:16 | new |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | create | calls.rb:278:1:286:3 | create |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | new | calls.rb:117:5:117:16 | new |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | create | calls.rb:278:1:286:3 | create |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | new | calls.rb:117:5:117:16 | new |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:583:1:594:3 | SingletonA | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:583:1:594:3 | SingletonA | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:583:1:594:3 | SingletonA | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:583:1:594:3 | SingletonA | create | calls.rb:278:1:286:3 | create |
-| calls.rb:583:1:594:3 | SingletonA | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:583:1:594:3 | SingletonA | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:583:1:594:3 | SingletonA | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:583:1:594:3 | SingletonA | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:583:1:594:3 | SingletonA | new | calls.rb:117:5:117:16 | new |
-| calls.rb:583:1:594:3 | SingletonA | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:583:1:594:3 | SingletonA | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:583:1:594:3 | SingletonA | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:583:1:594:3 | SingletonA | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:583:1:594:3 | SingletonA | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:596:1:603:3 | SingletonB | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:596:1:603:3 | SingletonB | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:596:1:603:3 | SingletonB | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:596:1:603:3 | SingletonB | create | calls.rb:278:1:286:3 | create |
-| calls.rb:596:1:603:3 | SingletonB | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:596:1:603:3 | SingletonB | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:596:1:603:3 | SingletonB | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:596:1:603:3 | SingletonB | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:596:1:603:3 | SingletonB | new | calls.rb:117:5:117:16 | new |
-| calls.rb:596:1:603:3 | SingletonB | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:596:1:603:3 | SingletonB | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:596:1:603:3 | SingletonB | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:596:1:603:3 | SingletonB | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:596:1:603:3 | SingletonB | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:605:1:612:3 | SingletonC | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:605:1:612:3 | SingletonC | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:605:1:612:3 | SingletonC | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:605:1:612:3 | SingletonC | create | calls.rb:278:1:286:3 | create |
-| calls.rb:605:1:612:3 | SingletonC | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:605:1:612:3 | SingletonC | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:605:1:612:3 | SingletonC | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:605:1:612:3 | SingletonC | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:605:1:612:3 | SingletonC | new | calls.rb:117:5:117:16 | new |
-| calls.rb:605:1:612:3 | SingletonC | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:605:1:612:3 | SingletonC | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:605:1:612:3 | SingletonC | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:605:1:612:3 | SingletonC | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:605:1:612:3 | SingletonC | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:618:1:624:3 | Included | bar | calls.rb:622:5:623:7 | bar |
-| calls.rb:618:1:624:3 | Included | foo | calls.rb:619:5:621:7 | foo |
-| calls.rb:626:1:631:3 | IncludesIncluded | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:626:1:631:3 | IncludesIncluded | bar | calls.rb:628:5:630:7 | bar |
-| calls.rb:626:1:631:3 | IncludesIncluded | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:626:1:631:3 | IncludesIncluded | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:626:1:631:3 | IncludesIncluded | create | calls.rb:278:1:286:3 | create |
-| calls.rb:626:1:631:3 | IncludesIncluded | foo | calls.rb:619:5:621:7 | foo |
-| calls.rb:626:1:631:3 | IncludesIncluded | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:626:1:631:3 | IncludesIncluded | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:626:1:631:3 | IncludesIncluded | new | calls.rb:117:5:117:16 | new |
-| calls.rb:626:1:631:3 | IncludesIncluded | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:626:1:631:3 | IncludesIncluded | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:626:1:631:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:626:1:631:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:626:1:631:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:633:1:637:3 | CustomNew1 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:633:1:637:3 | CustomNew1 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:633:1:637:3 | CustomNew1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:633:1:637:3 | CustomNew1 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:633:1:637:3 | CustomNew1 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:633:1:637:3 | CustomNew1 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:633:1:637:3 | CustomNew1 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:633:1:637:3 | CustomNew1 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:633:1:637:3 | CustomNew1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:633:1:637:3 | CustomNew1 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:633:1:637:3 | CustomNew1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:633:1:637:3 | CustomNew1 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:633:1:637:3 | CustomNew1 | to_s | calls.rb:172:5:173:7 | to_s |
-| calls.rb:641:1:649:3 | CustomNew2 | add_singleton | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:641:1:649:3 | CustomNew2 | call_block | calls.rb:81:1:83:3 | call_block |
-| calls.rb:641:1:649:3 | CustomNew2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
-| calls.rb:641:1:649:3 | CustomNew2 | create | calls.rb:278:1:286:3 | create |
-| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:1:1:3:3 | foo |
-| calls.rb:641:1:649:3 | CustomNew2 | foo | calls.rb:85:1:89:3 | foo |
-| calls.rb:641:1:649:3 | CustomNew2 | funny | calls.rb:140:1:142:3 | funny |
-| calls.rb:641:1:649:3 | CustomNew2 | indirect | calls.rb:158:1:160:3 | indirect |
-| calls.rb:641:1:649:3 | CustomNew2 | instance | calls.rb:646:5:648:7 | instance |
-| calls.rb:641:1:649:3 | CustomNew2 | new | calls.rb:117:5:117:16 | new |
-| calls.rb:641:1:649:3 | CustomNew2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
-| calls.rb:641:1:649:3 | CustomNew2 | pattern_dispatch | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:641:1:649:3 | CustomNew2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
-| calls.rb:641:1:649:3 | CustomNew2 | puts | calls.rb:102:5:102:30 | puts |
-| calls.rb:641:1:649:3 | CustomNew2 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:325:1:333:3 | C1 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:325:1:333:3 | C1 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:325:1:333:3 | C1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:325:1:333:3 | C1 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:325:1:333:3 | C1 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:325:1:333:3 | C1 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:325:1:333:3 | C1 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:325:1:333:3 | C1 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:325:1:333:3 | C1 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:325:1:333:3 | C1 | instance | calls.rb:326:5:328:7 | instance |
+| calls.rb:325:1:333:3 | C1 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:325:1:333:3 | C1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:325:1:333:3 | C1 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:325:1:333:3 | C1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:325:1:333:3 | C1 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:325:1:333:3 | C1 | return_self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:325:1:333:3 | C1 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:335:1:339:3 | C2 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:335:1:339:3 | C2 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:335:1:339:3 | C2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:335:1:339:3 | C2 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:335:1:339:3 | C2 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:335:1:339:3 | C2 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:335:1:339:3 | C2 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:335:1:339:3 | C2 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:335:1:339:3 | C2 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:335:1:339:3 | C2 | instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:335:1:339:3 | C2 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:335:1:339:3 | C2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:335:1:339:3 | C2 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:335:1:339:3 | C2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:335:1:339:3 | C2 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:335:1:339:3 | C2 | return_self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:335:1:339:3 | C2 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:341:1:345:3 | C3 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:341:1:345:3 | C3 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:341:1:345:3 | C3 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:341:1:345:3 | C3 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:341:1:345:3 | C3 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:341:1:345:3 | C3 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:341:1:345:3 | C3 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:341:1:345:3 | C3 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:341:1:345:3 | C3 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:341:1:345:3 | C3 | instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:341:1:345:3 | C3 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:341:1:345:3 | C3 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:341:1:345:3 | C3 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:341:1:345:3 | C3 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:341:1:345:3 | C3 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:341:1:345:3 | C3 | return_self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:341:1:345:3 | C3 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:385:1:413:3 | SingletonOverride1 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:385:1:413:3 | SingletonOverride1 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:385:1:413:3 | SingletonOverride1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:385:1:413:3 | SingletonOverride1 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:385:1:413:3 | SingletonOverride1 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:385:1:413:3 | SingletonOverride1 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:385:1:413:3 | SingletonOverride1 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:385:1:413:3 | SingletonOverride1 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:385:1:413:3 | SingletonOverride1 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:385:1:413:3 | SingletonOverride1 | instance1 | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:385:1:413:3 | SingletonOverride1 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:385:1:413:3 | SingletonOverride1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:385:1:413:3 | SingletonOverride1 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:385:1:413:3 | SingletonOverride1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:385:1:413:3 | SingletonOverride1 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:385:1:413:3 | SingletonOverride1 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:420:1:434:3 | SingletonOverride2 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:420:1:434:3 | SingletonOverride2 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:420:1:434:3 | SingletonOverride2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:420:1:434:3 | SingletonOverride2 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:420:1:434:3 | SingletonOverride2 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:420:1:434:3 | SingletonOverride2 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:420:1:434:3 | SingletonOverride2 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:420:1:434:3 | SingletonOverride2 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:420:1:434:3 | SingletonOverride2 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:420:1:434:3 | SingletonOverride2 | instance1 | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:420:1:434:3 | SingletonOverride2 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:420:1:434:3 | SingletonOverride2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:420:1:434:3 | SingletonOverride2 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:420:1:434:3 | SingletonOverride2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:420:1:434:3 | SingletonOverride2 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:420:1:434:3 | SingletonOverride2 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | create | calls.rb:278:1:286:3 | create |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m1 | calls.rb:443:9:445:11 | m1 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | m2 | calls.rb:448:5:460:7 | m2 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | new | calls.rb:117:5:117:16 | new |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:504:1:510:3 | ExtendSingletonMethod | singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:533:1:537:3 | ProtectedMethodInModule | foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:539:1:552:3 | ProtectedMethods | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:539:1:552:3 | ProtectedMethods | bar | calls.rb:542:15:544:7 | bar |
+| calls.rb:539:1:552:3 | ProtectedMethods | baz | calls.rb:546:5:551:7 | baz |
+| calls.rb:539:1:552:3 | ProtectedMethods | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:539:1:552:3 | ProtectedMethods | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:539:1:552:3 | ProtectedMethods | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:539:1:552:3 | ProtectedMethods | create | calls.rb:278:1:286:3 | create |
+| calls.rb:539:1:552:3 | ProtectedMethods | foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:539:1:552:3 | ProtectedMethods | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:539:1:552:3 | ProtectedMethods | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:539:1:552:3 | ProtectedMethods | new | calls.rb:117:5:117:16 | new |
+| calls.rb:539:1:552:3 | ProtectedMethods | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:539:1:552:3 | ProtectedMethods | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:539:1:552:3 | ProtectedMethods | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:539:1:552:3 | ProtectedMethods | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:539:1:552:3 | ProtectedMethods | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | bar | calls.rb:542:15:544:7 | bar |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | baz | calls.rb:559:5:562:7 | baz |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | create | calls.rb:278:1:286:3 | create |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | new | calls.rb:117:5:117:16 | new |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | create | calls.rb:278:1:286:3 | create |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | new | calls.rb:117:5:117:16 | new |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | create | calls.rb:278:1:286:3 | create |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | new | calls.rb:117:5:117:16 | new |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | create | calls.rb:278:1:286:3 | create |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | new | calls.rb:117:5:117:16 | new |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:591:1:602:3 | SingletonA | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:591:1:602:3 | SingletonA | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:591:1:602:3 | SingletonA | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:591:1:602:3 | SingletonA | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:591:1:602:3 | SingletonA | create | calls.rb:278:1:286:3 | create |
+| calls.rb:591:1:602:3 | SingletonA | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:591:1:602:3 | SingletonA | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:591:1:602:3 | SingletonA | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:591:1:602:3 | SingletonA | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:591:1:602:3 | SingletonA | new | calls.rb:117:5:117:16 | new |
+| calls.rb:591:1:602:3 | SingletonA | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:591:1:602:3 | SingletonA | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:591:1:602:3 | SingletonA | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:591:1:602:3 | SingletonA | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:591:1:602:3 | SingletonA | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:604:1:611:3 | SingletonB | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:604:1:611:3 | SingletonB | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:604:1:611:3 | SingletonB | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:604:1:611:3 | SingletonB | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:604:1:611:3 | SingletonB | create | calls.rb:278:1:286:3 | create |
+| calls.rb:604:1:611:3 | SingletonB | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:604:1:611:3 | SingletonB | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:604:1:611:3 | SingletonB | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:604:1:611:3 | SingletonB | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:604:1:611:3 | SingletonB | new | calls.rb:117:5:117:16 | new |
+| calls.rb:604:1:611:3 | SingletonB | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:604:1:611:3 | SingletonB | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:604:1:611:3 | SingletonB | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:604:1:611:3 | SingletonB | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:604:1:611:3 | SingletonB | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:613:1:620:3 | SingletonC | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:613:1:620:3 | SingletonC | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:613:1:620:3 | SingletonC | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:613:1:620:3 | SingletonC | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:613:1:620:3 | SingletonC | create | calls.rb:278:1:286:3 | create |
+| calls.rb:613:1:620:3 | SingletonC | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:613:1:620:3 | SingletonC | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:613:1:620:3 | SingletonC | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:613:1:620:3 | SingletonC | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:613:1:620:3 | SingletonC | new | calls.rb:117:5:117:16 | new |
+| calls.rb:613:1:620:3 | SingletonC | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:613:1:620:3 | SingletonC | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:613:1:620:3 | SingletonC | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:613:1:620:3 | SingletonC | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:613:1:620:3 | SingletonC | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:626:1:632:3 | Included | bar | calls.rb:630:5:631:7 | bar |
+| calls.rb:626:1:632:3 | Included | foo | calls.rb:627:5:629:7 | foo |
+| calls.rb:634:1:639:3 | IncludesIncluded | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:634:1:639:3 | IncludesIncluded | bar | calls.rb:636:5:638:7 | bar |
+| calls.rb:634:1:639:3 | IncludesIncluded | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:634:1:639:3 | IncludesIncluded | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:634:1:639:3 | IncludesIncluded | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:634:1:639:3 | IncludesIncluded | create | calls.rb:278:1:286:3 | create |
+| calls.rb:634:1:639:3 | IncludesIncluded | foo | calls.rb:627:5:629:7 | foo |
+| calls.rb:634:1:639:3 | IncludesIncluded | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:634:1:639:3 | IncludesIncluded | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:634:1:639:3 | IncludesIncluded | new | calls.rb:117:5:117:16 | new |
+| calls.rb:634:1:639:3 | IncludesIncluded | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:634:1:639:3 | IncludesIncluded | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:634:1:639:3 | IncludesIncluded | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:634:1:639:3 | IncludesIncluded | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:634:1:639:3 | IncludesIncluded | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:641:1:645:3 | CustomNew1 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:641:1:645:3 | CustomNew1 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:641:1:645:3 | CustomNew1 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:641:1:645:3 | CustomNew1 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:641:1:645:3 | CustomNew1 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:641:1:645:3 | CustomNew1 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:641:1:645:3 | CustomNew1 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:641:1:645:3 | CustomNew1 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:641:1:645:3 | CustomNew1 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:641:1:645:3 | CustomNew1 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:641:1:645:3 | CustomNew1 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:641:1:645:3 | CustomNew1 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:641:1:645:3 | CustomNew1 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:641:1:645:3 | CustomNew1 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:641:1:645:3 | CustomNew1 | to_s | calls.rb:172:5:173:7 | to_s |
+| calls.rb:649:1:657:3 | CustomNew2 | add_singleton | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:649:1:657:3 | CustomNew2 | call_block | calls.rb:81:1:83:3 | call_block |
+| calls.rb:649:1:657:3 | CustomNew2 | call_instance_m | calls.rb:39:1:41:3 | call_instance_m |
+| calls.rb:649:1:657:3 | CustomNew2 | capture_parameter | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:649:1:657:3 | CustomNew2 | create | calls.rb:278:1:286:3 | create |
+| calls.rb:649:1:657:3 | CustomNew2 | foo | calls.rb:1:1:3:3 | foo |
+| calls.rb:649:1:657:3 | CustomNew2 | foo | calls.rb:85:1:89:3 | foo |
+| calls.rb:649:1:657:3 | CustomNew2 | funny | calls.rb:140:1:142:3 | funny |
+| calls.rb:649:1:657:3 | CustomNew2 | indirect | calls.rb:158:1:160:3 | indirect |
+| calls.rb:649:1:657:3 | CustomNew2 | instance | calls.rb:654:5:656:7 | instance |
+| calls.rb:649:1:657:3 | CustomNew2 | new | calls.rb:117:5:117:16 | new |
+| calls.rb:649:1:657:3 | CustomNew2 | optional_arg | calls.rb:76:1:79:3 | optional_arg |
+| calls.rb:649:1:657:3 | CustomNew2 | pattern_dispatch | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:649:1:657:3 | CustomNew2 | private_on_main | calls.rb:185:1:186:3 | private_on_main |
+| calls.rb:649:1:657:3 | CustomNew2 | puts | calls.rb:102:5:102:30 | puts |
+| calls.rb:649:1:657:3 | CustomNew2 | to_s | calls.rb:172:5:173:7 | to_s |
| file://:0:0:0:0 | Class | include | calls.rb:108:5:110:7 | include |
| file://:0:0:0:0 | Class | module_eval | calls.rb:107:5:107:24 | module_eval |
| file://:0:0:0:0 | Class | new | calls.rb:117:5:117:16 | new |
@@ -864,176 +898,188 @@ enclosingMethod
| calls.rb:327:9:327:26 | self | calls.rb:326:5:328:7 | instance |
| calls.rb:327:14:327:26 | "C1#instance" | calls.rb:326:5:328:7 | instance |
| calls.rb:327:15:327:25 | C1#instance | calls.rb:326:5:328:7 | instance |
-| calls.rb:333:9:333:26 | call to puts | calls.rb:332:5:334:7 | instance |
-| calls.rb:333:9:333:26 | self | calls.rb:332:5:334:7 | instance |
-| calls.rb:333:14:333:26 | "C2#instance" | calls.rb:332:5:334:7 | instance |
-| calls.rb:333:15:333:25 | C2#instance | calls.rb:332:5:334:7 | instance |
-| calls.rb:339:9:339:26 | call to puts | calls.rb:338:5:340:7 | instance |
-| calls.rb:339:9:339:26 | self | calls.rb:338:5:340:7 | instance |
-| calls.rb:339:14:339:26 | "C3#instance" | calls.rb:338:5:340:7 | instance |
-| calls.rb:339:15:339:25 | C3#instance | calls.rb:338:5:340:7 | instance |
-| calls.rb:343:22:343:22 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:343:22:343:22 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:344:5:352:7 | case ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:344:10:344:10 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:345:5:346:18 | when ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:345:10:345:11 | C3 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:345:12:346:18 | then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:346:9:346:9 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:346:9:346:18 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:347:5:348:18 | when ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:347:10:347:11 | C2 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:347:12:348:18 | then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:348:9:348:9 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:348:9:348:18 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:349:5:350:18 | when ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:349:10:349:11 | C1 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:349:12:350:18 | then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:350:9:350:9 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:350:9:350:18 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:351:5:351:8 | else ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:354:5:358:7 | case ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:354:10:354:10 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:355:9:355:29 | in ... then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:355:12:355:13 | C3 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:355:15:355:29 | then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:355:20:355:20 | x | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:355:20:355:29 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:9:356:36 | in ... then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:12:356:13 | C2 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:12:356:19 | ... => ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:18:356:19 | c2 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:21:356:36 | then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:26:356:27 | c2 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:356:26:356:36 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:9:357:36 | in ... then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:12:357:13 | C1 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:12:357:19 | ... => ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:18:357:19 | c1 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:21:357:36 | then ... | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:26:357:27 | c1 | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:357:26:357:36 | call to instance | calls.rb:343:1:359:3 | pattern_dispatch |
-| calls.rb:367:19:367:19 | x | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:367:19:367:19 | x | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:368:5:370:7 | instance | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:368:9:368:9 | x | calls.rb:367:1:371:3 | add_singleton |
-| calls.rb:369:9:369:28 | call to puts | calls.rb:368:5:370:7 | instance |
-| calls.rb:369:9:369:28 | self | calls.rb:368:5:370:7 | instance |
-| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:368:5:370:7 | instance |
-| calls.rb:369:15:369:27 | instance_on x | calls.rb:368:5:370:7 | instance |
-| calls.rb:380:13:380:48 | call to puts | calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:380:13:380:48 | self | calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:380:18:380:48 | "SingletonOverride1#singleton1" | calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:380:19:380:47 | SingletonOverride1#singleton1 | calls.rb:379:9:381:11 | singleton1 |
-| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:383:9:385:11 | call_singleton1 |
-| calls.rb:384:13:384:22 | self | calls.rb:383:9:385:11 | call_singleton1 |
-| calls.rb:388:13:388:16 | self | calls.rb:387:9:389:11 | factory |
-| calls.rb:388:13:388:20 | call to new | calls.rb:387:9:389:11 | factory |
-| calls.rb:388:13:388:30 | call to instance1 | calls.rb:387:9:389:11 | factory |
-| calls.rb:393:9:393:44 | call to puts | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:393:9:393:44 | self | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:393:14:393:44 | "SingletonOverride1#singleton2" | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:393:15:393:43 | SingletonOverride1#singleton2 | calls.rb:392:5:394:7 | singleton2 |
-| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:396:5:398:7 | call_singleton2 |
-| calls.rb:397:9:397:18 | self | calls.rb:396:5:398:7 | call_singleton2 |
-| calls.rb:403:9:403:43 | call to puts | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:403:9:403:43 | self | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:403:14:403:43 | "SingletonOverride1#instance1" | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:403:15:403:42 | SingletonOverride1#instance1 | calls.rb:402:5:404:7 | instance1 |
-| calls.rb:415:13:415:48 | call to puts | calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:415:13:415:48 | self | calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:415:18:415:48 | "SingletonOverride2#singleton1" | calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:415:19:415:47 | SingletonOverride2#singleton1 | calls.rb:414:9:416:11 | singleton1 |
-| calls.rb:420:9:420:44 | call to puts | calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:420:9:420:44 | self | calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:420:14:420:44 | "SingletonOverride2#singleton2" | calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:420:15:420:43 | SingletonOverride2#singleton2 | calls.rb:419:5:421:7 | singleton2 |
-| calls.rb:424:9:424:43 | call to puts | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:424:9:424:43 | self | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:424:14:424:43 | "SingletonOverride2#instance1" | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:424:15:424:42 | SingletonOverride2#instance1 | calls.rb:423:5:425:7 | instance1 |
-| calls.rb:436:13:436:48 | call to puts | calls.rb:435:9:437:11 | m1 |
-| calls.rb:436:13:436:48 | self | calls.rb:435:9:437:11 | m1 |
-| calls.rb:436:18:436:48 | "ConditionalInstanceMethods#m1" | calls.rb:435:9:437:11 | m1 |
-| calls.rb:436:19:436:47 | ConditionalInstanceMethods#m1 | calls.rb:435:9:437:11 | m1 |
-| calls.rb:441:9:441:44 | call to puts | calls.rb:440:5:452:7 | m2 |
-| calls.rb:441:9:441:44 | self | calls.rb:440:5:452:7 | m2 |
-| calls.rb:441:14:441:44 | "ConditionalInstanceMethods#m2" | calls.rb:440:5:452:7 | m2 |
-| calls.rb:441:15:441:43 | ConditionalInstanceMethods#m2 | calls.rb:440:5:452:7 | m2 |
-| calls.rb:443:9:449:11 | m3 | calls.rb:440:5:452:7 | m2 |
-| calls.rb:444:13:444:48 | call to puts | calls.rb:443:9:449:11 | m3 |
-| calls.rb:444:13:444:48 | self | calls.rb:443:9:449:11 | m3 |
-| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m3" | calls.rb:443:9:449:11 | m3 |
-| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m3 | calls.rb:443:9:449:11 | m3 |
-| calls.rb:446:13:448:15 | m4 | calls.rb:443:9:449:11 | m3 |
-| calls.rb:447:17:447:52 | call to puts | calls.rb:446:13:448:15 | m4 |
-| calls.rb:447:17:447:52 | self | calls.rb:446:13:448:15 | m4 |
-| calls.rb:447:22:447:52 | "ConditionalInstanceMethods#m4" | calls.rb:446:13:448:15 | m4 |
-| calls.rb:447:23:447:51 | ConditionalInstanceMethods#m4 | calls.rb:446:13:448:15 | m4 |
-| calls.rb:451:9:451:10 | call to m3 | calls.rb:440:5:452:7 | m2 |
-| calls.rb:451:9:451:10 | self | calls.rb:440:5:452:7 | m2 |
-| calls.rb:457:17:457:40 | call to puts | calls.rb:456:13:458:15 | m5 |
-| calls.rb:457:17:457:40 | self | calls.rb:456:13:458:15 | m5 |
-| calls.rb:457:22:457:40 | "AnonymousClass#m5" | calls.rb:456:13:458:15 | m5 |
-| calls.rb:457:23:457:39 | AnonymousClass#m5 | calls.rb:456:13:458:15 | m5 |
-| calls.rb:473:13:473:22 | call to puts | calls.rb:472:9:474:11 | foo |
-| calls.rb:473:13:473:22 | self | calls.rb:472:9:474:11 | foo |
-| calls.rb:473:18:473:22 | "foo" | calls.rb:472:9:474:11 | foo |
-| calls.rb:473:19:473:21 | foo | calls.rb:472:9:474:11 | foo |
-| calls.rb:479:13:479:22 | call to puts | calls.rb:478:9:480:11 | bar |
-| calls.rb:479:13:479:22 | self | calls.rb:478:9:480:11 | bar |
-| calls.rb:479:18:479:22 | "bar" | calls.rb:478:9:480:11 | bar |
-| calls.rb:479:19:479:21 | bar | calls.rb:478:9:480:11 | bar |
-| calls.rb:498:9:498:46 | call to puts | calls.rb:497:5:499:7 | singleton |
-| calls.rb:498:9:498:46 | self | calls.rb:497:5:499:7 | singleton |
-| calls.rb:498:14:498:46 | "ExtendSingletonMethod#singleton" | calls.rb:497:5:499:7 | singleton |
-| calls.rb:498:15:498:45 | ExtendSingletonMethod#singleton | calls.rb:497:5:499:7 | singleton |
-| calls.rb:527:9:527:42 | call to puts | calls.rb:526:15:528:7 | foo |
-| calls.rb:527:9:527:42 | self | calls.rb:526:15:528:7 | foo |
-| calls.rb:527:14:527:42 | "ProtectedMethodInModule#foo" | calls.rb:526:15:528:7 | foo |
-| calls.rb:527:15:527:41 | ProtectedMethodInModule#foo | calls.rb:526:15:528:7 | foo |
-| calls.rb:535:9:535:35 | call to puts | calls.rb:534:15:536:7 | bar |
-| calls.rb:535:9:535:35 | self | calls.rb:534:15:536:7 | bar |
-| calls.rb:535:14:535:35 | "ProtectedMethods#bar" | calls.rb:534:15:536:7 | bar |
-| calls.rb:535:15:535:34 | ProtectedMethods#bar | calls.rb:534:15:536:7 | bar |
-| calls.rb:539:9:539:11 | call to foo | calls.rb:538:5:543:7 | baz |
-| calls.rb:539:9:539:11 | self | calls.rb:538:5:543:7 | baz |
-| calls.rb:540:9:540:11 | call to bar | calls.rb:538:5:543:7 | baz |
-| calls.rb:540:9:540:11 | self | calls.rb:538:5:543:7 | baz |
-| calls.rb:541:9:541:24 | ProtectedMethods | calls.rb:538:5:543:7 | baz |
-| calls.rb:541:9:541:28 | call to new | calls.rb:538:5:543:7 | baz |
-| calls.rb:541:9:541:32 | call to foo | calls.rb:538:5:543:7 | baz |
-| calls.rb:542:9:542:24 | ProtectedMethods | calls.rb:538:5:543:7 | baz |
-| calls.rb:542:9:542:28 | call to new | calls.rb:538:5:543:7 | baz |
-| calls.rb:542:9:542:32 | call to bar | calls.rb:538:5:543:7 | baz |
-| calls.rb:552:9:552:11 | call to foo | calls.rb:551:5:554:7 | baz |
-| calls.rb:552:9:552:11 | self | calls.rb:551:5:554:7 | baz |
-| calls.rb:553:9:553:27 | ProtectedMethodsSub | calls.rb:551:5:554:7 | baz |
-| calls.rb:553:9:553:31 | call to new | calls.rb:551:5:554:7 | baz |
-| calls.rb:553:9:553:35 | call to foo | calls.rb:551:5:554:7 | baz |
-| calls.rb:572:9:572:17 | call to singleton | calls.rb:571:5:574:7 | mid_method |
-| calls.rb:572:9:572:17 | self | calls.rb:571:5:574:7 | mid_method |
-| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:571:5:574:7 | mid_method |
-| calls.rb:573:9:573:18 | self | calls.rb:571:5:574:7 | mid_method |
-| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:587:5:589:7 | call_singleton1 |
-| calls.rb:588:9:588:18 | self | calls.rb:587:5:589:7 | call_singleton1 |
-| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:591:5:593:7 | call_call_singleton1 |
-| calls.rb:592:9:592:23 | self | calls.rb:591:5:593:7 | call_call_singleton1 |
-| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:600:5:602:7 | call_singleton1 |
-| calls.rb:601:9:601:18 | self | calls.rb:600:5:602:7 | call_singleton1 |
-| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:609:5:611:7 | call_singleton1 |
-| calls.rb:610:9:610:18 | self | calls.rb:609:5:611:7 | call_singleton1 |
-| calls.rb:620:9:620:12 | self | calls.rb:619:5:621:7 | foo |
-| calls.rb:620:9:620:16 | call to bar | calls.rb:619:5:621:7 | foo |
-| calls.rb:629:9:629:13 | super call to bar | calls.rb:628:5:630:7 | bar |
-| calls.rb:635:9:635:10 | C1 | calls.rb:634:5:636:7 | new |
-| calls.rb:635:9:635:14 | call to new | calls.rb:634:5:636:7 | new |
-| calls.rb:643:9:643:12 | self | calls.rb:642:5:644:7 | new |
-| calls.rb:643:9:643:21 | call to allocate | calls.rb:642:5:644:7 | new |
-| calls.rb:647:9:647:34 | call to puts | calls.rb:646:5:648:7 | instance |
-| calls.rb:647:9:647:34 | self | calls.rb:646:5:648:7 | instance |
-| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:646:5:648:7 | instance |
-| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:646:5:648:7 | instance |
+| calls.rb:331:9:331:12 | self | calls.rb:330:5:332:7 | return_self |
+| calls.rb:337:9:337:26 | call to puts | calls.rb:336:5:338:7 | instance |
+| calls.rb:337:9:337:26 | self | calls.rb:336:5:338:7 | instance |
+| calls.rb:337:14:337:26 | "C2#instance" | calls.rb:336:5:338:7 | instance |
+| calls.rb:337:15:337:25 | C2#instance | calls.rb:336:5:338:7 | instance |
+| calls.rb:343:9:343:26 | call to puts | calls.rb:342:5:344:7 | instance |
+| calls.rb:343:9:343:26 | self | calls.rb:342:5:344:7 | instance |
+| calls.rb:343:14:343:26 | "C3#instance" | calls.rb:342:5:344:7 | instance |
+| calls.rb:343:15:343:25 | C3#instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:347:22:347:22 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:347:22:347:22 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:348:5:356:7 | case ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:348:10:348:10 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:349:5:350:18 | when ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:349:10:349:11 | C3 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:349:12:350:18 | then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:350:9:350:9 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:350:9:350:18 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:351:5:352:18 | when ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:351:10:351:11 | C2 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:351:12:352:18 | then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:352:9:352:9 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:352:9:352:18 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:353:5:354:18 | when ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:353:10:353:11 | C1 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:353:12:354:18 | then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:354:9:354:9 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:354:9:354:18 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:355:5:355:8 | else ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:358:5:362:7 | case ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:358:10:358:10 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:359:9:359:29 | in ... then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:359:12:359:13 | C3 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:359:15:359:29 | then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:359:20:359:20 | x | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:359:20:359:29 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:9:360:36 | in ... then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:12:360:13 | C2 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:12:360:19 | ... => ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:18:360:19 | c2 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:21:360:36 | then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:26:360:27 | c2 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:360:26:360:36 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:9:361:36 | in ... then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:12:361:13 | C1 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:12:361:19 | ... => ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:18:361:19 | c1 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:21:361:36 | then ... | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:26:361:27 | c1 | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:361:26:361:36 | call to instance | calls.rb:347:1:363:3 | pattern_dispatch |
+| calls.rb:374:19:374:19 | x | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:374:19:374:19 | x | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:375:5:377:7 | instance | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:375:9:375:9 | x | calls.rb:374:1:378:3 | add_singleton |
+| calls.rb:376:9:376:28 | call to puts | calls.rb:375:5:377:7 | instance |
+| calls.rb:376:9:376:28 | self | calls.rb:375:5:377:7 | instance |
+| calls.rb:376:14:376:28 | "instance_on x" | calls.rb:375:5:377:7 | instance |
+| calls.rb:376:15:376:27 | instance_on x | calls.rb:375:5:377:7 | instance |
+| calls.rb:388:13:388:48 | call to puts | calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:388:13:388:48 | self | calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:388:18:388:48 | "SingletonOverride1#singleton1" | calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:388:19:388:47 | SingletonOverride1#singleton1 | calls.rb:387:9:389:11 | singleton1 |
+| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:391:9:393:11 | call_singleton1 |
+| calls.rb:392:13:392:22 | self | calls.rb:391:9:393:11 | call_singleton1 |
+| calls.rb:396:13:396:16 | self | calls.rb:395:9:397:11 | factory |
+| calls.rb:396:13:396:20 | call to new | calls.rb:395:9:397:11 | factory |
+| calls.rb:396:13:396:30 | call to instance1 | calls.rb:395:9:397:11 | factory |
+| calls.rb:401:9:401:44 | call to puts | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:401:9:401:44 | self | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:401:14:401:44 | "SingletonOverride1#singleton2" | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:401:15:401:43 | SingletonOverride1#singleton2 | calls.rb:400:5:402:7 | singleton2 |
+| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:404:5:406:7 | call_singleton2 |
+| calls.rb:405:9:405:18 | self | calls.rb:404:5:406:7 | call_singleton2 |
+| calls.rb:411:9:411:43 | call to puts | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:411:9:411:43 | self | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:411:14:411:43 | "SingletonOverride1#instance1" | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:411:15:411:42 | SingletonOverride1#instance1 | calls.rb:410:5:412:7 | instance1 |
+| calls.rb:423:13:423:48 | call to puts | calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:423:13:423:48 | self | calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:423:18:423:48 | "SingletonOverride2#singleton1" | calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:423:19:423:47 | SingletonOverride2#singleton1 | calls.rb:422:9:424:11 | singleton1 |
+| calls.rb:428:9:428:44 | call to puts | calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:428:9:428:44 | self | calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:428:14:428:44 | "SingletonOverride2#singleton2" | calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:428:15:428:43 | SingletonOverride2#singleton2 | calls.rb:427:5:429:7 | singleton2 |
+| calls.rb:432:9:432:43 | call to puts | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:432:9:432:43 | self | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:432:14:432:43 | "SingletonOverride2#instance1" | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:432:15:432:42 | SingletonOverride2#instance1 | calls.rb:431:5:433:7 | instance1 |
+| calls.rb:444:13:444:48 | call to puts | calls.rb:443:9:445:11 | m1 |
+| calls.rb:444:13:444:48 | self | calls.rb:443:9:445:11 | m1 |
+| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m1" | calls.rb:443:9:445:11 | m1 |
+| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m1 | calls.rb:443:9:445:11 | m1 |
+| calls.rb:449:9:449:44 | call to puts | calls.rb:448:5:460:7 | m2 |
+| calls.rb:449:9:449:44 | self | calls.rb:448:5:460:7 | m2 |
+| calls.rb:449:14:449:44 | "ConditionalInstanceMethods#m2" | calls.rb:448:5:460:7 | m2 |
+| calls.rb:449:15:449:43 | ConditionalInstanceMethods#m2 | calls.rb:448:5:460:7 | m2 |
+| calls.rb:451:9:457:11 | m3 | calls.rb:448:5:460:7 | m2 |
+| calls.rb:452:13:452:48 | call to puts | calls.rb:451:9:457:11 | m3 |
+| calls.rb:452:13:452:48 | self | calls.rb:451:9:457:11 | m3 |
+| calls.rb:452:18:452:48 | "ConditionalInstanceMethods#m3" | calls.rb:451:9:457:11 | m3 |
+| calls.rb:452:19:452:47 | ConditionalInstanceMethods#m3 | calls.rb:451:9:457:11 | m3 |
+| calls.rb:454:13:456:15 | m4 | calls.rb:451:9:457:11 | m3 |
+| calls.rb:455:17:455:52 | call to puts | calls.rb:454:13:456:15 | m4 |
+| calls.rb:455:17:455:52 | self | calls.rb:454:13:456:15 | m4 |
+| calls.rb:455:22:455:52 | "ConditionalInstanceMethods#m4" | calls.rb:454:13:456:15 | m4 |
+| calls.rb:455:23:455:51 | ConditionalInstanceMethods#m4 | calls.rb:454:13:456:15 | m4 |
+| calls.rb:459:9:459:10 | call to m3 | calls.rb:448:5:460:7 | m2 |
+| calls.rb:459:9:459:10 | self | calls.rb:448:5:460:7 | m2 |
+| calls.rb:465:17:465:40 | call to puts | calls.rb:464:13:466:15 | m5 |
+| calls.rb:465:17:465:40 | self | calls.rb:464:13:466:15 | m5 |
+| calls.rb:465:22:465:40 | "AnonymousClass#m5" | calls.rb:464:13:466:15 | m5 |
+| calls.rb:465:23:465:39 | AnonymousClass#m5 | calls.rb:464:13:466:15 | m5 |
+| calls.rb:481:13:481:22 | call to puts | calls.rb:480:9:482:11 | foo |
+| calls.rb:481:13:481:22 | self | calls.rb:480:9:482:11 | foo |
+| calls.rb:481:18:481:22 | "foo" | calls.rb:480:9:482:11 | foo |
+| calls.rb:481:19:481:21 | foo | calls.rb:480:9:482:11 | foo |
+| calls.rb:487:13:487:22 | call to puts | calls.rb:486:9:488:11 | bar |
+| calls.rb:487:13:487:22 | self | calls.rb:486:9:488:11 | bar |
+| calls.rb:487:18:487:22 | "bar" | calls.rb:486:9:488:11 | bar |
+| calls.rb:487:19:487:21 | bar | calls.rb:486:9:488:11 | bar |
+| calls.rb:506:9:506:46 | call to puts | calls.rb:505:5:507:7 | singleton |
+| calls.rb:506:9:506:46 | self | calls.rb:505:5:507:7 | singleton |
+| calls.rb:506:14:506:46 | "ExtendSingletonMethod#singleton" | calls.rb:505:5:507:7 | singleton |
+| calls.rb:506:15:506:45 | ExtendSingletonMethod#singleton | calls.rb:505:5:507:7 | singleton |
+| calls.rb:535:9:535:42 | call to puts | calls.rb:534:15:536:7 | foo |
+| calls.rb:535:9:535:42 | self | calls.rb:534:15:536:7 | foo |
+| calls.rb:535:14:535:42 | "ProtectedMethodInModule#foo" | calls.rb:534:15:536:7 | foo |
+| calls.rb:535:15:535:41 | ProtectedMethodInModule#foo | calls.rb:534:15:536:7 | foo |
+| calls.rb:543:9:543:35 | call to puts | calls.rb:542:15:544:7 | bar |
+| calls.rb:543:9:543:35 | self | calls.rb:542:15:544:7 | bar |
+| calls.rb:543:14:543:35 | "ProtectedMethods#bar" | calls.rb:542:15:544:7 | bar |
+| calls.rb:543:15:543:34 | ProtectedMethods#bar | calls.rb:542:15:544:7 | bar |
+| calls.rb:547:9:547:11 | call to foo | calls.rb:546:5:551:7 | baz |
+| calls.rb:547:9:547:11 | self | calls.rb:546:5:551:7 | baz |
+| calls.rb:548:9:548:11 | call to bar | calls.rb:546:5:551:7 | baz |
+| calls.rb:548:9:548:11 | self | calls.rb:546:5:551:7 | baz |
+| calls.rb:549:9:549:24 | ProtectedMethods | calls.rb:546:5:551:7 | baz |
+| calls.rb:549:9:549:28 | call to new | calls.rb:546:5:551:7 | baz |
+| calls.rb:549:9:549:32 | call to foo | calls.rb:546:5:551:7 | baz |
+| calls.rb:550:9:550:24 | ProtectedMethods | calls.rb:546:5:551:7 | baz |
+| calls.rb:550:9:550:28 | call to new | calls.rb:546:5:551:7 | baz |
+| calls.rb:550:9:550:32 | call to bar | calls.rb:546:5:551:7 | baz |
+| calls.rb:560:9:560:11 | call to foo | calls.rb:559:5:562:7 | baz |
+| calls.rb:560:9:560:11 | self | calls.rb:559:5:562:7 | baz |
+| calls.rb:561:9:561:27 | ProtectedMethodsSub | calls.rb:559:5:562:7 | baz |
+| calls.rb:561:9:561:31 | call to new | calls.rb:559:5:562:7 | baz |
+| calls.rb:561:9:561:35 | call to foo | calls.rb:559:5:562:7 | baz |
+| calls.rb:580:9:580:17 | call to singleton | calls.rb:579:5:582:7 | mid_method |
+| calls.rb:580:9:580:17 | self | calls.rb:579:5:582:7 | mid_method |
+| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:579:5:582:7 | mid_method |
+| calls.rb:581:9:581:18 | self | calls.rb:579:5:582:7 | mid_method |
+| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:595:5:597:7 | call_singleton1 |
+| calls.rb:596:9:596:18 | self | calls.rb:595:5:597:7 | call_singleton1 |
+| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:599:5:601:7 | call_call_singleton1 |
+| calls.rb:600:9:600:23 | self | calls.rb:599:5:601:7 | call_call_singleton1 |
+| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:608:5:610:7 | call_singleton1 |
+| calls.rb:609:9:609:18 | self | calls.rb:608:5:610:7 | call_singleton1 |
+| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:617:5:619:7 | call_singleton1 |
+| calls.rb:618:9:618:18 | self | calls.rb:617:5:619:7 | call_singleton1 |
+| calls.rb:628:9:628:12 | self | calls.rb:627:5:629:7 | foo |
+| calls.rb:628:9:628:16 | call to bar | calls.rb:627:5:629:7 | foo |
+| calls.rb:637:9:637:13 | super call to bar | calls.rb:636:5:638:7 | bar |
+| calls.rb:643:9:643:10 | C1 | calls.rb:642:5:644:7 | new |
+| calls.rb:643:9:643:14 | call to new | calls.rb:642:5:644:7 | new |
+| calls.rb:651:9:651:12 | self | calls.rb:650:5:652:7 | new |
+| calls.rb:651:9:651:21 | call to allocate | calls.rb:650:5:652:7 | new |
+| calls.rb:655:9:655:34 | call to puts | calls.rb:654:5:656:7 | instance |
+| calls.rb:655:9:655:34 | self | calls.rb:654:5:656:7 | instance |
+| calls.rb:655:14:655:34 | "CustomNew2#instance" | calls.rb:654:5:656:7 | instance |
+| calls.rb:655:15:655:33 | CustomNew2#instance | calls.rb:654:5:656:7 | instance |
+| calls.rb:661:23:661:23 | x | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:661:23:661:23 | x | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:5:662:11 | Array | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:5:662:11 | [...] | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:5:662:11 | call to [] | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:5:664:7 | call to each | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:6:662:6 | 0 | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:8:662:8 | 1 | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:10:662:10 | 2 | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:662:18:664:7 | do ... end | calls.rb:661:1:665:3 | capture_parameter |
+| calls.rb:663:9:663:9 | x | calls.rb:661:1:665:3 | capture_parameter |
| hello.rb:3:9:3:22 | return | hello.rb:2:5:4:7 | hello |
| hello.rb:3:16:3:22 | "hello" | hello.rb:2:5:4:7 | hello |
| hello.rb:3:17:3:21 | hello | hello.rb:2:5:4:7 | hello |
diff --git a/ruby/ql/test/library-tests/modules/modules.expected b/ruby/ql/test/library-tests/modules/modules.expected
index e138f5ce4c3..0b98c128eb0 100644
--- a/ruby/ql/test/library-tests/modules/modules.expected
+++ b/ruby/ql/test/library-tests/modules/modules.expected
@@ -14,28 +14,28 @@ getModule
| calls.rb:176:1:179:3 | B |
| calls.rb:190:1:226:3 | Singletons |
| calls.rb:310:1:321:3 | SelfNew |
-| calls.rb:325:1:329:3 | C1 |
-| calls.rb:331:1:335:3 | C2 |
-| calls.rb:337:1:341:3 | C3 |
-| calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:506:1:508:3 | ExtendSingletonMethod2 |
-| calls.rb:512:1:513:3 | ExtendSingletonMethod3 |
-| calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub |
-| calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:618:1:624:3 | Included |
-| calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:633:1:637:3 | CustomNew1 |
-| calls.rb:641:1:649:3 | CustomNew2 |
+| calls.rb:325:1:333:3 | C1 |
+| calls.rb:335:1:339:3 | C2 |
+| calls.rb:341:1:345:3 | C3 |
+| calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:514:1:516:3 | ExtendSingletonMethod2 |
+| calls.rb:520:1:521:3 | ExtendSingletonMethod3 |
+| calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub |
+| calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:626:1:632:3 | Included |
+| calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:641:1:645:3 | CustomNew1 |
+| calls.rb:649:1:657:3 | CustomNew2 |
| file://:0:0:0:0 | BasicObject |
| file://:0:0:0:0 | Class |
| file://:0:0:0:0 | Complex |
@@ -111,7 +111,7 @@ getADeclaration
| calls.rb:96:1:98:3 | String | calls.rb:96:1:98:3 | String |
| calls.rb:100:1:103:3 | Kernel | calls.rb:100:1:103:3 | Kernel |
| calls.rb:105:1:113:3 | Module | calls.rb:105:1:113:3 | Module |
-| calls.rb:115:1:118:3 | Object | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:115:1:118:3 | Object | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:115:1:118:3 | Object | calls.rb:115:1:118:3 | Object |
| calls.rb:115:1:118:3 | Object | hello.rb:1:1:22:3 | hello.rb |
| calls.rb:115:1:118:3 | Object | instance_fields.rb:1:1:29:4 | instance_fields.rb |
@@ -131,28 +131,28 @@ getADeclaration
| calls.rb:176:1:179:3 | B | instance_fields.rb:16:1:25:3 | B |
| calls.rb:190:1:226:3 | Singletons | calls.rb:190:1:226:3 | Singletons |
| calls.rb:310:1:321:3 | SelfNew | calls.rb:310:1:321:3 | SelfNew |
-| calls.rb:325:1:329:3 | C1 | calls.rb:325:1:329:3 | C1 |
-| calls.rb:331:1:335:3 | C2 | calls.rb:331:1:335:3 | C2 |
-| calls.rb:337:1:341:3 | C3 | calls.rb:337:1:341:3 | C3 |
-| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:496:1:502:3 | ExtendSingletonMethod | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | calls.rb:506:1:508:3 | ExtendSingletonMethod2 |
-| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | calls.rb:512:1:513:3 | ExtendSingletonMethod3 |
-| calls.rb:525:1:529:3 | ProtectedMethodInModule | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:564:1:567:3 | SingletonUpCall_Base |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:576:1:581:3 | SingletonUpCall_SubSub |
-| calls.rb:583:1:594:3 | SingletonA | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:596:1:603:3 | SingletonB | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:605:1:612:3 | SingletonC | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:618:1:624:3 | Included | calls.rb:618:1:624:3 | Included |
-| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:633:1:637:3 | CustomNew1 |
-| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:641:1:649:3 | CustomNew2 |
+| calls.rb:325:1:333:3 | C1 | calls.rb:325:1:333:3 | C1 |
+| calls.rb:335:1:339:3 | C2 | calls.rb:335:1:339:3 | C2 |
+| calls.rb:341:1:345:3 | C3 | calls.rb:341:1:345:3 | C3 |
+| calls.rb:385:1:413:3 | SingletonOverride1 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:420:1:434:3 | SingletonOverride2 | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:504:1:510:3 | ExtendSingletonMethod | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | calls.rb:514:1:516:3 | ExtendSingletonMethod2 |
+| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | calls.rb:520:1:521:3 | ExtendSingletonMethod3 |
+| calls.rb:533:1:537:3 | ProtectedMethodInModule | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | calls.rb:572:1:575:3 | SingletonUpCall_Base |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | calls.rb:584:1:589:3 | SingletonUpCall_SubSub |
+| calls.rb:591:1:602:3 | SingletonA | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:604:1:611:3 | SingletonB | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:613:1:620:3 | SingletonC | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:626:1:632:3 | Included | calls.rb:626:1:632:3 | Included |
+| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:641:1:645:3 | CustomNew1 | calls.rb:641:1:645:3 | CustomNew1 |
+| calls.rb:649:1:657:3 | CustomNew2 | calls.rb:649:1:657:3 | CustomNew2 |
| hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:8:3 | EnglishWords |
| hello.rb:11:1:16:3 | Greeting | hello.rb:11:1:16:3 | Greeting |
| hello.rb:18:1:22:3 | HelloWorld | hello.rb:18:1:22:3 | HelloWorld |
@@ -221,23 +221,23 @@ getSuperClass
| calls.rb:176:1:179:3 | B | calls.rb:165:1:169:3 | S |
| calls.rb:190:1:226:3 | Singletons | calls.rb:115:1:118:3 | Object |
| calls.rb:310:1:321:3 | SelfNew | calls.rb:115:1:118:3 | Object |
-| calls.rb:325:1:329:3 | C1 | calls.rb:115:1:118:3 | Object |
-| calls.rb:331:1:335:3 | C2 | calls.rb:325:1:329:3 | C1 |
-| calls.rb:337:1:341:3 | C3 | calls.rb:331:1:335:3 | C2 |
-| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:115:1:118:3 | Object |
-| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:115:1:118:3 | Object |
-| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:115:1:118:3 | Object |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:115:1:118:3 | Object |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:564:1:567:3 | SingletonUpCall_Base |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:583:1:594:3 | SingletonA | calls.rb:115:1:118:3 | Object |
-| calls.rb:596:1:603:3 | SingletonB | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:605:1:612:3 | SingletonC | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:115:1:118:3 | Object |
-| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:115:1:118:3 | Object |
-| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:115:1:118:3 | Object |
+| calls.rb:325:1:333:3 | C1 | calls.rb:115:1:118:3 | Object |
+| calls.rb:335:1:339:3 | C2 | calls.rb:325:1:333:3 | C1 |
+| calls.rb:341:1:345:3 | C3 | calls.rb:335:1:339:3 | C2 |
+| calls.rb:385:1:413:3 | SingletonOverride1 | calls.rb:115:1:118:3 | Object |
+| calls.rb:420:1:434:3 | SingletonOverride2 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | calls.rb:115:1:118:3 | Object |
+| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:115:1:118:3 | Object |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | calls.rb:115:1:118:3 | Object |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | calls.rb:572:1:575:3 | SingletonUpCall_Base |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:591:1:602:3 | SingletonA | calls.rb:115:1:118:3 | Object |
+| calls.rb:604:1:611:3 | SingletonB | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:613:1:620:3 | SingletonC | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:115:1:118:3 | Object |
+| calls.rb:641:1:645:3 | CustomNew1 | calls.rb:115:1:118:3 | Object |
+| calls.rb:649:1:657:3 | CustomNew2 | calls.rb:115:1:118:3 | Object |
| file://:0:0:0:0 | Class | calls.rb:105:1:113:3 | Module |
| file://:0:0:0:0 | Complex | file://:0:0:0:0 | Numeric |
| file://:0:0:0:0 | FalseClass | calls.rb:115:1:118:3 | Object |
@@ -278,8 +278,8 @@ getAPrependedModule
getAnIncludedModule
| calls.rb:43:1:58:3 | C | calls.rb:21:1:34:3 | M |
| calls.rb:115:1:118:3 | Object | calls.rb:100:1:103:3 | Kernel |
-| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:618:1:624:3 | Included |
+| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:626:1:632:3 | Included |
| hello.rb:11:1:16:3 | Greeting | hello.rb:1:1:8:3 | EnglishWords |
| modules.rb:88:1:93:3 | IncludeTest | modules.rb:63:1:81:3 | Test |
| modules.rb:95:1:99:3 | IncludeTest2 | modules.rb:63:1:81:3 | Test |
@@ -316,76 +316,79 @@ resolveConstantReadAccess
| calls.rb:302:10:302:19 | Singletons | Singletons |
| calls.rb:308:1:308:10 | Singletons | Singletons |
| calls.rb:323:1:323:7 | SelfNew | SelfNew |
-| calls.rb:331:12:331:13 | C1 | C1 |
-| calls.rb:337:12:337:13 | C2 | C2 |
-| calls.rb:345:10:345:11 | C3 | C3 |
-| calls.rb:347:10:347:11 | C2 | C2 |
-| calls.rb:349:10:349:11 | C1 | C1 |
-| calls.rb:355:12:355:13 | C3 | C3 |
-| calls.rb:356:12:356:13 | C2 | C2 |
-| calls.rb:357:12:357:13 | C1 | C1 |
-| calls.rb:361:6:361:7 | C1 | C1 |
-| calls.rb:363:19:363:20 | C1 | C1 |
-| calls.rb:364:19:364:20 | C2 | C2 |
-| calls.rb:365:19:365:20 | C3 | C3 |
-| calls.rb:373:6:373:7 | C1 | C1 |
-| calls.rb:407:1:407:18 | SingletonOverride1 | SingletonOverride1 |
-| calls.rb:408:1:408:18 | SingletonOverride1 | SingletonOverride1 |
-| calls.rb:409:1:409:18 | SingletonOverride1 | SingletonOverride1 |
-| calls.rb:410:1:410:18 | SingletonOverride1 | SingletonOverride1 |
-| calls.rb:412:28:412:45 | SingletonOverride1 | SingletonOverride1 |
-| calls.rb:428:1:428:18 | SingletonOverride2 | SingletonOverride2 |
-| calls.rb:429:1:429:18 | SingletonOverride2 | SingletonOverride2 |
-| calls.rb:430:1:430:18 | SingletonOverride2 | SingletonOverride2 |
-| calls.rb:431:1:431:18 | SingletonOverride2 | SingletonOverride2 |
-| calls.rb:455:9:455:13 | Class | Class |
-| calls.rb:463:1:463:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:464:1:464:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:465:1:465:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:466:1:466:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:467:1:467:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:468:1:468:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:470:27:470:31 | Class | Class |
-| calls.rb:471:5:471:11 | Array | Array |
-| calls.rb:477:5:477:9 | Class | Class |
-| calls.rb:483:5:483:11 | Array | Array |
-| calls.rb:490:1:490:23 | EsotericInstanceMethods | EsotericInstanceMethods |
-| calls.rb:491:1:491:23 | EsotericInstanceMethods | EsotericInstanceMethods |
-| calls.rb:492:1:492:23 | EsotericInstanceMethods | EsotericInstanceMethods |
-| calls.rb:493:1:493:23 | EsotericInstanceMethods | EsotericInstanceMethods |
-| calls.rb:494:1:494:23 | EsotericInstanceMethods | EsotericInstanceMethods |
-| calls.rb:504:1:504:21 | ExtendSingletonMethod | ExtendSingletonMethod |
-| calls.rb:507:12:507:32 | ExtendSingletonMethod | ExtendSingletonMethod |
-| calls.rb:510:1:510:22 | ExtendSingletonMethod2 | ExtendSingletonMethod2 |
-| calls.rb:515:1:515:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 |
-| calls.rb:515:31:515:51 | ExtendSingletonMethod | ExtendSingletonMethod |
-| calls.rb:517:1:517:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 |
-| calls.rb:521:12:521:32 | ExtendSingletonMethod | ExtendSingletonMethod |
-| calls.rb:532:13:532:35 | ProtectedMethodInModule | ProtectedMethodInModule |
-| calls.rb:541:9:541:24 | ProtectedMethods | ProtectedMethods |
-| calls.rb:542:9:542:24 | ProtectedMethods | ProtectedMethods |
-| calls.rb:546:1:546:16 | ProtectedMethods | ProtectedMethods |
-| calls.rb:547:1:547:16 | ProtectedMethods | ProtectedMethods |
-| calls.rb:548:1:548:16 | ProtectedMethods | ProtectedMethods |
-| calls.rb:550:29:550:44 | ProtectedMethods | ProtectedMethods |
-| calls.rb:553:9:553:27 | ProtectedMethodsSub | ProtectedMethodsSub |
-| calls.rb:557:1:557:19 | ProtectedMethodsSub | ProtectedMethodsSub |
-| calls.rb:558:1:558:19 | ProtectedMethodsSub | ProtectedMethodsSub |
-| calls.rb:559:1:559:19 | ProtectedMethodsSub | ProtectedMethodsSub |
-| calls.rb:561:1:561:7 | Array | Array |
-| calls.rb:561:2:561:2 | C | C |
-| calls.rb:562:1:562:13 | Array | Array |
-| calls.rb:568:29:568:48 | SingletonUpCall_Base | SingletonUpCall_Base |
-| calls.rb:576:32:576:50 | SingletonUpCall_Sub | SingletonUpCall_Sub |
-| calls.rb:596:20:596:29 | SingletonA | SingletonA |
-| calls.rb:605:20:605:29 | SingletonA | SingletonA |
-| calls.rb:614:1:614:10 | SingletonA | SingletonA |
-| calls.rb:615:1:615:10 | SingletonB | SingletonB |
-| calls.rb:616:1:616:10 | SingletonC | SingletonC |
-| calls.rb:627:13:627:20 | Included | Included |
-| calls.rb:635:9:635:10 | C1 | C1 |
-| calls.rb:639:1:639:10 | CustomNew1 | CustomNew1 |
-| calls.rb:651:1:651:10 | CustomNew2 | CustomNew2 |
+| calls.rb:335:12:335:13 | C1 | C1 |
+| calls.rb:341:12:341:13 | C2 | C2 |
+| calls.rb:349:10:349:11 | C3 | C3 |
+| calls.rb:351:10:351:11 | C2 | C2 |
+| calls.rb:353:10:353:11 | C1 | C1 |
+| calls.rb:359:12:359:13 | C3 | C3 |
+| calls.rb:360:12:360:13 | C2 | C2 |
+| calls.rb:361:12:361:13 | C1 | C1 |
+| calls.rb:365:6:365:7 | C1 | C1 |
+| calls.rb:368:19:368:20 | C1 | C1 |
+| calls.rb:369:19:369:20 | C2 | C2 |
+| calls.rb:370:19:370:20 | C3 | C3 |
+| calls.rb:372:1:372:2 | C3 | C3 |
+| calls.rb:380:6:380:7 | C1 | C1 |
+| calls.rb:415:1:415:18 | SingletonOverride1 | SingletonOverride1 |
+| calls.rb:416:1:416:18 | SingletonOverride1 | SingletonOverride1 |
+| calls.rb:417:1:417:18 | SingletonOverride1 | SingletonOverride1 |
+| calls.rb:418:1:418:18 | SingletonOverride1 | SingletonOverride1 |
+| calls.rb:420:28:420:45 | SingletonOverride1 | SingletonOverride1 |
+| calls.rb:436:1:436:18 | SingletonOverride2 | SingletonOverride2 |
+| calls.rb:437:1:437:18 | SingletonOverride2 | SingletonOverride2 |
+| calls.rb:438:1:438:18 | SingletonOverride2 | SingletonOverride2 |
+| calls.rb:439:1:439:18 | SingletonOverride2 | SingletonOverride2 |
+| calls.rb:463:9:463:13 | Class | Class |
+| calls.rb:471:1:471:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:472:1:472:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:473:1:473:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:474:1:474:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:475:1:475:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:476:1:476:26 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:478:27:478:31 | Class | Class |
+| calls.rb:479:5:479:11 | Array | Array |
+| calls.rb:485:5:485:9 | Class | Class |
+| calls.rb:491:5:491:11 | Array | Array |
+| calls.rb:498:1:498:23 | EsotericInstanceMethods | EsotericInstanceMethods |
+| calls.rb:499:1:499:23 | EsotericInstanceMethods | EsotericInstanceMethods |
+| calls.rb:500:1:500:23 | EsotericInstanceMethods | EsotericInstanceMethods |
+| calls.rb:501:1:501:23 | EsotericInstanceMethods | EsotericInstanceMethods |
+| calls.rb:502:1:502:23 | EsotericInstanceMethods | EsotericInstanceMethods |
+| calls.rb:512:1:512:21 | ExtendSingletonMethod | ExtendSingletonMethod |
+| calls.rb:515:12:515:32 | ExtendSingletonMethod | ExtendSingletonMethod |
+| calls.rb:518:1:518:22 | ExtendSingletonMethod2 | ExtendSingletonMethod2 |
+| calls.rb:523:1:523:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 |
+| calls.rb:523:31:523:51 | ExtendSingletonMethod | ExtendSingletonMethod |
+| calls.rb:525:1:525:22 | ExtendSingletonMethod3 | ExtendSingletonMethod3 |
+| calls.rb:529:12:529:32 | ExtendSingletonMethod | ExtendSingletonMethod |
+| calls.rb:540:13:540:35 | ProtectedMethodInModule | ProtectedMethodInModule |
+| calls.rb:549:9:549:24 | ProtectedMethods | ProtectedMethods |
+| calls.rb:550:9:550:24 | ProtectedMethods | ProtectedMethods |
+| calls.rb:554:1:554:16 | ProtectedMethods | ProtectedMethods |
+| calls.rb:555:1:555:16 | ProtectedMethods | ProtectedMethods |
+| calls.rb:556:1:556:16 | ProtectedMethods | ProtectedMethods |
+| calls.rb:558:29:558:44 | ProtectedMethods | ProtectedMethods |
+| calls.rb:561:9:561:27 | ProtectedMethodsSub | ProtectedMethodsSub |
+| calls.rb:565:1:565:19 | ProtectedMethodsSub | ProtectedMethodsSub |
+| calls.rb:566:1:566:19 | ProtectedMethodsSub | ProtectedMethodsSub |
+| calls.rb:567:1:567:19 | ProtectedMethodsSub | ProtectedMethodsSub |
+| calls.rb:569:1:569:7 | Array | Array |
+| calls.rb:569:2:569:2 | C | C |
+| calls.rb:570:1:570:13 | Array | Array |
+| calls.rb:576:29:576:48 | SingletonUpCall_Base | SingletonUpCall_Base |
+| calls.rb:584:32:584:50 | SingletonUpCall_Sub | SingletonUpCall_Sub |
+| calls.rb:604:20:604:29 | SingletonA | SingletonA |
+| calls.rb:613:20:613:29 | SingletonA | SingletonA |
+| calls.rb:622:1:622:10 | SingletonA | SingletonA |
+| calls.rb:623:1:623:10 | SingletonB | SingletonB |
+| calls.rb:624:1:624:10 | SingletonC | SingletonC |
+| calls.rb:635:13:635:20 | Included | Included |
+| calls.rb:643:9:643:10 | C1 | C1 |
+| calls.rb:647:1:647:10 | CustomNew1 | CustomNew1 |
+| calls.rb:659:1:659:10 | CustomNew2 | CustomNew2 |
+| calls.rb:662:5:662:11 | Array | Array |
+| calls.rb:667:20:667:21 | C1 | C1 |
| hello.rb:12:13:12:24 | EnglishWords | EnglishWords |
| hello.rb:18:20:18:27 | Greeting | Greeting |
| instance_fields.rb:4:22:4:31 | A_target | A_target |
@@ -469,29 +472,29 @@ resolveConstantWriteAccess
| calls.rb:176:1:179:3 | B | B |
| calls.rb:190:1:226:3 | Singletons | Singletons |
| calls.rb:310:1:321:3 | SelfNew | SelfNew |
-| calls.rb:325:1:329:3 | C1 | C1 |
-| calls.rb:331:1:335:3 | C2 | C2 |
-| calls.rb:337:1:341:3 | C3 | C3 |
-| calls.rb:377:1:405:3 | SingletonOverride1 | SingletonOverride1 |
-| calls.rb:412:1:426:3 | SingletonOverride2 | SingletonOverride2 |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | ConditionalInstanceMethods |
-| calls.rb:470:1:470:23 | EsotericInstanceMethods | EsotericInstanceMethods |
-| calls.rb:496:1:502:3 | ExtendSingletonMethod | ExtendSingletonMethod |
-| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | ExtendSingletonMethod2 |
-| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | ExtendSingletonMethod3 |
-| calls.rb:525:1:529:3 | ProtectedMethodInModule | ProtectedMethodInModule |
-| calls.rb:531:1:544:3 | ProtectedMethods | ProtectedMethods |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | ProtectedMethodsSub |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | SingletonUpCall_Base |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | SingletonUpCall_Sub |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | SingletonUpCall_SubSub |
-| calls.rb:583:1:594:3 | SingletonA | SingletonA |
-| calls.rb:596:1:603:3 | SingletonB | SingletonB |
-| calls.rb:605:1:612:3 | SingletonC | SingletonC |
-| calls.rb:618:1:624:3 | Included | Included |
-| calls.rb:626:1:631:3 | IncludesIncluded | IncludesIncluded |
-| calls.rb:633:1:637:3 | CustomNew1 | CustomNew1 |
-| calls.rb:641:1:649:3 | CustomNew2 | CustomNew2 |
+| calls.rb:325:1:333:3 | C1 | C1 |
+| calls.rb:335:1:339:3 | C2 | C2 |
+| calls.rb:341:1:345:3 | C3 | C3 |
+| calls.rb:385:1:413:3 | SingletonOverride1 | SingletonOverride1 |
+| calls.rb:420:1:434:3 | SingletonOverride2 | SingletonOverride2 |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | ConditionalInstanceMethods |
+| calls.rb:478:1:478:23 | EsotericInstanceMethods | EsotericInstanceMethods |
+| calls.rb:504:1:510:3 | ExtendSingletonMethod | ExtendSingletonMethod |
+| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | ExtendSingletonMethod2 |
+| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | ExtendSingletonMethod3 |
+| calls.rb:533:1:537:3 | ProtectedMethodInModule | ProtectedMethodInModule |
+| calls.rb:539:1:552:3 | ProtectedMethods | ProtectedMethods |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | ProtectedMethodsSub |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | SingletonUpCall_Base |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | SingletonUpCall_Sub |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | SingletonUpCall_SubSub |
+| calls.rb:591:1:602:3 | SingletonA | SingletonA |
+| calls.rb:604:1:611:3 | SingletonB | SingletonB |
+| calls.rb:613:1:620:3 | SingletonC | SingletonC |
+| calls.rb:626:1:632:3 | Included | Included |
+| calls.rb:634:1:639:3 | IncludesIncluded | IncludesIncluded |
+| calls.rb:641:1:645:3 | CustomNew1 | CustomNew1 |
+| calls.rb:649:1:657:3 | CustomNew2 | CustomNew2 |
| hello.rb:1:1:8:3 | EnglishWords | EnglishWords |
| hello.rb:11:1:16:3 | Greeting | Greeting |
| hello.rb:18:1:22:3 | HelloWorld | HelloWorld |
@@ -561,32 +564,32 @@ resolveConstantWriteAccess
| unresolved_subclass.rb:17:1:18:3 | Subclass2 | UnresolvedNamespace::X1::X2::X3::Subclass2 |
| unresolved_subclass.rb:21:1:22:3 | A | UnresolvedNamespace::X1::X2::X3::A |
enclosingModule
-| calls.rb:1:1:3:3 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:2:5:2:14 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:2:11:2:13 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:5:1:5:3 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:7:1:9:3 | bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:7:5:7:8 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:8:5:8:15 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:11:1:11:4 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:13:1:15:3 | bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:13:5:13:8 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:14:5:14:15 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:17:1:17:4 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:19:1:19:4 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:21:1:34:3 | M | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:1:1:3:3 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:2:5:2:14 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:2:10:2:14 | "foo" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:2:11:2:13 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:5:1:5:3 | call to foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:5:1:5:3 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:7:1:9:3 | bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:7:5:7:8 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:8:5:8:15 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:8:5:8:15 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:8:10:8:15 | "bar1" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:8:11:8:14 | bar1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:11:1:11:4 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:11:1:11:8 | call to bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:13:1:15:3 | bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:13:5:13:8 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:14:5:14:15 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:14:5:14:15 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:14:10:14:15 | "bar2" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:14:11:14:14 | bar2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:17:1:17:4 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:17:1:17:8 | call to bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:19:1:19:4 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:19:1:19:8 | call to foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:21:1:34:3 | M | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:22:5:24:7 | instance_m | calls.rb:21:1:34:3 | M |
| calls.rb:23:9:23:19 | call to singleton_m | calls.rb:21:1:34:3 | M |
| calls.rb:23:9:23:19 | self | calls.rb:21:1:34:3 | M |
@@ -602,14 +605,14 @@ enclosingModule
| calls.rb:32:5:32:15 | self | calls.rb:21:1:34:3 | M |
| calls.rb:33:5:33:8 | self | calls.rb:21:1:34:3 | M |
| calls.rb:33:5:33:20 | call to singleton_m | calls.rb:21:1:34:3 | M |
-| calls.rb:36:1:36:1 | M | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:37:1:37:1 | M | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:40:5:40:14 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:43:1:58:3 | C | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:36:1:36:1 | M | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:36:1:36:12 | call to instance_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:37:1:37:1 | M | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:37:1:37:13 | call to singleton_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:39:1:41:3 | call_instance_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:40:5:40:14 | call to instance_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:40:5:40:14 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:43:1:58:3 | C | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:44:5:44:13 | call to include | calls.rb:43:1:58:3 | C |
| calls.rb:44:5:44:13 | self | calls.rb:43:1:58:3 | C |
| calls.rb:44:13:44:13 | M | calls.rb:43:1:58:3 | C |
@@ -630,66 +633,66 @@ enclosingModule
| calls.rb:55:9:55:19 | self | calls.rb:43:1:58:3 | C |
| calls.rb:56:9:56:12 | self | calls.rb:43:1:58:3 | C |
| calls.rb:56:9:56:24 | call to singleton_m | calls.rb:43:1:58:3 | C |
-| calls.rb:60:1:60:1 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:60:5:60:5 | C | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:61:1:61:1 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:62:1:62:1 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:63:1:63:1 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:65:1:69:3 | D | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:65:11:65:11 | C | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:60:1:60:1 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:60:1:60:9 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:60:5:60:5 | C | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:60:5:60:9 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:61:1:61:1 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:61:1:61:5 | call to baz | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:62:1:62:1 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:62:1:62:13 | call to singleton_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:63:1:63:1 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:63:1:63:12 | call to instance_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:65:1:69:3 | D | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:65:11:65:11 | C | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:66:5:68:7 | baz | calls.rb:65:1:69:3 | D |
| calls.rb:67:9:67:13 | super call to baz | calls.rb:65:1:69:3 | D |
-| calls.rb:71:1:71:1 | d | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:71:5:71:5 | D | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:72:1:72:1 | d | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:73:1:73:1 | d | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:74:1:74:1 | d | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:18:76:18 | a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:18:76:18 | a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:25:76:25 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:25:76:25 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:77:5:77:5 | a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:78:5:78:5 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:85:1:89:3 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:86:5:86:7 | var | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:87:5:87:7 | var | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:5:88:29 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:19:88:19 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:19:88:19 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:22:88:24 | var | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:88:26:88:26 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:71:1:71:1 | d | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:71:1:71:9 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:71:5:71:5 | D | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:71:5:71:9 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:72:1:72:1 | d | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:72:1:72:5 | call to baz | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:73:1:73:1 | d | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:73:1:73:13 | call to singleton_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:74:1:74:1 | d | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:74:1:74:12 | call to instance_m | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:1:79:3 | optional_arg | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:18:76:18 | a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:18:76:18 | a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:22:76:22 | 4 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:25:76:25 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:25:76:25 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:76:28:76:28 | 5 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:77:5:77:5 | a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:77:5:77:16 | call to bit_length | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:78:5:78:5 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:78:5:78:16 | call to bit_length | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:81:1:83:3 | call_block | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:82:5:82:11 | yield ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:82:11:82:11 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:85:1:89:3 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:86:5:86:7 | var | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:86:5:86:18 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:86:11:86:14 | Hash | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:86:11:86:18 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:87:5:87:7 | var | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:87:5:87:10 | ...[...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:87:9:87:9 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:5:88:29 | call to call_block | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:5:88:29 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:16:88:29 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:19:88:19 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:19:88:19 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:22:88:24 | var | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:22:88:27 | ...[...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:88:26:88:26 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:91:1:94:3 | Integer | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:92:5:92:23 | bit_length | calls.rb:91:1:94:3 | Integer |
| calls.rb:93:5:93:16 | abs | calls.rb:91:1:94:3 | Integer |
-| calls.rb:96:1:98:3 | String | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:96:1:98:3 | String | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:97:5:97:23 | capitalize | calls.rb:96:1:98:3 | String |
-| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:100:1:103:3 | Kernel | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:101:5:101:25 | alias ... | calls.rb:100:1:103:3 | Kernel |
| calls.rb:101:11:101:19 | :old_puts | calls.rb:100:1:103:3 | Kernel |
| calls.rb:101:11:101:19 | old_puts | calls.rb:100:1:103:3 | Kernel |
@@ -701,7 +704,7 @@ enclosingModule
| calls.rb:102:17:102:26 | call to old_puts | calls.rb:100:1:103:3 | Kernel |
| calls.rb:102:17:102:26 | self | calls.rb:100:1:103:3 | Kernel |
| calls.rb:102:26:102:26 | x | calls.rb:100:1:103:3 | Kernel |
-| calls.rb:105:1:113:3 | Module | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:105:1:113:3 | Module | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:106:5:106:31 | alias ... | calls.rb:105:1:113:3 | Module |
| calls.rb:106:11:106:22 | :old_include | calls.rb:105:1:113:3 | Module |
| calls.rb:106:11:106:22 | old_include | calls.rb:105:1:113:3 | Module |
@@ -716,13 +719,13 @@ enclosingModule
| calls.rb:109:21:109:21 | x | calls.rb:105:1:113:3 | Module |
| calls.rb:111:5:111:20 | prepend | calls.rb:105:1:113:3 | Module |
| calls.rb:112:5:112:20 | private | calls.rb:105:1:113:3 | Module |
-| calls.rb:115:1:118:3 | Object | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:115:16:115:21 | Module | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:115:1:118:3 | Object | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:115:16:115:21 | Module | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:116:5:116:18 | call to include | calls.rb:115:1:118:3 | Object |
| calls.rb:116:5:116:18 | self | calls.rb:115:1:118:3 | Object |
| calls.rb:116:13:116:18 | Kernel | calls.rb:115:1:118:3 | Object |
| calls.rb:117:5:117:16 | new | calls.rb:115:1:118:3 | Object |
-| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:120:1:123:3 | Hash | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:121:5:121:25 | alias ... | calls.rb:120:1:123:3 | Hash |
| calls.rb:121:11:121:21 | :old_lookup | calls.rb:120:1:123:3 | Hash |
| calls.rb:121:11:121:21 | old_lookup | calls.rb:120:1:123:3 | Hash |
@@ -734,7 +737,7 @@ enclosingModule
| calls.rb:122:15:122:27 | call to old_lookup | calls.rb:120:1:123:3 | Hash |
| calls.rb:122:15:122:27 | self | calls.rb:120:1:123:3 | Hash |
| calls.rb:122:26:122:26 | x | calls.rb:120:1:123:3 | Hash |
-| calls.rb:125:1:138:3 | Array | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:125:1:138:3 | Array | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:126:3:126:23 | alias ... | calls.rb:125:1:138:3 | Array |
| calls.rb:126:9:126:19 | :old_lookup | calls.rb:125:1:138:3 | Array |
| calls.rb:126:9:126:19 | old_lookup | calls.rb:125:1:138:3 | Array |
@@ -770,130 +773,130 @@ enclosingModule
| calls.rb:135:9:135:14 | ... = ... | calls.rb:125:1:138:3 | Array |
| calls.rb:135:11:135:12 | ... + ... | calls.rb:125:1:138:3 | Array |
| calls.rb:135:14:135:14 | 1 | calls.rb:125:1:138:3 | Array |
-| calls.rb:140:1:142:3 | funny | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:1:144:30 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:10:144:10 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:10:144:10 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:13:144:29 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:18:144:18 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:146:2:146:2 | a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:1:150:13 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:3:150:3 | a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:7:150:7 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:11:150:11 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:26:150:26 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:26:150:26 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:29:150:29 | v | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:29:150:29 | v | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:32:150:61 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:40:150:40 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:42:150:45 | -> | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:48:150:48 | v | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:1:152:7 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:20:152:20 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:20:152:20 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:23:152:23 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:1:154:7 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:20:154:20 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:20:154:20 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:23:154:39 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:28:154:28 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:1:156:8 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:21:156:21 | _ | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:21:156:21 | _ | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:24:156:24 | v | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:24:156:24 | v | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:27:156:36 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:32:156:32 | v | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:158:14:158:15 | &b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:158:15:158:15 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:159:5:159:17 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:159:16:159:17 | &... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:159:17:159:17 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:1:162:28 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:13:162:13 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:13:162:13 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:16:162:16 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:165:1:169:3 | S | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:140:1:142:3 | funny | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:141:5:141:20 | yield ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:141:11:141:20 | "prefix: " | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:141:12:141:19 | prefix: | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:1:144:30 | call to funny | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:1:144:30 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:7:144:30 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:10:144:10 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:10:144:10 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:13:144:29 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:13:144:29 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:18:144:18 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:144:18:144:29 | call to capitalize | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:146:1:146:3 | "a" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:146:1:146:14 | call to capitalize | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:146:2:146:2 | a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:147:1:147:1 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:147:1:147:12 | call to bit_length | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:148:1:148:1 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:148:1:148:5 | call to abs | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:1:150:13 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:1:150:13 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:1:150:13 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:1:150:62 | call to foreach | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:2:150:4 | "a" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:3:150:3 | a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:6:150:8 | "b" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:7:150:7 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:10:150:12 | "c" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:11:150:11 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:23:150:62 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:26:150:26 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:26:150:26 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:29:150:29 | v | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:29:150:29 | v | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:32:150:61 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:32:150:61 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:37:150:61 | "#{...} -> #{...}" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:38:150:41 | #{...} | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:40:150:40 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:42:150:45 | -> | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:46:150:60 | #{...} | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:48:150:48 | v | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:150:48:150:59 | call to capitalize | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:1:152:7 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:1:152:7 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:1:152:7 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:1:152:35 | call to foreach | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:2:152:2 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:4:152:4 | 2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:6:152:6 | 3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:17:152:35 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:20:152:20 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:20:152:20 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:23:152:23 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:152:23:152:34 | call to bit_length | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:1:154:7 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:1:154:7 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:1:154:7 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:1:154:40 | call to foreach | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:2:154:2 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:4:154:4 | 2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:6:154:6 | 3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:17:154:40 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:20:154:20 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:20:154:20 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:23:154:39 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:23:154:39 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:28:154:28 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:154:28:154:39 | call to capitalize | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:1:156:8 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:1:156:8 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:1:156:8 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:1:156:37 | call to foreach | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:2:156:2 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:4:156:5 | - ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:5:156:5 | 2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:7:156:7 | 3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:18:156:37 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:21:156:21 | _ | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:21:156:21 | _ | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:24:156:24 | v | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:24:156:24 | v | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:27:156:36 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:27:156:36 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:32:156:32 | v | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:156:32:156:36 | call to abs | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:158:1:160:3 | indirect | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:158:14:158:15 | &b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:158:15:158:15 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:159:5:159:17 | call to call_block | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:159:5:159:17 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:159:16:159:17 | &... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:159:17:159:17 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:1:162:28 | call to indirect | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:1:162:28 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:10:162:28 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:13:162:13 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:13:162:13 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:16:162:16 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:162:16:162:27 | call to bit_length | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:165:1:169:3 | S | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:166:5:168:7 | s_method | calls.rb:165:1:169:3 | S |
| calls.rb:167:9:167:12 | self | calls.rb:165:1:169:3 | S |
| calls.rb:167:9:167:17 | call to to_s | calls.rb:165:1:169:3 | S |
-| calls.rb:171:1:174:3 | A | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:171:11:171:11 | S | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:171:1:174:3 | A | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:171:11:171:11 | S | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:172:5:173:7 | to_s | calls.rb:171:1:174:3 | A |
-| calls.rb:176:1:179:3 | B | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:176:11:176:11 | S | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:176:1:179:3 | B | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:176:11:176:11 | S | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:177:5:178:7 | to_s | calls.rb:176:1:179:3 | B |
-| calls.rb:181:1:181:1 | S | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:182:1:182:1 | A | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:183:1:183:1 | B | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:188:1:188:15 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:181:1:181:1 | S | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:181:1:181:5 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:181:1:181:14 | call to s_method | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:182:1:182:1 | A | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:182:1:182:5 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:182:1:182:14 | call to s_method | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:183:1:183:1 | B | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:183:1:183:5 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:183:1:183:14 | call to s_method | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:185:1:186:3 | private_on_main | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:188:1:188:15 | call to private_on_main | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:188:1:188:15 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:190:1:226:3 | Singletons | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:191:5:194:7 | singleton_a | calls.rb:190:1:226:3 | Singletons |
| calls.rb:191:9:191:12 | self | calls.rb:190:1:226:3 | Singletons |
| calls.rb:192:9:192:26 | call to puts | calls.rb:190:1:226:3 | Singletons |
@@ -943,126 +946,126 @@ enclosingModule
| calls.rb:223:5:225:7 | call_singleton_g | calls.rb:190:1:226:3 | Singletons |
| calls.rb:224:9:224:12 | self | calls.rb:190:1:226:3 | Singletons |
| calls.rb:224:9:224:24 | call to singleton_g | calls.rb:190:1:226:3 | Singletons |
-| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:237:5:237:24 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:244:5:244:24 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:228:1:228:10 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:228:1:228:22 | call to singleton_a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:229:1:229:10 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:229:1:229:22 | call to singleton_f | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:231:1:231:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:231:1:231:19 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:231:6:231:15 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:231:6:231:19 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:233:1:233:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:233:1:233:11 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:234:1:234:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:234:1:234:14 | call to singleton_e | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:236:1:238:3 | singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:236:5:236:6 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:237:5:237:24 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:237:5:237:24 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:237:10:237:24 | "singleton_g_1" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:237:11:237:23 | singleton_g_1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:240:1:240:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:240:1:240:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:241:1:241:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:241:1:241:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:243:1:245:3 | singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:243:5:243:6 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:244:5:244:24 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:244:5:244:24 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:244:10:244:24 | "singleton_g_2" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:244:11:244:23 | singleton_g_2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:247:1:247:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:247:1:247:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:248:1:248:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:248:1:248:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:250:1:254:3 | class << ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:250:10:250:11 | c1 | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:251:5:253:7 | singleton_g | calls.rb:250:1:254:3 | class << ... |
| calls.rb:252:9:252:28 | call to puts | calls.rb:250:1:254:3 | class << ... |
| calls.rb:252:9:252:28 | self | calls.rb:250:1:254:3 | class << ... |
| calls.rb:252:14:252:28 | "singleton_g_3" | calls.rb:250:1:254:3 | class << ... |
| calls.rb:252:15:252:27 | singleton_g_3 | calls.rb:250:1:254:3 | class << ... |
-| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:263:1:263:4 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:265:1:265:16 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:268:5:268:22 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:278:1:286:3 | create | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:278:12:278:15 | type | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:278:12:278:15 | type | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:279:5:279:8 | type | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:281:9:281:12 | type | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:282:9:282:26 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:285:5:285:8 | type | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:288:1:288:17 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:291:1:291:1 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:293:10:293:10 | x | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:256:1:256:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:256:1:256:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:257:1:257:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:257:1:257:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:259:1:259:2 | c2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:259:1:259:19 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:259:6:259:15 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:259:6:259:19 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:260:1:260:2 | c2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:260:1:260:14 | call to singleton_e | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:261:1:261:2 | c2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:261:1:261:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:263:1:263:4 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:263:1:263:8 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:265:1:265:16 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:265:1:265:16 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:265:6:265:16 | "top-level" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:265:7:265:15 | top-level | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:267:1:269:3 | singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:267:5:267:14 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:268:5:268:22 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:268:5:268:22 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:268:10:268:22 | "singleton_g" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:268:11:268:21 | singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:271:1:271:10 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:271:1:271:22 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:272:1:272:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:272:1:272:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:273:1:273:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:273:1:273:19 | call to call_singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:274:1:274:2 | c2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:274:1:274:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:275:1:275:2 | c3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:275:1:275:19 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:275:6:275:15 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:275:6:275:19 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:276:1:276:2 | c3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:276:1:276:14 | call to singleton_g | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:278:1:286:3 | create | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:278:12:278:15 | type | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:278:12:278:15 | type | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:279:5:279:8 | type | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:279:5:279:12 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:279:5:279:21 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:281:5:283:7 | singleton_h | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:281:9:281:12 | type | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:282:9:282:26 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:282:9:282:26 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:282:14:282:26 | "singleton_h" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:282:15:282:25 | singleton_h | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:285:5:285:8 | type | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:285:5:285:20 | call to singleton_h | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:288:1:288:17 | call to create | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:288:1:288:17 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:288:8:288:17 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:289:1:289:10 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:289:1:289:22 | call to singleton_h | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:291:1:291:1 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:291:1:291:14 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:291:5:291:14 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:293:1:297:3 | class << ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:293:10:293:10 | x | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:294:5:296:7 | singleton_i | calls.rb:293:1:297:3 | class << ... |
| calls.rb:295:9:295:26 | call to puts | calls.rb:293:1:297:3 | class << ... |
| calls.rb:295:9:295:26 | self | calls.rb:293:1:297:3 | class << ... |
| calls.rb:295:14:295:26 | "singleton_i" | calls.rb:293:1:297:3 | class << ... |
| calls.rb:295:15:295:25 | singleton_i | calls.rb:293:1:297:3 | class << ... |
-| calls.rb:299:1:299:1 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:299:1:299:1 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:299:1:299:13 | call to singleton_i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:300:1:300:10 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:300:1:300:22 | call to singleton_i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:302:1:306:3 | class << ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:302:10:302:19 | Singletons | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:303:5:305:7 | singleton_j | calls.rb:302:1:306:3 | class << ... |
| calls.rb:304:9:304:26 | call to puts | calls.rb:302:1:306:3 | class << ... |
| calls.rb:304:9:304:26 | self | calls.rb:302:1:306:3 | class << ... |
| calls.rb:304:14:304:26 | "singleton_j" | calls.rb:302:1:306:3 | class << ... |
| calls.rb:304:15:304:25 | singleton_j | calls.rb:302:1:306:3 | class << ... |
-| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:308:1:308:10 | Singletons | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:308:1:308:22 | call to singleton_j | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:310:1:321:3 | SelfNew | calls.rb:1:1:667:52 | calls.rb |
| calls.rb:311:5:314:7 | instance | calls.rb:310:1:321:3 | SelfNew |
| calls.rb:312:9:312:31 | call to puts | calls.rb:310:1:321:3 | SelfNew |
| calls.rb:312:9:312:31 | self | calls.rb:310:1:321:3 | SelfNew |
@@ -1079,508 +1082,535 @@ enclosingModule
| calls.rb:320:5:320:7 | call to new | calls.rb:310:1:321:3 | SelfNew |
| calls.rb:320:5:320:7 | self | calls.rb:310:1:321:3 | SelfNew |
| calls.rb:320:5:320:16 | call to instance | calls.rb:310:1:321:3 | SelfNew |
-| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:325:1:329:3 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:326:5:328:7 | instance | calls.rb:325:1:329:3 | C1 |
-| calls.rb:327:9:327:26 | call to puts | calls.rb:325:1:329:3 | C1 |
-| calls.rb:327:9:327:26 | self | calls.rb:325:1:329:3 | C1 |
-| calls.rb:327:14:327:26 | "C1#instance" | calls.rb:325:1:329:3 | C1 |
-| calls.rb:327:15:327:25 | C1#instance | calls.rb:325:1:329:3 | C1 |
-| calls.rb:331:1:335:3 | C2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:331:12:331:13 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:332:5:334:7 | instance | calls.rb:331:1:335:3 | C2 |
-| calls.rb:333:9:333:26 | call to puts | calls.rb:331:1:335:3 | C2 |
-| calls.rb:333:9:333:26 | self | calls.rb:331:1:335:3 | C2 |
-| calls.rb:333:14:333:26 | "C2#instance" | calls.rb:331:1:335:3 | C2 |
-| calls.rb:333:15:333:25 | C2#instance | calls.rb:331:1:335:3 | C2 |
-| calls.rb:337:1:341:3 | C3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:337:12:337:13 | C2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:338:5:340:7 | instance | calls.rb:337:1:341:3 | C3 |
-| calls.rb:339:9:339:26 | call to puts | calls.rb:337:1:341:3 | C3 |
-| calls.rb:339:9:339:26 | self | calls.rb:337:1:341:3 | C3 |
-| calls.rb:339:14:339:26 | "C3#instance" | calls.rb:337:1:341:3 | C3 |
-| calls.rb:339:15:339:25 | C3#instance | calls.rb:337:1:341:3 | C3 |
-| calls.rb:343:1:359:3 | pattern_dispatch | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:343:22:343:22 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:343:22:343:22 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:344:5:352:7 | case ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:344:10:344:10 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:345:5:346:18 | when ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:345:10:345:11 | C3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:345:12:346:18 | then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:346:9:346:9 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:346:9:346:18 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:347:5:348:18 | when ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:347:10:347:11 | C2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:347:12:348:18 | then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:348:9:348:9 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:348:9:348:18 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:349:10:349:11 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:350:9:350:9 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:351:5:351:8 | else ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:354:5:358:7 | case ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:354:10:354:10 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:355:9:355:29 | in ... then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:355:12:355:13 | C3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:355:15:355:29 | then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:355:20:355:20 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:355:20:355:29 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:9:356:36 | in ... then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:12:356:13 | C2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:12:356:19 | ... => ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:18:356:19 | c2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:21:356:36 | then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:26:356:27 | c2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:356:26:356:36 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:9:357:36 | in ... then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:12:357:13 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:12:357:19 | ... => ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:18:357:19 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:21:357:36 | then ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:26:357:27 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:357:26:357:36 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:361:1:361:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:361:1:361:11 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:361:6:361:7 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:361:6:361:11 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:362:1:362:2 | c1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:362:1:362:11 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:363:1:363:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:363:1:363:25 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:363:18:363:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:363:19:363:20 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:363:19:363:24 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:364:1:364:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:364:1:364:25 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:364:18:364:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:364:19:364:20 | C2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:364:19:364:24 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:365:1:365:25 | call to pattern_dispatch | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:365:1:365:25 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:365:18:365:25 | ( ... ) | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:365:19:365:20 | C3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:365:19:365:24 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:367:1:371:3 | add_singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:367:19:367:19 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:367:19:367:19 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:368:5:370:7 | instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:368:9:368:9 | x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:369:9:369:28 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:369:9:369:28 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:369:14:369:28 | "instance_on x" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:369:15:369:27 | instance_on x | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:373:1:373:2 | c3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:373:1:373:11 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:373:6:373:7 | C1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:373:6:373:11 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:374:1:374:16 | call to add_singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:374:1:374:16 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:374:15:374:16 | c3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:375:1:375:2 | c3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:375:1:375:11 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:377:1:405:3 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:378:5:390:7 | class << ... | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:378:14:378:17 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:379:9:381:11 | singleton1 | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:380:13:380:48 | call to puts | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:380:13:380:48 | self | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:380:18:380:48 | "SingletonOverride1#singleton1" | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:380:19:380:47 | SingletonOverride1#singleton1 | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:383:9:385:11 | call_singleton1 | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:384:13:384:22 | call to singleton1 | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:384:13:384:22 | self | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:387:9:389:11 | factory | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:388:13:388:16 | self | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:388:13:388:20 | call to new | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:388:13:388:30 | call to instance1 | calls.rb:378:5:390:7 | class << ... |
-| calls.rb:392:5:394:7 | singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:392:9:392:12 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:393:9:393:44 | call to puts | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:393:9:393:44 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:393:14:393:44 | "SingletonOverride1#singleton2" | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:393:15:393:43 | SingletonOverride1#singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:396:5:398:7 | call_singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:396:9:396:12 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:397:9:397:18 | call to singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:397:9:397:18 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:400:5:400:14 | call to singleton2 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:400:5:400:14 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:402:5:404:7 | instance1 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:403:9:403:43 | call to puts | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:403:9:403:43 | self | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:403:14:403:43 | "SingletonOverride1#instance1" | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:403:15:403:42 | SingletonOverride1#instance1 | calls.rb:377:1:405:3 | SingletonOverride1 |
-| calls.rb:407:1:407:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:407:1:407:29 | call to singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:408:1:408:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:408:1:408:29 | call to singleton2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:409:1:409:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:409:1:409:34 | call to call_singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:410:1:410:18 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:410:1:410:34 | call to call_singleton2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:412:1:426:3 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:412:28:412:45 | SingletonOverride1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:413:5:417:7 | class << ... | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:413:14:413:17 | self | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:414:9:416:11 | singleton1 | calls.rb:413:5:417:7 | class << ... |
-| calls.rb:415:13:415:48 | call to puts | calls.rb:413:5:417:7 | class << ... |
-| calls.rb:415:13:415:48 | self | calls.rb:413:5:417:7 | class << ... |
-| calls.rb:415:18:415:48 | "SingletonOverride2#singleton1" | calls.rb:413:5:417:7 | class << ... |
-| calls.rb:415:19:415:47 | SingletonOverride2#singleton1 | calls.rb:413:5:417:7 | class << ... |
-| calls.rb:419:5:421:7 | singleton2 | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:419:9:419:12 | self | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:420:9:420:44 | call to puts | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:420:9:420:44 | self | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:420:14:420:44 | "SingletonOverride2#singleton2" | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:420:15:420:43 | SingletonOverride2#singleton2 | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:423:5:425:7 | instance1 | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:424:9:424:43 | call to puts | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:424:9:424:43 | self | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:424:14:424:43 | "SingletonOverride2#instance1" | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:424:15:424:42 | SingletonOverride2#instance1 | calls.rb:412:1:426:3 | SingletonOverride2 |
-| calls.rb:428:1:428:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:428:1:428:29 | call to singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:429:1:429:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:429:1:429:29 | call to singleton2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:430:1:430:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:430:1:430:34 | call to call_singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:431:1:431:18 | SingletonOverride2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:431:1:431:34 | call to call_singleton2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:433:1:461:3 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:434:5:438:7 | if ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:434:8:434:13 | call to rand | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:434:8:434:13 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:434:8:434:17 | ... > ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:434:17:434:17 | 0 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:434:19:437:11 | then ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:435:9:437:11 | m1 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:436:13:436:48 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:436:13:436:48 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:436:18:436:48 | "ConditionalInstanceMethods#m1" | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:436:19:436:47 | ConditionalInstanceMethods#m1 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:440:5:452:7 | m2 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:441:9:441:44 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:441:9:441:44 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:441:14:441:44 | "ConditionalInstanceMethods#m2" | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:441:15:441:43 | ConditionalInstanceMethods#m2 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:443:9:449:11 | m3 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:444:13:444:48 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:444:13:444:48 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m3" | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m3 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:446:13:448:15 | m4 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:447:17:447:52 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:447:17:447:52 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:447:22:447:52 | "ConditionalInstanceMethods#m4" | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:447:23:447:51 | ConditionalInstanceMethods#m4 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:451:9:451:10 | call to m3 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:451:9:451:10 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:454:5:460:7 | if ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:454:8:454:13 | call to rand | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:454:8:454:13 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:454:8:454:17 | ... > ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:454:17:454:17 | 0 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:454:19:459:18 | then ... | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:455:9:455:13 | Class | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:455:9:459:11 | call to new | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:455:9:459:15 | call to new | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:455:9:459:18 | call to m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:455:19:459:11 | do ... end | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:456:13:458:15 | m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:457:17:457:40 | call to puts | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:457:17:457:40 | self | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:457:22:457:40 | "AnonymousClass#m5" | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:457:23:457:39 | AnonymousClass#m5 | calls.rb:433:1:461:3 | ConditionalInstanceMethods |
-| calls.rb:463:1:463:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:463:1:463:30 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:463:1:463:33 | call to m1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:464:1:464:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:464:1:464:30 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:464:1:464:33 | call to m3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:465:1:465:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:465:1:465:30 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:465:1:465:33 | call to m2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:466:1:466:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:466:1:466:30 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:466:1:466:33 | call to m3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:467:1:467:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:467:1:467:30 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:467:1:467:33 | call to m4 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:468:1:468:26 | ConditionalInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:468:1:468:30 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:468:1:468:33 | call to m5 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:470:1:470:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:470:1:488:3 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:470:27:470:31 | Class | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:470:27:488:3 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:470:37:488:3 | do ... end | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:5:471:11 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:5:471:11 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:5:471:11 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:5:475:7 | call to each | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:6:471:6 | 0 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:8:471:8 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:10:471:10 | 2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:471:18:475:7 | do ... end | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:472:9:474:11 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:473:13:473:22 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:473:13:473:22 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:473:18:473:22 | "foo" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:473:19:473:21 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:477:5:477:9 | Class | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:477:5:481:7 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:477:5:481:11 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:477:5:481:15 | call to bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:477:15:481:7 | do ... end | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:478:9:480:11 | bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:479:13:479:22 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:479:13:479:22 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:479:18:479:22 | "bar" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:479:19:479:21 | bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:5:483:11 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:5:483:11 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:5:483:11 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:5:487:7 | call to each | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:6:483:6 | 0 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:8:483:8 | 1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:10:483:10 | 2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:18:487:7 | do ... end | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:22:483:22 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:483:22:483:22 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:9:486:11 | call to define_method | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:9:486:11 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:23:484:32 | "baz_#{...}" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:24:484:27 | baz_ | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:28:484:31 | #{...} | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:30:484:30 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:484:35:486:11 | do ... end | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:485:13:485:27 | call to puts | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:485:13:485:27 | self | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:485:18:485:27 | "baz_#{...}" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:485:19:485:22 | baz_ | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:485:23:485:26 | #{...} | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:485:25:485:25 | i | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:490:1:490:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:490:1:490:27 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:490:1:490:31 | call to foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:491:1:491:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:491:1:491:27 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:491:1:491:31 | call to bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:492:1:492:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:492:1:492:27 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:492:1:492:33 | call to baz_0 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:493:1:493:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:493:1:493:27 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:493:1:493:33 | call to baz_1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:494:1:494:23 | EsotericInstanceMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:494:1:494:27 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:494:1:494:33 | call to baz_2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:496:1:502:3 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:497:5:499:7 | singleton | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:498:9:498:46 | call to puts | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:498:9:498:46 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:498:14:498:46 | "ExtendSingletonMethod#singleton" | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:498:15:498:45 | ExtendSingletonMethod#singleton | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:501:5:501:15 | call to extend | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:501:5:501:15 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:501:12:501:15 | self | calls.rb:496:1:502:3 | ExtendSingletonMethod |
-| calls.rb:504:1:504:21 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:504:1:504:31 | call to singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:506:1:508:3 | ExtendSingletonMethod2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:507:5:507:32 | call to extend | calls.rb:506:1:508:3 | ExtendSingletonMethod2 |
-| calls.rb:507:5:507:32 | self | calls.rb:506:1:508:3 | ExtendSingletonMethod2 |
-| calls.rb:507:12:507:32 | ExtendSingletonMethod | calls.rb:506:1:508:3 | ExtendSingletonMethod2 |
-| calls.rb:510:1:510:22 | ExtendSingletonMethod2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:510:1:510:32 | call to singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:512:1:513:3 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:515:1:515:22 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:515:1:515:51 | call to extend | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:515:31:515:51 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:517:1:517:22 | ExtendSingletonMethod3 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:517:1:517:32 | call to singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:519:1:519:3 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:519:1:519:13 | ... = ... | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:519:7:519:13 | "hello" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:519:8:519:12 | hello | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:520:1:520:3 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:520:1:520:13 | call to singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:521:1:521:3 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:521:1:521:32 | call to extend | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:521:12:521:32 | ExtendSingletonMethod | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:523:1:523:3 | foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:523:1:523:13 | call to singleton | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:525:1:529:3 | ProtectedMethodInModule | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:526:5:528:7 | call to protected | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:526:5:528:7 | self | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:526:15:528:7 | foo | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:527:9:527:42 | call to puts | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:527:9:527:42 | self | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:527:14:527:42 | "ProtectedMethodInModule#foo" | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:527:15:527:41 | ProtectedMethodInModule#foo | calls.rb:525:1:529:3 | ProtectedMethodInModule |
-| calls.rb:531:1:544:3 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:532:5:532:35 | call to include | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:532:5:532:35 | self | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:532:13:532:35 | ProtectedMethodInModule | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:534:5:536:7 | call to protected | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:534:5:536:7 | self | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:534:15:536:7 | bar | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:535:9:535:35 | call to puts | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:535:9:535:35 | self | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:535:14:535:35 | "ProtectedMethods#bar" | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:535:15:535:34 | ProtectedMethods#bar | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:538:5:543:7 | baz | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:539:9:539:11 | call to foo | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:539:9:539:11 | self | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:540:9:540:11 | call to bar | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:540:9:540:11 | self | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:541:9:541:24 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:541:9:541:28 | call to new | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:541:9:541:32 | call to foo | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:542:9:542:24 | ProtectedMethods | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:542:9:542:28 | call to new | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:542:9:542:32 | call to bar | calls.rb:531:1:544:3 | ProtectedMethods |
-| calls.rb:546:1:546:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:546:1:546:20 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:546:1:546:24 | call to foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:547:1:547:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:547:1:547:20 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:547:1:547:24 | call to bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:548:1:548:16 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:548:1:548:20 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:548:1:548:24 | call to baz | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:550:1:555:3 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:550:29:550:44 | ProtectedMethods | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:551:5:554:7 | baz | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:552:9:552:11 | call to foo | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:552:9:552:11 | self | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:553:9:553:27 | ProtectedMethodsSub | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:553:9:553:31 | call to new | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:553:9:553:35 | call to foo | calls.rb:550:1:555:3 | ProtectedMethodsSub |
-| calls.rb:557:1:557:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:557:1:557:23 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:557:1:557:27 | call to foo | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:558:1:558:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:558:1:558:23 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:558:1:558:27 | call to bar | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:559:1:559:19 | ProtectedMethodsSub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:559:1:559:23 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:559:1:559:27 | call to baz | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:1:561:7 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:1:561:7 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:1:561:7 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:1:561:26 | call to each | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:2:561:2 | C | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:2:561:6 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:14:561:26 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:17:561:17 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:17:561:17 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:20:561:20 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:561:20:561:24 | call to baz | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:1:562:13 | Array | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:1:562:13 | [...] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:1:562:13 | call to [] | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:1:562:39 | call to each | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:2:562:4 | "a" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:3:562:3 | a | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:6:562:8 | "b" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:7:562:7 | b | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:10:562:12 | "c" | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:11:562:11 | c | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:20:562:39 | { ... } | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:23:562:23 | s | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:23:562:23 | s | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:26:562:26 | s | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:562:26:562:37 | call to capitalize | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:564:1:567:3 | SingletonUpCall_Base | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:565:5:566:7 | singleton | calls.rb:564:1:567:3 | SingletonUpCall_Base |
-| calls.rb:565:9:565:12 | self | calls.rb:564:1:567:3 | SingletonUpCall_Base |
-| calls.rb:568:1:575:3 | SingletonUpCall_Sub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:568:29:568:48 | SingletonUpCall_Base | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:569:5:569:13 | call to singleton | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:569:5:569:13 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:570:5:570:14 | call to singleton2 | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:570:5:570:14 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:571:5:574:7 | mid_method | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:571:9:571:12 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:572:9:572:17 | call to singleton | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:572:9:572:17 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:573:9:573:18 | call to singleton2 | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:573:9:573:18 | self | calls.rb:568:1:575:3 | SingletonUpCall_Sub |
-| calls.rb:576:1:581:3 | SingletonUpCall_SubSub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:576:32:576:50 | SingletonUpCall_Sub | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:577:5:578:7 | singleton2 | calls.rb:576:1:581:3 | SingletonUpCall_SubSub |
-| calls.rb:577:9:577:12 | self | calls.rb:576:1:581:3 | SingletonUpCall_SubSub |
-| calls.rb:580:5:580:14 | call to mid_method | calls.rb:576:1:581:3 | SingletonUpCall_SubSub |
-| calls.rb:580:5:580:14 | self | calls.rb:576:1:581:3 | SingletonUpCall_SubSub |
-| calls.rb:583:1:594:3 | SingletonA | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:584:5:585:7 | singleton1 | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:584:9:584:12 | self | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:587:5:589:7 | call_singleton1 | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:587:9:587:12 | self | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:588:9:588:18 | call to singleton1 | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:588:9:588:18 | self | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:591:5:593:7 | call_call_singleton1 | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:591:9:591:12 | self | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:592:9:592:23 | call to call_singleton1 | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:592:9:592:23 | self | calls.rb:583:1:594:3 | SingletonA |
-| calls.rb:596:1:603:3 | SingletonB | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:596:20:596:29 | SingletonA | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:597:5:598:7 | singleton1 | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:597:9:597:12 | self | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:600:5:602:7 | call_singleton1 | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:600:9:600:12 | self | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:601:9:601:18 | call to singleton1 | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:601:9:601:18 | self | calls.rb:596:1:603:3 | SingletonB |
-| calls.rb:605:1:612:3 | SingletonC | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:605:20:605:29 | SingletonA | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:606:5:607:7 | singleton1 | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:606:9:606:12 | self | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:609:5:611:7 | call_singleton1 | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:609:9:609:12 | self | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:610:9:610:18 | call to singleton1 | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:610:9:610:18 | self | calls.rb:605:1:612:3 | SingletonC |
-| calls.rb:614:1:614:10 | SingletonA | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:614:1:614:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:615:1:615:10 | SingletonB | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:615:1:615:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:616:1:616:10 | SingletonC | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:616:1:616:31 | call to call_call_singleton1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:618:1:624:3 | Included | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:619:5:621:7 | foo | calls.rb:618:1:624:3 | Included |
-| calls.rb:620:9:620:12 | self | calls.rb:618:1:624:3 | Included |
-| calls.rb:620:9:620:16 | call to bar | calls.rb:618:1:624:3 | Included |
-| calls.rb:622:5:623:7 | bar | calls.rb:618:1:624:3 | Included |
-| calls.rb:626:1:631:3 | IncludesIncluded | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:627:5:627:20 | call to include | calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:627:5:627:20 | self | calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:627:13:627:20 | Included | calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:628:5:630:7 | bar | calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:629:9:629:13 | super call to bar | calls.rb:626:1:631:3 | IncludesIncluded |
-| calls.rb:633:1:637:3 | CustomNew1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:634:5:636:7 | new | calls.rb:633:1:637:3 | CustomNew1 |
-| calls.rb:634:9:634:12 | self | calls.rb:633:1:637:3 | CustomNew1 |
-| calls.rb:635:9:635:10 | C1 | calls.rb:633:1:637:3 | CustomNew1 |
-| calls.rb:635:9:635:14 | call to new | calls.rb:633:1:637:3 | CustomNew1 |
-| calls.rb:639:1:639:10 | CustomNew1 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:639:1:639:14 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:639:1:639:23 | call to instance | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:641:1:649:3 | CustomNew2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:642:5:644:7 | new | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:642:9:642:12 | self | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:643:9:643:12 | self | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:643:9:643:21 | call to allocate | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:646:5:648:7 | instance | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:647:9:647:34 | call to puts | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:647:9:647:34 | self | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:647:14:647:34 | "CustomNew2#instance" | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:647:15:647:33 | CustomNew2#instance | calls.rb:641:1:649:3 | CustomNew2 |
-| calls.rb:651:1:651:10 | CustomNew2 | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:651:1:651:14 | call to new | calls.rb:1:1:651:24 | calls.rb |
-| calls.rb:651:1:651:23 | call to instance | calls.rb:1:1:651:24 | calls.rb |
+| calls.rb:323:1:323:7 | SelfNew | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:323:1:323:17 | call to singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:325:1:333:3 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:326:5:328:7 | instance | calls.rb:325:1:333:3 | C1 |
+| calls.rb:327:9:327:26 | call to puts | calls.rb:325:1:333:3 | C1 |
+| calls.rb:327:9:327:26 | self | calls.rb:325:1:333:3 | C1 |
+| calls.rb:327:14:327:26 | "C1#instance" | calls.rb:325:1:333:3 | C1 |
+| calls.rb:327:15:327:25 | C1#instance | calls.rb:325:1:333:3 | C1 |
+| calls.rb:330:5:332:7 | return_self | calls.rb:325:1:333:3 | C1 |
+| calls.rb:331:9:331:12 | self | calls.rb:325:1:333:3 | C1 |
+| calls.rb:335:1:339:3 | C2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:335:12:335:13 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:336:5:338:7 | instance | calls.rb:335:1:339:3 | C2 |
+| calls.rb:337:9:337:26 | call to puts | calls.rb:335:1:339:3 | C2 |
+| calls.rb:337:9:337:26 | self | calls.rb:335:1:339:3 | C2 |
+| calls.rb:337:14:337:26 | "C2#instance" | calls.rb:335:1:339:3 | C2 |
+| calls.rb:337:15:337:25 | C2#instance | calls.rb:335:1:339:3 | C2 |
+| calls.rb:341:1:345:3 | C3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:341:12:341:13 | C2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:342:5:344:7 | instance | calls.rb:341:1:345:3 | C3 |
+| calls.rb:343:9:343:26 | call to puts | calls.rb:341:1:345:3 | C3 |
+| calls.rb:343:9:343:26 | self | calls.rb:341:1:345:3 | C3 |
+| calls.rb:343:14:343:26 | "C3#instance" | calls.rb:341:1:345:3 | C3 |
+| calls.rb:343:15:343:25 | C3#instance | calls.rb:341:1:345:3 | C3 |
+| calls.rb:347:1:363:3 | pattern_dispatch | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:347:22:347:22 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:347:22:347:22 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:348:5:356:7 | case ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:348:10:348:10 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:349:5:350:18 | when ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:349:10:349:11 | C3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:349:12:350:18 | then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:350:9:350:9 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:350:9:350:18 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:351:5:352:18 | when ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:351:10:351:11 | C2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:351:12:352:18 | then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:352:9:352:9 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:352:9:352:18 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:353:5:354:18 | when ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:353:10:353:11 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:353:12:354:18 | then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:354:9:354:9 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:354:9:354:18 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:355:5:355:8 | else ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:358:5:362:7 | case ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:358:10:358:10 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:359:9:359:29 | in ... then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:359:12:359:13 | C3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:359:15:359:29 | then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:359:20:359:20 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:359:20:359:29 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:9:360:36 | in ... then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:12:360:13 | C2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:12:360:19 | ... => ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:18:360:19 | c2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:21:360:36 | then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:26:360:27 | c2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:360:26:360:36 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:9:361:36 | in ... then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:12:361:13 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:12:361:19 | ... => ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:18:361:19 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:21:361:36 | then ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:26:361:27 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:361:26:361:36 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:365:1:365:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:365:1:365:11 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:365:6:365:7 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:365:6:365:11 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:366:1:366:2 | c1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:366:1:366:11 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:368:1:368:25 | call to pattern_dispatch | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:368:1:368:25 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:368:18:368:25 | ( ... ) | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:368:19:368:20 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:368:19:368:24 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:369:1:369:25 | call to pattern_dispatch | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:369:1:369:25 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:369:18:369:25 | ( ... ) | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:369:19:369:20 | C2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:369:19:369:24 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:370:1:370:25 | call to pattern_dispatch | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:370:1:370:25 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:370:18:370:25 | ( ... ) | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:370:19:370:20 | C3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:370:19:370:24 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:372:1:372:2 | C3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:372:1:372:6 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:372:1:372:18 | call to return_self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:372:1:372:27 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:374:1:378:3 | add_singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:374:19:374:19 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:374:19:374:19 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:375:5:377:7 | instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:375:9:375:9 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:376:9:376:28 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:376:9:376:28 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:376:14:376:28 | "instance_on x" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:376:15:376:27 | instance_on x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:380:1:380:2 | c3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:380:1:380:11 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:380:6:380:7 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:380:6:380:11 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:381:1:381:16 | call to add_singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:381:1:381:16 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:381:15:381:16 | c3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:382:1:382:2 | c3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:382:1:382:11 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:383:1:383:2 | c3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:383:1:383:14 | call to return_self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:383:1:383:23 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:385:1:413:3 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:386:5:398:7 | class << ... | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:386:14:386:17 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:387:9:389:11 | singleton1 | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:388:13:388:48 | call to puts | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:388:13:388:48 | self | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:388:18:388:48 | "SingletonOverride1#singleton1" | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:388:19:388:47 | SingletonOverride1#singleton1 | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:391:9:393:11 | call_singleton1 | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:392:13:392:22 | self | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:395:9:397:11 | factory | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:396:13:396:16 | self | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:396:13:396:20 | call to new | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:396:13:396:30 | call to instance1 | calls.rb:386:5:398:7 | class << ... |
+| calls.rb:400:5:402:7 | singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:400:9:400:12 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:401:9:401:44 | call to puts | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:401:9:401:44 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:401:14:401:44 | "SingletonOverride1#singleton2" | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:401:15:401:43 | SingletonOverride1#singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:404:5:406:7 | call_singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:404:9:404:12 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:405:9:405:18 | call to singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:405:9:405:18 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:408:5:408:14 | call to singleton2 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:408:5:408:14 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:410:5:412:7 | instance1 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:411:9:411:43 | call to puts | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:411:9:411:43 | self | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:411:14:411:43 | "SingletonOverride1#instance1" | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:411:15:411:42 | SingletonOverride1#instance1 | calls.rb:385:1:413:3 | SingletonOverride1 |
+| calls.rb:415:1:415:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:415:1:415:29 | call to singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:416:1:416:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:416:1:416:29 | call to singleton2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:417:1:417:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:417:1:417:34 | call to call_singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:418:1:418:18 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:418:1:418:34 | call to call_singleton2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:420:1:434:3 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:420:28:420:45 | SingletonOverride1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:421:5:425:7 | class << ... | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:421:14:421:17 | self | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:422:9:424:11 | singleton1 | calls.rb:421:5:425:7 | class << ... |
+| calls.rb:423:13:423:48 | call to puts | calls.rb:421:5:425:7 | class << ... |
+| calls.rb:423:13:423:48 | self | calls.rb:421:5:425:7 | class << ... |
+| calls.rb:423:18:423:48 | "SingletonOverride2#singleton1" | calls.rb:421:5:425:7 | class << ... |
+| calls.rb:423:19:423:47 | SingletonOverride2#singleton1 | calls.rb:421:5:425:7 | class << ... |
+| calls.rb:427:5:429:7 | singleton2 | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:427:9:427:12 | self | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:428:9:428:44 | call to puts | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:428:9:428:44 | self | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:428:14:428:44 | "SingletonOverride2#singleton2" | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:428:15:428:43 | SingletonOverride2#singleton2 | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:431:5:433:7 | instance1 | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:432:9:432:43 | call to puts | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:432:9:432:43 | self | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:432:14:432:43 | "SingletonOverride2#instance1" | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:432:15:432:42 | SingletonOverride2#instance1 | calls.rb:420:1:434:3 | SingletonOverride2 |
+| calls.rb:436:1:436:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:436:1:436:29 | call to singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:437:1:437:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:437:1:437:29 | call to singleton2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:438:1:438:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:438:1:438:34 | call to call_singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:439:1:439:18 | SingletonOverride2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:439:1:439:34 | call to call_singleton2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:441:1:469:3 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:442:5:446:7 | if ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:442:8:442:13 | call to rand | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:442:8:442:13 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:442:8:442:17 | ... > ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:442:17:442:17 | 0 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:442:19:445:11 | then ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:443:9:445:11 | m1 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:444:13:444:48 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:444:13:444:48 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:444:18:444:48 | "ConditionalInstanceMethods#m1" | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:444:19:444:47 | ConditionalInstanceMethods#m1 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:448:5:460:7 | m2 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:449:9:449:44 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:449:9:449:44 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:449:14:449:44 | "ConditionalInstanceMethods#m2" | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:449:15:449:43 | ConditionalInstanceMethods#m2 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:451:9:457:11 | m3 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:452:13:452:48 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:452:13:452:48 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:452:18:452:48 | "ConditionalInstanceMethods#m3" | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:452:19:452:47 | ConditionalInstanceMethods#m3 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:454:13:456:15 | m4 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:455:17:455:52 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:455:17:455:52 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:455:22:455:52 | "ConditionalInstanceMethods#m4" | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:455:23:455:51 | ConditionalInstanceMethods#m4 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:459:9:459:10 | call to m3 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:459:9:459:10 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:462:5:468:7 | if ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:462:8:462:13 | call to rand | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:462:8:462:13 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:462:8:462:17 | ... > ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:462:17:462:17 | 0 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:462:19:467:18 | then ... | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:463:9:463:13 | Class | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:463:9:467:11 | call to new | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:463:9:467:15 | call to new | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:463:9:467:18 | call to m5 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:463:19:467:11 | do ... end | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:464:13:466:15 | m5 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:465:17:465:40 | call to puts | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:465:17:465:40 | self | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:465:22:465:40 | "AnonymousClass#m5" | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:465:23:465:39 | AnonymousClass#m5 | calls.rb:441:1:469:3 | ConditionalInstanceMethods |
+| calls.rb:471:1:471:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:471:1:471:30 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:471:1:471:33 | call to m1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:472:1:472:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:472:1:472:30 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:472:1:472:33 | call to m3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:473:1:473:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:473:1:473:30 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:473:1:473:33 | call to m2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:474:1:474:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:474:1:474:30 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:474:1:474:33 | call to m3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:475:1:475:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:475:1:475:30 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:475:1:475:33 | call to m4 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:476:1:476:26 | ConditionalInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:476:1:476:30 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:476:1:476:33 | call to m5 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:478:1:478:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:478:1:496:3 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:478:27:478:31 | Class | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:478:27:496:3 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:478:37:496:3 | do ... end | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:5:479:11 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:5:479:11 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:5:479:11 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:5:483:7 | call to each | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:6:479:6 | 0 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:8:479:8 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:10:479:10 | 2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:479:18:483:7 | do ... end | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:480:9:482:11 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:481:13:481:22 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:481:13:481:22 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:481:18:481:22 | "foo" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:481:19:481:21 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:485:5:485:9 | Class | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:485:5:489:7 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:485:5:489:11 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:485:5:489:15 | call to bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:485:15:489:7 | do ... end | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:486:9:488:11 | bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:487:13:487:22 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:487:13:487:22 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:487:18:487:22 | "bar" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:487:19:487:21 | bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:5:491:11 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:5:491:11 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:5:491:11 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:5:495:7 | call to each | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:6:491:6 | 0 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:8:491:8 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:10:491:10 | 2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:18:495:7 | do ... end | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:22:491:22 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:491:22:491:22 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:9:494:11 | call to define_method | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:9:494:11 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:23:492:32 | "baz_#{...}" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:24:492:27 | baz_ | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:28:492:31 | #{...} | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:30:492:30 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:492:35:494:11 | do ... end | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:493:13:493:27 | call to puts | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:493:13:493:27 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:493:18:493:27 | "baz_#{...}" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:493:19:493:22 | baz_ | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:493:23:493:26 | #{...} | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:493:25:493:25 | i | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:498:1:498:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:498:1:498:27 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:498:1:498:31 | call to foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:499:1:499:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:499:1:499:27 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:499:1:499:31 | call to bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:500:1:500:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:500:1:500:27 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:500:1:500:33 | call to baz_0 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:501:1:501:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:501:1:501:27 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:501:1:501:33 | call to baz_1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:502:1:502:23 | EsotericInstanceMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:502:1:502:27 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:502:1:502:33 | call to baz_2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:504:1:510:3 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:505:5:507:7 | singleton | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:506:9:506:46 | call to puts | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:506:9:506:46 | self | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:506:14:506:46 | "ExtendSingletonMethod#singleton" | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:506:15:506:45 | ExtendSingletonMethod#singleton | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:509:5:509:15 | call to extend | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:509:5:509:15 | self | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:509:12:509:15 | self | calls.rb:504:1:510:3 | ExtendSingletonMethod |
+| calls.rb:512:1:512:21 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:512:1:512:31 | call to singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:514:1:516:3 | ExtendSingletonMethod2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:515:5:515:32 | call to extend | calls.rb:514:1:516:3 | ExtendSingletonMethod2 |
+| calls.rb:515:5:515:32 | self | calls.rb:514:1:516:3 | ExtendSingletonMethod2 |
+| calls.rb:515:12:515:32 | ExtendSingletonMethod | calls.rb:514:1:516:3 | ExtendSingletonMethod2 |
+| calls.rb:518:1:518:22 | ExtendSingletonMethod2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:518:1:518:32 | call to singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:520:1:521:3 | ExtendSingletonMethod3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:523:1:523:22 | ExtendSingletonMethod3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:523:1:523:51 | call to extend | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:523:31:523:51 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:525:1:525:22 | ExtendSingletonMethod3 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:525:1:525:32 | call to singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:527:1:527:3 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:527:1:527:13 | ... = ... | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:527:7:527:13 | "hello" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:527:8:527:12 | hello | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:528:1:528:3 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:528:1:528:13 | call to singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:529:1:529:3 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:529:1:529:32 | call to extend | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:529:12:529:32 | ExtendSingletonMethod | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:531:1:531:3 | foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:531:1:531:13 | call to singleton | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:533:1:537:3 | ProtectedMethodInModule | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:534:5:536:7 | call to protected | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:534:5:536:7 | self | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:534:15:536:7 | foo | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:535:9:535:42 | call to puts | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:535:9:535:42 | self | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:535:14:535:42 | "ProtectedMethodInModule#foo" | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:535:15:535:41 | ProtectedMethodInModule#foo | calls.rb:533:1:537:3 | ProtectedMethodInModule |
+| calls.rb:539:1:552:3 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:540:5:540:35 | call to include | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:540:5:540:35 | self | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:540:13:540:35 | ProtectedMethodInModule | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:542:5:544:7 | call to protected | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:542:5:544:7 | self | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:542:15:544:7 | bar | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:543:9:543:35 | call to puts | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:543:9:543:35 | self | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:543:14:543:35 | "ProtectedMethods#bar" | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:543:15:543:34 | ProtectedMethods#bar | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:546:5:551:7 | baz | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:547:9:547:11 | call to foo | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:547:9:547:11 | self | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:548:9:548:11 | call to bar | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:548:9:548:11 | self | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:549:9:549:24 | ProtectedMethods | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:549:9:549:28 | call to new | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:549:9:549:32 | call to foo | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:550:9:550:24 | ProtectedMethods | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:550:9:550:28 | call to new | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:550:9:550:32 | call to bar | calls.rb:539:1:552:3 | ProtectedMethods |
+| calls.rb:554:1:554:16 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:554:1:554:20 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:554:1:554:24 | call to foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:555:1:555:16 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:555:1:555:20 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:555:1:555:24 | call to bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:556:1:556:16 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:556:1:556:20 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:556:1:556:24 | call to baz | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:558:1:563:3 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:558:29:558:44 | ProtectedMethods | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:559:5:562:7 | baz | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:560:9:560:11 | call to foo | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:560:9:560:11 | self | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:561:9:561:27 | ProtectedMethodsSub | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:561:9:561:31 | call to new | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:561:9:561:35 | call to foo | calls.rb:558:1:563:3 | ProtectedMethodsSub |
+| calls.rb:565:1:565:19 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:565:1:565:23 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:565:1:565:27 | call to foo | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:566:1:566:19 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:566:1:566:23 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:566:1:566:27 | call to bar | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:567:1:567:19 | ProtectedMethodsSub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:567:1:567:23 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:567:1:567:27 | call to baz | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:1:569:7 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:1:569:7 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:1:569:7 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:1:569:26 | call to each | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:2:569:2 | C | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:2:569:6 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:14:569:26 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:17:569:17 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:17:569:17 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:20:569:20 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:569:20:569:24 | call to baz | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:1:570:13 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:1:570:13 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:1:570:13 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:1:570:39 | call to each | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:2:570:4 | "a" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:3:570:3 | a | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:6:570:8 | "b" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:7:570:7 | b | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:10:570:12 | "c" | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:11:570:11 | c | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:20:570:39 | { ... } | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:23:570:23 | s | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:23:570:23 | s | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:26:570:26 | s | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:570:26:570:37 | call to capitalize | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:572:1:575:3 | SingletonUpCall_Base | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:573:5:574:7 | singleton | calls.rb:572:1:575:3 | SingletonUpCall_Base |
+| calls.rb:573:9:573:12 | self | calls.rb:572:1:575:3 | SingletonUpCall_Base |
+| calls.rb:576:1:583:3 | SingletonUpCall_Sub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:576:29:576:48 | SingletonUpCall_Base | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:577:5:577:13 | call to singleton | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:577:5:577:13 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:578:5:578:14 | call to singleton2 | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:578:5:578:14 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:579:5:582:7 | mid_method | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:579:9:579:12 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:580:9:580:17 | call to singleton | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:580:9:580:17 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:581:9:581:18 | call to singleton2 | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:581:9:581:18 | self | calls.rb:576:1:583:3 | SingletonUpCall_Sub |
+| calls.rb:584:1:589:3 | SingletonUpCall_SubSub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:584:32:584:50 | SingletonUpCall_Sub | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:585:5:586:7 | singleton2 | calls.rb:584:1:589:3 | SingletonUpCall_SubSub |
+| calls.rb:585:9:585:12 | self | calls.rb:584:1:589:3 | SingletonUpCall_SubSub |
+| calls.rb:588:5:588:14 | call to mid_method | calls.rb:584:1:589:3 | SingletonUpCall_SubSub |
+| calls.rb:588:5:588:14 | self | calls.rb:584:1:589:3 | SingletonUpCall_SubSub |
+| calls.rb:591:1:602:3 | SingletonA | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:592:5:593:7 | singleton1 | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:592:9:592:12 | self | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:595:5:597:7 | call_singleton1 | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:595:9:595:12 | self | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:596:9:596:18 | call to singleton1 | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:596:9:596:18 | self | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:599:5:601:7 | call_call_singleton1 | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:599:9:599:12 | self | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:600:9:600:23 | call to call_singleton1 | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:600:9:600:23 | self | calls.rb:591:1:602:3 | SingletonA |
+| calls.rb:604:1:611:3 | SingletonB | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:604:20:604:29 | SingletonA | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:605:5:606:7 | singleton1 | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:605:9:605:12 | self | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:608:5:610:7 | call_singleton1 | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:608:9:608:12 | self | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:609:9:609:18 | call to singleton1 | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:609:9:609:18 | self | calls.rb:604:1:611:3 | SingletonB |
+| calls.rb:613:1:620:3 | SingletonC | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:613:20:613:29 | SingletonA | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:614:5:615:7 | singleton1 | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:614:9:614:12 | self | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:617:5:619:7 | call_singleton1 | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:617:9:617:12 | self | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:618:9:618:18 | call to singleton1 | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:618:9:618:18 | self | calls.rb:613:1:620:3 | SingletonC |
+| calls.rb:622:1:622:10 | SingletonA | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:622:1:622:31 | call to call_call_singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:623:1:623:10 | SingletonB | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:623:1:623:31 | call to call_call_singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:624:1:624:10 | SingletonC | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:624:1:624:31 | call to call_call_singleton1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:626:1:632:3 | Included | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:627:5:629:7 | foo | calls.rb:626:1:632:3 | Included |
+| calls.rb:628:9:628:12 | self | calls.rb:626:1:632:3 | Included |
+| calls.rb:628:9:628:16 | call to bar | calls.rb:626:1:632:3 | Included |
+| calls.rb:630:5:631:7 | bar | calls.rb:626:1:632:3 | Included |
+| calls.rb:634:1:639:3 | IncludesIncluded | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:635:5:635:20 | call to include | calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:635:5:635:20 | self | calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:635:13:635:20 | Included | calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:636:5:638:7 | bar | calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:637:9:637:13 | super call to bar | calls.rb:634:1:639:3 | IncludesIncluded |
+| calls.rb:641:1:645:3 | CustomNew1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:642:5:644:7 | new | calls.rb:641:1:645:3 | CustomNew1 |
+| calls.rb:642:9:642:12 | self | calls.rb:641:1:645:3 | CustomNew1 |
+| calls.rb:643:9:643:10 | C1 | calls.rb:641:1:645:3 | CustomNew1 |
+| calls.rb:643:9:643:14 | call to new | calls.rb:641:1:645:3 | CustomNew1 |
+| calls.rb:647:1:647:10 | CustomNew1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:647:1:647:14 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:647:1:647:23 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:649:1:657:3 | CustomNew2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:650:5:652:7 | new | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:650:9:650:12 | self | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:651:9:651:12 | self | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:651:9:651:21 | call to allocate | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:654:5:656:7 | instance | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:655:9:655:34 | call to puts | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:655:9:655:34 | self | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:655:14:655:34 | "CustomNew2#instance" | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:655:15:655:33 | CustomNew2#instance | calls.rb:649:1:657:3 | CustomNew2 |
+| calls.rb:659:1:659:10 | CustomNew2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:659:1:659:14 | call to new | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:659:1:659:23 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:661:1:665:3 | capture_parameter | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:661:23:661:23 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:661:23:661:23 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:5:662:11 | Array | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:5:662:11 | [...] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:5:662:11 | call to [] | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:5:664:7 | call to each | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:6:662:6 | 0 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:8:662:8 | 1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:10:662:10 | 2 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:662:18:664:7 | do ... end | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:663:9:663:9 | x | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:667:1:667:26 | ( ... ) | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:667:1:667:35 | call to instance | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:667:2:667:25 | call to capture_parameter | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:667:2:667:25 | self | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:667:20:667:21 | C1 | calls.rb:1:1:667:52 | calls.rb |
+| calls.rb:667:20:667:25 | call to new | calls.rb:1:1:667:52 | calls.rb |
| hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:22:3 | hello.rb |
| hello.rb:2:5:4:7 | hello | hello.rb:1:1:8:3 | EnglishWords |
| hello.rb:3:9:3:22 | return | hello.rb:1:1:8:3 | EnglishWords |
diff --git a/ruby/ql/test/library-tests/modules/superclasses.expected b/ruby/ql/test/library-tests/modules/superclasses.expected
index a2c3473098b..358fe7fb4e9 100644
--- a/ruby/ql/test/library-tests/modules/superclasses.expected
+++ b/ruby/ql/test/library-tests/modules/superclasses.expected
@@ -90,62 +90,62 @@ calls.rb:
# 325| C1
#-----| -> Object
-# 331| C2
+# 335| C2
#-----| -> C1
-# 337| C3
+# 341| C3
#-----| -> C2
-# 377| SingletonOverride1
+# 385| SingletonOverride1
#-----| -> Object
-# 412| SingletonOverride2
+# 420| SingletonOverride2
#-----| -> SingletonOverride1
-# 433| ConditionalInstanceMethods
+# 441| ConditionalInstanceMethods
#-----| -> Object
-# 496| ExtendSingletonMethod
+# 504| ExtendSingletonMethod
-# 506| ExtendSingletonMethod2
+# 514| ExtendSingletonMethod2
-# 512| ExtendSingletonMethod3
+# 520| ExtendSingletonMethod3
-# 525| ProtectedMethodInModule
+# 533| ProtectedMethodInModule
-# 531| ProtectedMethods
+# 539| ProtectedMethods
#-----| -> Object
-# 550| ProtectedMethodsSub
+# 558| ProtectedMethodsSub
#-----| -> ProtectedMethods
-# 564| SingletonUpCall_Base
+# 572| SingletonUpCall_Base
#-----| -> Object
-# 568| SingletonUpCall_Sub
+# 576| SingletonUpCall_Sub
#-----| -> SingletonUpCall_Base
-# 576| SingletonUpCall_SubSub
+# 584| SingletonUpCall_SubSub
#-----| -> SingletonUpCall_Sub
-# 583| SingletonA
+# 591| SingletonA
#-----| -> Object
-# 596| SingletonB
+# 604| SingletonB
#-----| -> SingletonA
-# 605| SingletonC
+# 613| SingletonC
#-----| -> SingletonA
-# 618| Included
+# 626| Included
-# 626| IncludesIncluded
+# 634| IncludesIncluded
#-----| -> Object
-# 633| CustomNew1
+# 641| CustomNew1
#-----| -> Object
-# 641| CustomNew2
+# 649| CustomNew2
#-----| -> Object
hello.rb:
From 826b6219a0bb35104d1ce644119b387e63eb7e34 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Mon, 8 May 2023 11:39:38 +0200
Subject: [PATCH 36/67] Ruby: Include `self` parameters in type tracking
flow-through logic
---
.../ruby/dataflow/internal/DataFlowPrivate.qll | 12 ++++++++----
.../codeql/ruby/typetracking/TypeTrackerSpecific.qll | 6 ++----
.../ql/test/library-tests/modules/callgraph.expected | 1 +
3 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
index 18abb552709..cbdb38d5803 100644
--- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
+++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll
@@ -940,6 +940,12 @@ private class NewCall extends DataFlowCall {
abstract class ReturningNode extends Node {
/** Gets the kind of this return node. */
abstract ReturnKind getKind();
+
+ pragma[nomagic]
+ predicate hasKind(ReturnKind kind, CfgScope scope) {
+ kind = this.getKind() and
+ scope = this.(NodeImpl).getCfgScope()
+ }
}
/** A data-flow node that represents a value returned by a callable. */
@@ -1060,10 +1066,8 @@ private module ReturnNodes {
SynthReturnNode() { this = TSynthReturnNode(scope, kind) }
/** Gets a syntactic return node that flows into this synthetic node. */
- ReturningNode getAnInput() {
- result.(NodeImpl).getCfgScope() = scope and
- result.getKind() = kind
- }
+ pragma[nomagic]
+ ReturningNode getAnInput() { result.hasKind(kind, scope) }
override ReturnKind getKind() { result = kind }
diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll
index 69ac88c777e..7402b9ea18e 100644
--- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll
+++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll
@@ -80,10 +80,8 @@ predicate jumpStep = DataFlowPrivate::jumpStep/2;
pragma[nomagic]
private predicate flowThrough(DataFlowPublic::ParameterNode param) {
exists(DataFlowPrivate::ReturningNode returnNode, DataFlowDispatch::ReturnKind rk |
- DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter())
- .(TypeTrackingNode)
- .flowsTo(returnNode) and
- rk = returnNode.getKind()
+ param.flowsTo(returnNode) and
+ returnNode.hasKind(rk, param.(DataFlowPrivate::NodeImpl).getCfgScope())
|
rk instanceof DataFlowDispatch::NormalReturnKind
or
diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected
index 01b57aab2f8..cadc31e6940 100644
--- a/ruby/ql/test/library-tests/modules/callgraph.expected
+++ b/ruby/ql/test/library-tests/modules/callgraph.expected
@@ -153,6 +153,7 @@ getTarget
| calls.rb:383:1:383:23 | call to instance | calls.rb:326:5:328:7 | instance |
| calls.rb:383:1:383:23 | call to instance | calls.rb:336:5:338:7 | instance |
| calls.rb:383:1:383:23 | call to instance | calls.rb:342:5:344:7 | instance |
+| calls.rb:383:1:383:23 | call to instance | calls.rb:375:5:377:7 | instance |
| calls.rb:388:13:388:48 | call to puts | calls.rb:102:5:102:30 | puts |
| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:387:9:389:11 | singleton1 |
| calls.rb:392:13:392:22 | call to singleton1 | calls.rb:422:9:424:11 | singleton1 |
From 4781881a6a8111b5d3c079df2be8c4b41b88336e Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 15 May 2023 14:43:01 +0100
Subject: [PATCH 37/67] Swift: Improve mobile/phone number regexp.
---
swift/ql/lib/codeql/swift/security/SensitiveExprs.qll | 2 +-
.../query-tests/Security/CWE-311/CleartextTransmission.expected | 2 --
.../test/query-tests/Security/CWE-311/SensitiveExprs.expected | 1 -
swift/ql/test/query-tests/Security/CWE-311/testSend.swift | 2 +-
4 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
index c1bc5d0bd50..91f824aa5f2 100644
--- a/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
+++ b/swift/ql/lib/codeql/swift/security/SensitiveExprs.qll
@@ -48,7 +48,7 @@ class SensitivePrivateInfo extends SensitiveDataType, TPrivateInfo {
// Contact information, such as home addresses
"post.?code|zip.?code|home.?address|" +
// and telephone numbers
- "telephone|home.?phone|mobile|fax.?no|fax.?number|" +
+ "(mob(ile)?|home).?(num|no|tel|phone)|(tel|fax).?(num|no)|telephone|" +
// Geographic location - where the user is (or was)
"latitude|longitude|" +
// Financial data - such as credit card numbers, salary, bank accounts, and debts
diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
index 32a04544c2f..94272faf6d0 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextTransmission.expected
@@ -38,7 +38,6 @@ nodes
| testSend.swift:61:27:61:27 | str3 | semmle.label | str3 |
| testSend.swift:65:27:65:27 | license_key | semmle.label | license_key |
| testSend.swift:66:27:66:30 | .mobileNumber | semmle.label | .mobileNumber |
-| testSend.swift:68:27:68:30 | .mobilePlayer | semmle.label | .mobilePlayer |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| testURL.swift:13:54:13:54 | passwd | semmle.label | passwd |
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
@@ -58,7 +57,6 @@ subpaths
| testSend.swift:61:27:61:27 | str3 | testSend.swift:54:17:54:17 | password | testSend.swift:61:27:61:27 | str3 | This operation transmits 'str3', which may contain unencrypted sensitive data from $@. | testSend.swift:54:17:54:17 | password | password |
| testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | testSend.swift:65:27:65:27 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | testSend.swift:65:27:65:27 | license_key | license_key |
| testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | testSend.swift:66:27:66:30 | .mobileNumber | This operation transmits '.mobileNumber', which may contain unencrypted sensitive data from $@. | testSend.swift:66:27:66:30 | .mobileNumber | .mobileNumber |
-| testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | testSend.swift:68:27:68:30 | .mobilePlayer | This operation transmits '.mobilePlayer', which may contain unencrypted sensitive data from $@. | testSend.swift:68:27:68:30 | .mobilePlayer | .mobilePlayer |
| testURL.swift:13:22:13:54 | ... .+(_:_:) ... | testURL.swift:13:54:13:54 | passwd | testURL.swift:13:22:13:54 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:13:54:13:54 | passwd | passwd |
| testURL.swift:16:22:16:55 | ... .+(_:_:) ... | testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testURL.swift:16:55:16:55 | credit_card_no | credit_card_no |
| testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | testURL.swift:20:22:20:22 | passwd | This operation transmits 'passwd', which may contain unencrypted sensitive data from $@. | testURL.swift:20:22:20:22 | passwd | passwd |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
index ebda7360324..20e1757c132 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
+++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected
@@ -128,7 +128,6 @@
| testSend.swift:57:27:57:27 | password | label:password, type:credential |
| testSend.swift:65:27:65:27 | license_key | label:license_key, type:credential |
| testSend.swift:66:27:66:30 | .mobileNumber | label:mobileNumber, type:private information |
-| testSend.swift:68:27:68:30 | .mobilePlayer | label:mobilePlayer, type:private information |
| testSend.swift:69:27:69:30 | .passwordFeatureEnabled | label:passwordFeatureEnabled, type:credential |
| testURL.swift:13:54:13:54 | passwd | label:passwd, type:credential |
| testURL.swift:16:55:16:55 | credit_card_no | label:credit_card_no, type:private information |
diff --git a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
index ee6bf6beaf5..e7021f6e99a 100644
--- a/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
+++ b/swift/ql/test/query-tests/Security/CWE-311/testSend.swift
@@ -65,6 +65,6 @@ func test2(password : String, license_key: String, ms: MyStruct, connection : NW
connection.send(content: license_key, completion: .idempotent) // BAD
connection.send(content: ms.mobileNumber, completion: .idempotent) // BAD
connection.send(content: ms.mobileUrl, completion: .idempotent) // GOOD (not sensitive)
- connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive) [FALSE POSITIVE]
+ connection.send(content: ms.mobilePlayer, completion: .idempotent) // GOOD (not sensitive)
connection.send(content: ms.passwordFeatureEnabled, completion: .idempotent) // GOOD (not sensitive)
}
From 7a338c408e6c0220eb16976de0e83926f2a64091 Mon Sep 17 00:00:00 2001
From: erik-krogh
Date: Mon, 15 May 2023 17:23:40 +0200
Subject: [PATCH 38/67] fix typo, the variable in the example is called `items`
---
.../Security/CWE-915/PrototypePollutingAssignment.inc.qhelp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp
index b88457431bf..f4e972832c6 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp
@@ -35,8 +35,8 @@
In the example below, the untrusted value req.params.id is used as the property name
req.session.todos[id]. If a malicious user passes in the ID value __proto__,
- the variable todo will then refer to Object.prototype.
- Finally, the modification of todo then allows the attacker to inject arbitrary properties
+ the variable items will then refer to Object.prototype.
+ Finally, the modification of items then allows the attacker to inject arbitrary properties
onto Object.prototype.
From 2ebce99eae858989eebc331f841040e25f36e72f Mon Sep 17 00:00:00 2001
From: erik-krogh
Date: Mon, 15 May 2023 17:24:02 +0200
Subject: [PATCH 39/67] add another example of how to fix the prototype
pollution issue
---
.../PrototypePollutingAssignment.inc.qhelp | 6 ++++++
.../PrototypePollutingAssignmentFixed2.js | 16 ++++++++++++++++
2 files changed, 22 insertions(+)
create mode 100644 javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp
index f4e972832c6..bb0cd344070 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.inc.qhelp
@@ -48,6 +48,12 @@
+
+
+ Another way to fix it is to prevent the __proto__ property from being used as a key, as shown below:
+
+
+
diff --git a/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js
new file mode 100644
index 00000000000..74bc9a18f24
--- /dev/null
+++ b/javascript/ql/src/Security/CWE-915/examples/PrototypePollutingAssignmentFixed2.js
@@ -0,0 +1,16 @@
+let express = require('express');
+let app = express()
+
+app.put('/todos/:id', (req, res) => {
+ let id = req.params.id;
+ if (id === '__proto__' || id === 'constructor' || id === 'prototype') {
+ res.end(403);
+ return;
+ }
+ let items = req.session.todos[id];
+ if (!items) {
+ items = req.session.todos[id] = {};
+ }
+ items[req.query.name] = req.query.text;
+ res.end(200);
+});
From 7d79d87d48a8ae10d5f08db47a40d3c29de4291d Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 15 May 2023 17:39:35 +0200
Subject: [PATCH 40/67] Add XPath.evaluate as XXE sink
---
.../semmle/code/java/security/XmlParsers.qll | 27 +++++++++++---
.../change-notes/2023-05-15-xpath-xxe-sink.md | 4 +++
.../CWE-611/XPathExpressionTests.java | 35 +++++++++++++------
.../query-tests/security/CWE-611/XXE.expected | 12 ++++---
4 files changed, 59 insertions(+), 19 deletions(-)
create mode 100644 java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md
diff --git a/java/ql/lib/semmle/code/java/security/XmlParsers.qll b/java/ql/lib/semmle/code/java/security/XmlParsers.qll
index dd28d8b0117..230b102bd5e 100644
--- a/java/ql/lib/semmle/code/java/security/XmlParsers.qll
+++ b/java/ql/lib/semmle/code/java/security/XmlParsers.qll
@@ -655,6 +655,11 @@ class XmlReader extends RefType {
XmlReader() { this.hasQualifiedName("org.xml.sax", "XMLReader") }
}
+/** The class `org.xml.sax.InputSource`. */
+class InputSource extends Class {
+ InputSource() { this.hasQualifiedName("org.xml.sax", "InputSource") }
+}
+
/** DEPRECATED: Alias for XmlReader */
deprecated class XMLReader = XmlReader;
@@ -1164,22 +1169,34 @@ class XmlUnmarshal extends XmlParserCall {
}
/* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */
-/** The class `javax.xml.xpath.XPathExpression`. */
-class XPathExpression extends RefType {
+/** The interface `javax.xml.xpath.XPathExpression`. */
+class XPathExpression extends Interface {
XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") }
}
-/** A call to `XPathExpression.evaluate`. */
+/** The interface `java.xml.xpath.XPath`. */
+class XPath extends Interface {
+ XPath() { this.hasQualifiedName("javax.xml.xpath", "XPath") }
+}
+
+/** A call to the method `evaluate` of the classes `XPathExpression` or `XPath`. */
class XPathEvaluate extends XmlParserCall {
+ Argument sink;
+
XPathEvaluate() {
exists(Method m |
this.getMethod() = m and
- m.getDeclaringType() instanceof XPathExpression and
m.hasName("evaluate")
+ |
+ m.getDeclaringType().getASourceSupertype*() instanceof XPathExpression and
+ sink = this.getArgument(0)
+ or
+ m.getDeclaringType().getASourceSupertype*() instanceof XPath and
+ sink = this.getArgument(1)
)
}
- override Expr getSink() { result = this.getArgument(0) }
+ override Expr getSink() { result = sink }
override predicate isSafe() { none() }
}
diff --git a/java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md b/java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md
new file mode 100644
index 00000000000..1696ffbd213
--- /dev/null
+++ b/java/ql/src/change-notes/2023-05-15-xpath-xxe-sink.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The queries `java/xxe` and `java/xxe-local` now recognize the second argument of calls to `XPath.evaluate` as a sink.
diff --git a/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java b/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java
index 1d67b9a055f..e15c28e41e2 100644
--- a/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java
+++ b/java/ql/test/query-tests/security/CWE-611/XPathExpressionTests.java
@@ -12,18 +12,33 @@ public class XPathExpressionTests {
public void safeXPathExpression(Socket sock) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
- DocumentBuilder builder = factory.newDocumentBuilder();
- XPathFactory xFactory = XPathFactory.newInstance();
- XPath path = xFactory.newXPath();
- XPathExpression expr = path.compile("");
- expr.evaluate(builder.parse(sock.getInputStream())); //safe
+ factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ XPathFactory xFactory = XPathFactory.newInstance();
+ XPath path = xFactory.newXPath();
+ XPathExpression expr = path.compile("");
+ expr.evaluate(builder.parse(sock.getInputStream())); // safe
}
public void unsafeExpressionTests(Socket sock) throws Exception {
- XPathFactory xFactory = XPathFactory.newInstance();
- XPath path = xFactory.newXPath();
- XPathExpression expr = path.compile("");
- expr.evaluate(new InputSource(sock.getInputStream())); //unsafe
+ XPathFactory xFactory = XPathFactory.newInstance();
+ XPath path = xFactory.newXPath();
+ XPathExpression expr = path.compile("");
+ expr.evaluate(new InputSource(sock.getInputStream())); // unsafe
+ }
+
+ public void safeXPathEvaluateTest(Socket sock) throws Exception {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ XPathFactory xFactory = XPathFactory.newInstance();
+ XPath path = xFactory.newXPath();
+ path.evaluate("", builder.parse(sock.getInputStream()));
+ }
+
+ public void unsafeXPathEvaluateTest(Socket sock) throws Exception {
+ XPathFactory xFactory = XPathFactory.newInstance();
+ XPath path = xFactory.newXPath();
+ path.evaluate("", new InputSource(sock.getInputStream())); // unsafe
}
}
diff --git a/java/ql/test/query-tests/security/CWE-611/XXE.expected b/java/ql/test/query-tests/security/CWE-611/XXE.expected
index 6304e3582a2..bfc1eca96c0 100644
--- a/java/ql/test/query-tests/security/CWE-611/XXE.expected
+++ b/java/ql/test/query-tests/security/CWE-611/XXE.expected
@@ -74,7 +74,8 @@ edges
| XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) |
| XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) |
| XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) |
-| XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) |
+| XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:19:27:56 | new InputSource(...) |
+| XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | XPathExpressionTests.java:42:23:42:60 | new InputSource(...) |
nodes
| DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | semmle.label | getInputStream(...) |
| DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | semmle.label | getInputStream(...) |
@@ -235,8 +236,10 @@ nodes
| XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | semmle.label | new InputSource(...) |
| XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
-| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | semmle.label | new InputSource(...) |
-| XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | semmle.label | new InputSource(...) |
+| XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
+| XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | semmle.label | new InputSource(...) |
+| XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | semmle.label | getInputStream(...) : InputStream |
| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | semmle.label | getInputStream(...) |
| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | semmle.label | getInputStream(...) |
@@ -336,7 +339,8 @@ subpaths
| XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user-provided value |
| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user-provided value |
-| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) | user-provided value |
+| XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | XPathExpressionTests.java:27:35:27:55 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:19:27:56 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:27:35:27:55 | getInputStream(...) | user-provided value |
+| XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | XPathExpressionTests.java:42:39:42:59 | getInputStream(...) : InputStream | XPathExpressionTests.java:42:23:42:60 | new InputSource(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XPathExpressionTests.java:42:39:42:59 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user-provided value |
| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XML parsing depends on a $@ without guarding against external entity expansion. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user-provided value |
From 8db945a11e177e8ccf6cc5409996beec31a166ee Mon Sep 17 00:00:00 2001
From: Alexandre Boulgakov
Date: Mon, 15 May 2023 20:51:31 +0100
Subject: [PATCH 41/67] Swift: Use `...` to find and run all Bazel tests
instead of having to list them.
---
swift/actions/build-and-test/action.yml | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/swift/actions/build-and-test/action.yml b/swift/actions/build-and-test/action.yml
index 2e084e9a97b..f800bd3ffc2 100644
--- a/swift/actions/build-and-test/action.yml
+++ b/swift/actions/build-and-test/action.yml
@@ -53,21 +53,16 @@ runs:
shell: bash
run: |
bazel run //swift:create-extractor-pack
- - name: Run xcode-autobuilder tests
- if : ${{ github.event_name == 'pull_request' && runner.os == 'macOS' }}
- shell: bash
- run: |
- bazel test //swift/xcode-autobuilder/tests
- name: Run codegen tests
if : ${{ github.event_name == 'pull_request' }}
shell: bash
run: |
- bazel test //misc/codegen/test
- - name: Run qltest tests
- if : ${{ github.event_name == 'pull_request' }}
+ bazel test //misc/codegen/...
+ - name: Run Swift tests
+ if: ${{ github.event_name == 'pull_request' }}
shell: bash
run: |
- bazel test //swift/tools/test/qltest
+ bazel test //swift/...
- name: Evict bazel cache
if: ${{ github.event_name != 'pull_request' }}
shell: bash
From bfb098c3d6bf618ca28149313882b42455964776 Mon Sep 17 00:00:00 2001
From: Kasper Svendsen
Date: Tue, 16 May 2023 08:45:52 +0200
Subject: [PATCH 42/67] Enable implicit this warnings for shared packs
---
shared/regex/qlpack.yml | 1 +
shared/ssa/qlpack.yml | 1 +
shared/tutorial/qlpack.yml | 1 +
shared/typetracking/qlpack.yml | 1 +
shared/typos/qlpack.yml | 1 +
shared/util/qlpack.yml | 1 +
shared/yaml/qlpack.yml | 1 +
7 files changed, 7 insertions(+)
diff --git a/shared/regex/qlpack.yml b/shared/regex/qlpack.yml
index bd61542e004..ef9519ead25 100644
--- a/shared/regex/qlpack.yml
+++ b/shared/regex/qlpack.yml
@@ -3,3 +3,4 @@ version: 0.0.13-dev
groups: shared
library: true
dependencies:
+warnOnImplicitThis: true
diff --git a/shared/ssa/qlpack.yml b/shared/ssa/qlpack.yml
index 6c1e42e1950..4bb3d04e800 100644
--- a/shared/ssa/qlpack.yml
+++ b/shared/ssa/qlpack.yml
@@ -2,3 +2,4 @@ name: codeql/ssa
version: 0.0.17-dev
groups: shared
library: true
+warnOnImplicitThis: true
diff --git a/shared/tutorial/qlpack.yml b/shared/tutorial/qlpack.yml
index 4ac2f206cba..37c2fca38b4 100644
--- a/shared/tutorial/qlpack.yml
+++ b/shared/tutorial/qlpack.yml
@@ -3,3 +3,4 @@ description: Library for the CodeQL detective tutorials, helping new users learn
version: 0.0.10-dev
groups: shared
library: true
+warnOnImplicitThis: true
diff --git a/shared/typetracking/qlpack.yml b/shared/typetracking/qlpack.yml
index 239091ead67..499f5cc4d34 100644
--- a/shared/typetracking/qlpack.yml
+++ b/shared/typetracking/qlpack.yml
@@ -4,3 +4,4 @@ groups: shared
library: true
dependencies:
codeql/util: ${workspace}
+warnOnImplicitThis: true
diff --git a/shared/typos/qlpack.yml b/shared/typos/qlpack.yml
index 7f7a802dd0b..6d0b76e1ce5 100644
--- a/shared/typos/qlpack.yml
+++ b/shared/typos/qlpack.yml
@@ -2,3 +2,4 @@ name: codeql/typos
version: 0.0.17-dev
groups: shared
library: true
+warnOnImplicitThis: true
diff --git a/shared/util/qlpack.yml b/shared/util/qlpack.yml
index f3f03fded40..8ff9a0efdb6 100644
--- a/shared/util/qlpack.yml
+++ b/shared/util/qlpack.yml
@@ -3,3 +3,4 @@ version: 0.0.10-dev
groups: shared
library: true
dependencies:
+warnOnImplicitThis: true
diff --git a/shared/yaml/qlpack.yml b/shared/yaml/qlpack.yml
index f08abe18bfc..75a796f2ba3 100644
--- a/shared/yaml/qlpack.yml
+++ b/shared/yaml/qlpack.yml
@@ -2,3 +2,4 @@ name: codeql/yaml
version: 0.0.2-dev
groups: shared
library: true
+warnOnImplicitThis: true
From 145eaf3947f8cd49be3ccf502ee0d270b3cf4c79 Mon Sep 17 00:00:00 2001
From: Rasmus Lerchedahl Petersen
Date: Fri, 12 May 2023 13:29:27 +0200
Subject: [PATCH 43/67] python: remove steps for container constructors
---
.../new/internal/TaintTrackingPrivate.qll | 7 -------
.../test_collections.py | 20 +++++++++----------
.../frameworks/aiohttp/taint_test.py | 2 +-
.../frameworks/flask/taint_test.py | 2 +-
.../frameworks/multidict/taint_test.py | 4 ++--
5 files changed, 14 insertions(+), 21 deletions(-)
diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
index f7b5fc45f09..b19ed79928b 100644
--- a/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
+++ b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
@@ -181,13 +181,6 @@ predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
// don't provide that right now.
DataFlowPrivate::comprehensionStoreStep(nodeFrom, _, nodeTo)
or
- // constructor call
- exists(DataFlow::CallCfgNode call | call = nodeTo |
- call = API::builtin(["list", "set", "frozenset", "dict", "tuple"]).getACall() and
- call.getArg(0) = nodeFrom
- // TODO: Properly handle defaultdict/namedtuple
- )
- or
// functions operating on collections
exists(DataFlow::CallCfgNode call | call = nodeTo |
call = API::builtin(["sorted", "reversed", "iter", "next"]).getACall() and
diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py
index df30a75c3e3..96804ebe3d3 100644
--- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py
+++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py
@@ -28,19 +28,19 @@ def test_construction():
)
ensure_tainted(
- list(tainted_list), # $ tainted
- list(tainted_tuple), # $ tainted
- list(tainted_set), # $ tainted
- list(tainted_dict.values()), # $ tainted
- list(tainted_dict.items()), # $ tainted
+ list(tainted_list), # $ MISSING: tainted
+ list(tainted_tuple), # $ MISSING: tainted
+ list(tainted_set), # $ MISSING: tainted
+ list(tainted_dict.values()), # $ MISSING: tainted
+ list(tainted_dict.items()), # $ MISSING: tainted
- tuple(tainted_list), # $ tainted
- set(tainted_list), # $ tainted
- frozenset(tainted_list), # $ tainted
- dict(tainted_dict), # $ tainted
+ tuple(tainted_list), # $ MISSING: tainted
+ set(tainted_list), # $ MISSING: tainted
+ frozenset(tainted_list), # $ MISSING: tainted
+ dict(tainted_dict), # $ MISSING: tainted
dict(k = tainted_string)["k"], # $ MISSING: tainted
dict(dict(k = tainted_string))["k"], # $ MISSING: tainted
- dict(["k", tainted_string]), # $ tainted
+ dict(["k", tainted_string]), # $ MISSING: tainted
)
ensure_not_tainted(
diff --git a/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py b/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py
index ec475a592ab..0dcbbef1ffa 100644
--- a/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py
@@ -42,7 +42,7 @@ async def test_taint(request: web.Request): # $ requestHandler
request.cookies.keys(), # $ MISSING: tainted
request.cookies.values(), # $ tainted
request.cookies.items(), # $ tainted
- list(request.cookies), # $ tainted
+ list(request.cookies), # $ MISSING: tainted
iter(request.cookies), # $ tainted
diff --git a/python/ql/test/library-tests/frameworks/flask/taint_test.py b/python/ql/test/library-tests/frameworks/flask/taint_test.py
index dcca8ff6681..510a6d30550 100644
--- a/python/ql/test/library-tests/frameworks/flask/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/flask/taint_test.py
@@ -112,7 +112,7 @@ def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler route
request.headers.popitem()[0], # $ tainted
request.headers.popitem()[1], # $ tainted
# two ways to get (k, v) lists
- list(request.headers), # $ tainted
+ list(request.headers), # $ MISSING: tainted
request.headers.to_wsgi_list(), # $ tainted
request.json, # $ tainted
diff --git a/python/ql/test/library-tests/frameworks/multidict/taint_test.py b/python/ql/test/library-tests/frameworks/multidict/taint_test.py
index 8fbac79888f..5e346a5df4b 100644
--- a/python/ql/test/library-tests/frameworks/multidict/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/multidict/taint_test.py
@@ -16,7 +16,7 @@ ensure_tainted(
mdp.values(), # $ tainted
mdp.items(), # $ tainted
mdp.copy(), # $ tainted
- list(mdp), # $ tainted
+ list(mdp), # $ MISSING: tainted
iter(mdp), # $ tainted
)
@@ -36,6 +36,6 @@ ensure_tainted(
ci_mdp.values(), # $ tainted
ci_mdp.items(), # $ tainted
ci_mdp.copy(), # $ tainted
- list(ci_mdp), # $ tainted
+ list(ci_mdp), # $ MISSING: tainted
iter(ci_mdp), # $ tainted
)
From 03ef18b286fd8db4444a78b00a9cd124bef7d255 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 16 May 2023 11:55:07 +0100
Subject: [PATCH 44/67] Swift: Recommend a proper source of randomness in
'swift/hardcoded-key'.
---
.../CWE-321/HardcodedEncryptionKey.swift | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
index 82ffaf3a94a..b3f0af7395e 100644
--- a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
+++ b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
@@ -13,13 +13,16 @@ func encrypt(padding : Padding) {
// GOOD: Using randomly generated keys for encryption
- let key = (0..<10).map({ _ in UInt8.random(in: 0...UInt8.max) })
- let keyString = String(cString: key)
- let ivString = getRandomIV()
- _ = try AES(key: key, blockMode: CBC(), padding: padding)
- _ = try AES(key: keyString, iv: ivString)
- _ = try Blowfish(key: key, blockMode: CBC(), padding: padding)
- _ = try Blowfish(key: keyString, iv: ivString)
+ var key = [Int8](repeating: 0, count: 10)
+ let status = SecRandomCopyBytes(kSecRandomDefault, key.count, &key)
+ if status == errSecSuccess {
+ let keyString = String(cString: key)
+ let ivString = getRandomIV()
+ _ = try AES(key: key, blockMode: CBC(), padding: padding)
+ _ = try AES(key: keyString, iv: ivString)
+ _ = try Blowfish(key: key, blockMode: CBC(), padding: padding)
+ _ = try Blowfish(key: keyString, iv: ivString)
+ }
// ...
}
From 5b4f98d6c422a085abe8a17e9183a8024f7baca8 Mon Sep 17 00:00:00 2001
From: Rasmus Lerchedahl Petersen
Date: Mon, 15 May 2023 11:00:43 +0200
Subject: [PATCH 45/67] python: Add summaries for container constructors Also:
- turn on flow summaries for taint - do not restrict node type (as now we
need summary nodes)
---
.../new/internal/TaintTrackingPrivate.qll | 5 +-
.../lib/semmle/python/frameworks/Stdlib.qll | 132 ++++++++++++++++++
.../dataflow/basic/callGraphSinks.expected | 5 +
.../dataflow/basic/callGraphSources.expected | 5 +
.../dataflow/basic/global.expected | 10 ++
.../dataflow/basic/globalStep.expected | 10 ++
.../dataflow/basic/local.expected | 34 +++++
.../dataflow/basic/localStep.expected | 10 ++
.../dataflow/basic/sinks.expected | 24 ++++
.../dataflow/basic/sources.expected | 24 ++++
.../dataflow/coverage/test_builtins.py | 26 ++--
.../basic/LocalTaintStep.expected | 15 ++
.../test_collections.py | 24 ++--
.../frameworks/aiohttp/taint_test.py | 2 +-
.../frameworks/flask/taint_test.py | 2 +-
.../frameworks/multidict/taint_test.py | 4 +-
16 files changed, 302 insertions(+), 30 deletions(-)
diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
index b19ed79928b..3b32d95ae0b 100644
--- a/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
+++ b/python/ql/lib/semmle/python/dataflow/new/internal/TaintTrackingPrivate.qll
@@ -1,6 +1,7 @@
private import python
private import semmle.python.dataflow.new.DataFlow
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
+private import FlowSummaryImpl as FlowSummaryImpl
private import semmle.python.dataflow.new.internal.TaintTrackingPublic
private import semmle.python.ApiGraphs
@@ -55,6 +56,8 @@ private module Cached {
awaitStep(nodeFrom, nodeTo)
or
asyncWithStep(nodeFrom, nodeTo)
+ or
+ FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
}
}
@@ -159,7 +162,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
* is currently very imprecise, as an example, since we model `dict.get`, we treat any
* `.get()` will be tainted, whether it's true or not.
*/
-predicate containerStep(DataFlow::CfgNode nodeFrom, DataFlow::Node nodeTo) {
+predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// construction by literal
//
// TODO: once we have proper flow-summary modeling, we might not need this step any
diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
index 7e62a5b033e..cd5ec31945e 100644
--- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll
+++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll
@@ -3790,6 +3790,138 @@ private module StdlibPrivate {
override DataFlow::Node getAPathArgument() { result = this.getAnInput() }
}
+ // ---------------------------------------------------------------------------
+ // Flow summaries for functions contructing containers
+ // ---------------------------------------------------------------------------
+ /** A flow summary for `dict`. */
+ class DictSummary extends SummarizedCallable {
+ DictSummary() { this = "builtins.dict" }
+
+ override DataFlow::CallCfgNode getACall() { result = API::builtin("dict").getACall() }
+
+ override DataFlow::ArgumentNode getACallback() {
+ result = API::builtin("dict").getAValueReachableFromSource()
+ }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
+ input = "Argument[0].DictionaryElement[" + key + "]" and
+ output = "ReturnValue.DictionaryElement[" + key + "]" and
+ preservesValue = true
+ )
+ or
+ exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
+ input = "Argument[" + key + ":]" and
+ output = "ReturnValue.DictionaryElement[" + key + "]" and
+ preservesValue = true
+ )
+ or
+ input = "Argument[0]" and
+ output = "ReturnValue" and
+ preservesValue = false
+ }
+ }
+
+ /** A flow summary for `list`. */
+ class ListSummary extends SummarizedCallable {
+ ListSummary() { this = "builtins.list" }
+
+ override DataFlow::CallCfgNode getACall() { result = API::builtin("list").getACall() }
+
+ override DataFlow::ArgumentNode getACallback() {
+ result = API::builtin("list").getAValueReachableFromSource()
+ }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ (
+ input = "Argument[0].ListElement"
+ or
+ input = "Argument[0].SetElement"
+ or
+ exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
+ input = "Argument[0].TupleElement[" + i.toString() + "]"
+ )
+ // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
+ ) and
+ output = "ReturnValue.ListElement" and
+ preservesValue = true
+ or
+ input = "Argument[0]" and
+ output = "ReturnValue" and
+ preservesValue = false
+ }
+ }
+
+ /** A flow summary for tuple */
+ class TupleSummary extends SummarizedCallable {
+ TupleSummary() { this = "builtins.tuple" }
+
+ override DataFlow::CallCfgNode getACall() { result = API::builtin("tuple").getACall() }
+
+ override DataFlow::ArgumentNode getACallback() {
+ result = API::builtin("tuple").getAValueReachableFromSource()
+ }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
+ input = "Argument[0].TupleElement[" + i.toString() + "]" and
+ output = "ReturnValue.TupleElement[" + i.toString() + "]" and
+ preservesValue = true
+ )
+ or
+ // TODO: We need to also translate iterable content such as list element
+ // but we currently lack TupleElementAny
+ input = "Argument[0]" and
+ output = "ReturnValue" and
+ preservesValue = false
+ }
+ }
+
+ /** A flow summary for set */
+ class SetSummary extends SummarizedCallable {
+ SetSummary() { this = "builtins.set" }
+
+ override DataFlow::CallCfgNode getACall() { result = API::builtin("set").getACall() }
+
+ override DataFlow::ArgumentNode getACallback() {
+ result = API::builtin("set").getAValueReachableFromSource()
+ }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ (
+ input = "Argument[0].ListElement"
+ or
+ input = "Argument[0].SetElement"
+ or
+ exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
+ input = "Argument[0].TupleElement[" + i.toString() + "]"
+ )
+ // TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
+ ) and
+ output = "ReturnValue.SetElement" and
+ preservesValue = true
+ or
+ input = "Argument[0]" and
+ output = "ReturnValue" and
+ preservesValue = false
+ }
+ }
+
+ /** A flow summary for frozenset */
+ class FrozensetSummary extends SummarizedCallable {
+ FrozensetSummary() { this = "builtins.frozenset" }
+
+ override DataFlow::CallCfgNode getACall() { result = API::builtin("frozenset").getACall() }
+
+ override DataFlow::ArgumentNode getACallback() {
+ result = API::builtin("frozenset").getAValueReachableFromSource()
+ }
+
+ override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
+ any(SetSummary s).propagatesFlowExt(input, output, preservesValue)
+ }
+ }
+
/** A flow summary for `reversed`. */
class ReversedSummary extends SummarizedCallable {
ReversedSummary() { this = "builtins.reversed" }
diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected
index ef35d8f5039..02c43353fbd 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected
+++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected
@@ -1,4 +1,9 @@
+| file://:0:0:0:0 | parameter position 0 of builtins.dict |
+| file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
+| file://:0:0:0:0 | parameter position 0 of builtins.list |
| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
+| file://:0:0:0:0 | parameter position 0 of builtins.set |
+| file://:0:0:0:0 | parameter position 0 of builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:1:1:1:21 | SynthDictSplatParameterNode |
| test.py:1:19:1:19 | ControlFlowNode for x |
diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected
index 74d546c5f2b..5ef30fa5871 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected
+++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected
@@ -1,4 +1,9 @@
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:4:10:4:10 | ControlFlowNode for z |
| test.py:7:19:7:19 | ControlFlowNode for a |
diff --git a/python/ql/test/experimental/dataflow/basic/global.expected b/python/ql/test/experimental/dataflow/basic/global.expected
index 11696c17335..60511486372 100644
--- a/python/ql/test/experimental/dataflow/basic/global.expected
+++ b/python/ql/test/experimental/dataflow/basic/global.expected
@@ -1,4 +1,14 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.expected b/python/ql/test/experimental/dataflow/basic/globalStep.expected
index b11ee6fe249..79924c7d55a 100644
--- a/python/ql/test/experimental/dataflow/basic/globalStep.expected
+++ b/python/ql/test/experimental/dataflow/basic/globalStep.expected
@@ -1,4 +1,14 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
diff --git a/python/ql/test/experimental/dataflow/basic/local.expected b/python/ql/test/experimental/dataflow/basic/local.expected
index 18497a00a60..8f1455df883 100644
--- a/python/ql/test/experimental/dataflow/basic/local.expected
+++ b/python/ql/test/experimental/dataflow/basic/local.expected
@@ -1,9 +1,43 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict | file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list | file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set | file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
+| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | parameter position 0 of builtins.dict | file://:0:0:0:0 | parameter position 0 of builtins.dict |
+| file://:0:0:0:0 | parameter position 0 of builtins.frozenset | file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
+| file://:0:0:0:0 | parameter position 0 of builtins.list | file://:0:0:0:0 | parameter position 0 of builtins.list |
| file://:0:0:0:0 | parameter position 0 of builtins.reversed | file://:0:0:0:0 | parameter position 0 of builtins.reversed |
+| file://:0:0:0:0 | parameter position 0 of builtins.set | file://:0:0:0:0 | parameter position 0 of builtins.set |
+| file://:0:0:0:0 | parameter position 0 of builtins.tuple | file://:0:0:0:0 | parameter position 0 of builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ |
diff --git a/python/ql/test/experimental/dataflow/basic/localStep.expected b/python/ql/test/experimental/dataflow/basic/localStep.expected
index d05e8aa3a42..943ff65d1ea 100644
--- a/python/ql/test/experimental/dataflow/basic/localStep.expected
+++ b/python/ql/test/experimental/dataflow/basic/localStep.expected
@@ -1,4 +1,14 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
diff --git a/python/ql/test/experimental/dataflow/basic/sinks.expected b/python/ql/test/experimental/dataflow/basic/sinks.expected
index 1e516e32336..18edca26f98 100644
--- a/python/ql/test/experimental/dataflow/basic/sinks.expected
+++ b/python/ql/test/experimental/dataflow/basic/sinks.expected
@@ -1,8 +1,32 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
+| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | parameter position 0 of builtins.dict |
+| file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
+| file://:0:0:0:0 | parameter position 0 of builtins.list |
| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
+| file://:0:0:0:0 | parameter position 0 of builtins.set |
+| file://:0:0:0:0 | parameter position 0 of builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ |
| test.py:0:0:0:0 | GSSA Variable __package__ |
diff --git a/python/ql/test/experimental/dataflow/basic/sources.expected b/python/ql/test/experimental/dataflow/basic/sources.expected
index 1e516e32336..18edca26f98 100644
--- a/python/ql/test/experimental/dataflow/basic/sources.expected
+++ b/python/ql/test/experimental/dataflow/basic/sources.expected
@@ -1,8 +1,32 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
+| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | parameter position 0 of builtins.dict |
+| file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
+| file://:0:0:0:0 | parameter position 0 of builtins.list |
| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
+| file://:0:0:0:0 | parameter position 0 of builtins.set |
+| file://:0:0:0:0 | parameter position 0 of builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ |
| test.py:0:0:0:0 | GSSA Variable __package__ |
diff --git a/python/ql/test/experimental/dataflow/coverage/test_builtins.py b/python/ql/test/experimental/dataflow/coverage/test_builtins.py
index 5d9d92ffcb8..4a3ee95fedf 100644
--- a/python/ql/test/experimental/dataflow/coverage/test_builtins.py
+++ b/python/ql/test/experimental/dataflow/coverage/test_builtins.py
@@ -41,8 +41,8 @@ def SINK_F(x):
def test_list_from_list():
l1 = [SOURCE, NONSOURCE]
l2 = list(l1)
- SINK(l2[0]) #$ MISSING: flow="SOURCE, l:-2 -> l2[0]"
- SINK_F(l2[1]) # expecting FP due to imprecise flow
+ SINK(l2[0]) #$ flow="SOURCE, l:-2 -> l2[0]"
+ SINK_F(l2[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l2[1]"
# -- skip list_from_string
@@ -50,13 +50,13 @@ def test_list_from_list():
def test_list_from_tuple():
t = (SOURCE, NONSOURCE)
l = list(t)
- SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
- SINK_F(l[1]) # expecting FP due to imprecise flow
+ SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
+ SINK_F(l[1]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[1]"
def test_list_from_set():
s = {SOURCE}
l = list(s)
- SINK(l[0]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
+ SINK(l[0]) #$ flow="SOURCE, l:-2 -> l[0]"
@expects(2)
def test_list_from_dict():
@@ -78,7 +78,7 @@ def test_tuple_from_list():
def test_tuple_from_tuple():
t0 = (SOURCE, NONSOURCE)
t = tuple(t0)
- SINK(t[0]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
+ SINK(t[0]) #$ flow="SOURCE, l:-2 -> t[0]"
SINK_F(t[1])
def test_tuple_from_set():
@@ -100,19 +100,19 @@ def test_set_from_list():
l = [SOURCE]
s = set(l)
v = s.pop()
- SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v"
+ SINK(v) #$ flow="SOURCE, l:-3 -> v"
def test_set_from_tuple():
t = (SOURCE,)
s = set(t)
v = s.pop()
- SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v"
+ SINK(v) #$ flow="SOURCE, l:-3 -> v"
def test_set_from_set():
s0 = {SOURCE}
s = set(s0)
v = s.pop()
- SINK(v) #$ MISSING: flow="SOURCE, l:-3 -> v"
+ SINK(v) #$ flow="SOURCE, l:-3 -> v"
def test_set_from_dict():
d = {SOURCE: "val"}
@@ -126,7 +126,7 @@ def test_set_from_dict():
@expects(2)
def test_dict_from_keyword():
d = dict(k = SOURCE, k1 = NONSOURCE)
- SINK(d["k"]) #$ MISSING: flow="SOURCE, l:-1 -> d[k]"
+ SINK(d["k"]) #$ flow="SOURCE, l:-1 -> d['k']"
SINK_F(d["k1"])
@expects(2)
@@ -139,7 +139,7 @@ def test_dict_from_list():
def test_dict_from_dict():
d1 = {'k': SOURCE, 'k1': NONSOURCE}
d2 = dict(d1)
- SINK(d2["k"]) #$ MISSING: flow="SOURCE, l:-2 -> d[k]"
+ SINK(d2["k"]) #$ flow="SOURCE, l:-2 -> d2['k']"
SINK_F(d2["k1"])
## Container methods
@@ -278,8 +278,8 @@ def test_reversed_list():
l0 = [SOURCE, NONSOURCE]
r = reversed(l0)
l = list(r)
- SINK_F(l[0])
- SINK(l[1]) #$ MISSING: flow="SOURCE, l:-4 -> l[1]"
+ SINK_F(l[0]) #$ SPURIOUS: flow="SOURCE, l:-3 -> l[0]"
+ SINK(l[1]) #$ flow="SOURCE, l:-4 -> l[1]"
@expects(2)
def test_reversed_tuple():
diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected
index ef6f6a2929b..51fd643577a 100644
--- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected
+++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected
@@ -1,4 +1,19 @@
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
+| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
+| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
+| file://:0:0:0:0 | parameter position 0 of builtins.dict | file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
+| file://:0:0:0:0 | parameter position 0 of builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
+| file://:0:0:0:0 | parameter position 0 of builtins.list | file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
+| file://:0:0:0:0 | parameter position 0 of builtins.set | file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
+| file://:0:0:0:0 | parameter position 0 of builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:3:1:3:7 | GSSA Variable tainted | test.py:4:6:4:12 | ControlFlowNode for tainted |
| test.py:3:11:3:16 | ControlFlowNode for SOURCE | test.py:3:1:3:7 | GSSA Variable tainted |
diff --git a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py
index 96804ebe3d3..50f9a613f9b 100644
--- a/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py
+++ b/python/ql/test/experimental/dataflow/tainttracking/defaultAdditionalTaintStep/test_collections.py
@@ -28,19 +28,19 @@ def test_construction():
)
ensure_tainted(
- list(tainted_list), # $ MISSING: tainted
- list(tainted_tuple), # $ MISSING: tainted
- list(tainted_set), # $ MISSING: tainted
- list(tainted_dict.values()), # $ MISSING: tainted
- list(tainted_dict.items()), # $ MISSING: tainted
+ list(tainted_list), # $ tainted
+ list(tainted_tuple), # $ tainted
+ list(tainted_set), # $ tainted
+ list(tainted_dict.values()), # $ tainted
+ list(tainted_dict.items()), # $ tainted
- tuple(tainted_list), # $ MISSING: tainted
- set(tainted_list), # $ MISSING: tainted
- frozenset(tainted_list), # $ MISSING: tainted
- dict(tainted_dict), # $ MISSING: tainted
- dict(k = tainted_string)["k"], # $ MISSING: tainted
- dict(dict(k = tainted_string))["k"], # $ MISSING: tainted
- dict(["k", tainted_string]), # $ MISSING: tainted
+ tuple(tainted_list), # $ tainted
+ set(tainted_list), # $ tainted
+ frozenset(tainted_list), # $ tainted
+ dict(tainted_dict), # $ tainted
+ dict(k = tainted_string)["k"], # $ tainted
+ dict(dict(k = tainted_string))["k"], # $ tainted
+ dict(["k", tainted_string]), # $ tainted
)
ensure_not_tainted(
diff --git a/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py b/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py
index 0dcbbef1ffa..ec475a592ab 100644
--- a/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/aiohttp/taint_test.py
@@ -42,7 +42,7 @@ async def test_taint(request: web.Request): # $ requestHandler
request.cookies.keys(), # $ MISSING: tainted
request.cookies.values(), # $ tainted
request.cookies.items(), # $ tainted
- list(request.cookies), # $ MISSING: tainted
+ list(request.cookies), # $ tainted
iter(request.cookies), # $ tainted
diff --git a/python/ql/test/library-tests/frameworks/flask/taint_test.py b/python/ql/test/library-tests/frameworks/flask/taint_test.py
index 510a6d30550..dcca8ff6681 100644
--- a/python/ql/test/library-tests/frameworks/flask/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/flask/taint_test.py
@@ -112,7 +112,7 @@ def test_taint(name = "World!", number="0", foo="foo"): # $requestHandler route
request.headers.popitem()[0], # $ tainted
request.headers.popitem()[1], # $ tainted
# two ways to get (k, v) lists
- list(request.headers), # $ MISSING: tainted
+ list(request.headers), # $ tainted
request.headers.to_wsgi_list(), # $ tainted
request.json, # $ tainted
diff --git a/python/ql/test/library-tests/frameworks/multidict/taint_test.py b/python/ql/test/library-tests/frameworks/multidict/taint_test.py
index 5e346a5df4b..8fbac79888f 100644
--- a/python/ql/test/library-tests/frameworks/multidict/taint_test.py
+++ b/python/ql/test/library-tests/frameworks/multidict/taint_test.py
@@ -16,7 +16,7 @@ ensure_tainted(
mdp.values(), # $ tainted
mdp.items(), # $ tainted
mdp.copy(), # $ tainted
- list(mdp), # $ MISSING: tainted
+ list(mdp), # $ tainted
iter(mdp), # $ tainted
)
@@ -36,6 +36,6 @@ ensure_tainted(
ci_mdp.values(), # $ tainted
ci_mdp.items(), # $ tainted
ci_mdp.copy(), # $ tainted
- list(ci_mdp), # $ MISSING: tainted
+ list(ci_mdp), # $ tainted
iter(ci_mdp), # $ tainted
)
From 5d68473d1281bedb220c9ef365a5828dfba795a9 Mon Sep 17 00:00:00 2001
From: Rasmus Lerchedahl Petersen
Date: Mon, 15 May 2023 21:18:51 +0200
Subject: [PATCH 46/67] python: elide nodes without location from basic
---
.../experimental/dataflow/basic/callGraph.ql | 5 ++-
.../dataflow/basic/callGraphSinks.expected | 7 ----
.../dataflow/basic/callGraphSinks.ql | 4 +-
.../dataflow/basic/callGraphSources.expected | 7 ----
.../dataflow/basic/callGraphSources.ql | 4 +-
.../dataflow/basic/global.expected | 12 ------
.../experimental/dataflow/basic/global.ql | 4 +-
.../dataflow/basic/globalStep.expected | 12 ------
.../experimental/dataflow/basic/globalStep.ql | 5 ++-
.../dataflow/basic/local.expected | 42 -------------------
.../test/experimental/dataflow/basic/local.ql | 5 ++-
.../dataflow/basic/localStep.expected | 12 ------
.../experimental/dataflow/basic/localStep.ql | 5 ++-
.../dataflow/basic/maximalFlows.expected | 1 -
.../dataflow/basic/maximalFlows.ql | 4 +-
.../dataflow/basic/sinks.expected | 30 -------------
.../test/experimental/dataflow/basic/sinks.ql | 4 +-
.../dataflow/basic/sources.expected | 30 -------------
.../experimental/dataflow/basic/sources.ql | 4 +-
.../basic/LocalTaintStep.expected | 17 --------
.../tainttracking/basic/LocalTaintStep.ql | 5 ++-
21 files changed, 38 insertions(+), 181 deletions(-)
diff --git a/python/ql/test/experimental/dataflow/basic/callGraph.ql b/python/ql/test/experimental/dataflow/basic/callGraph.ql
index 2e8d6956c70..d83da4c5c11 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraph.ql
+++ b/python/ql/test/experimental/dataflow/basic/callGraph.ql
@@ -1,5 +1,8 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node source, DataFlow::Node sink
-where exists(CallGraphConfig cfg | cfg.hasFlow(source, sink))
+where
+ exists(CallGraphConfig cfg | cfg.hasFlow(source, sink)) and
+ exists(source.getLocation().getFile().getRelativePath()) and
+ exists(sink.getLocation().getFile().getRelativePath())
select source, sink
diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected
index 02c43353fbd..e4b8f905530 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected
+++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.expected
@@ -1,10 +1,3 @@
-| file://:0:0:0:0 | parameter position 0 of builtins.dict |
-| file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
-| file://:0:0:0:0 | parameter position 0 of builtins.list |
-| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
-| file://:0:0:0:0 | parameter position 0 of builtins.set |
-| file://:0:0:0:0 | parameter position 0 of builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:1:1:1:21 | SynthDictSplatParameterNode |
| test.py:1:19:1:19 | ControlFlowNode for x |
| test.py:7:5:7:20 | ControlFlowNode for obfuscated_id() |
diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql
index 7d15b353274..8b9f57a0462 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql
+++ b/python/ql/test/experimental/dataflow/basic/callGraphSinks.ql
@@ -1,5 +1,7 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node sink
-where exists(CallGraphConfig cfg | cfg.isSink(sink))
+where
+ exists(CallGraphConfig cfg | cfg.isSink(sink)) and
+ exists(sink.getLocation().getFile().getRelativePath())
select sink
diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected
index 5ef30fa5871..4023ba8f3ea 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraphSources.expected
+++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.expected
@@ -1,9 +1,2 @@
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:4:10:4:10 | ControlFlowNode for z |
| test.py:7:19:7:19 | ControlFlowNode for a |
diff --git a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql
index 21c3a5a9ace..e482a07cf39 100644
--- a/python/ql/test/experimental/dataflow/basic/callGraphSources.ql
+++ b/python/ql/test/experimental/dataflow/basic/callGraphSources.ql
@@ -1,5 +1,7 @@
import experimental.dataflow.callGraphConfig
from DataFlow::Node source
-where exists(CallGraphConfig cfg | cfg.isSource(source))
+where
+ exists(CallGraphConfig cfg | cfg.isSource(source)) and
+ exists(source.getLocation().getFile().getRelativePath())
select source
diff --git a/python/ql/test/experimental/dataflow/basic/global.expected b/python/ql/test/experimental/dataflow/basic/global.expected
index 60511486372..8894bcc190a 100644
--- a/python/ql/test/experimental/dataflow/basic/global.expected
+++ b/python/ql/test/experimental/dataflow/basic/global.expected
@@ -1,15 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
diff --git a/python/ql/test/experimental/dataflow/basic/global.ql b/python/ql/test/experimental/dataflow/basic/global.ql
index ba9a302b05b..ecab29899e3 100644
--- a/python/ql/test/experimental/dataflow/basic/global.ql
+++ b/python/ql/test/experimental/dataflow/basic/global.ql
@@ -3,5 +3,7 @@ import allFlowsConfig
from DataFlow::Node source, DataFlow::Node sink
where
source != sink and
- exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink))
+ exists(AllFlowsConfig cfg | cfg.hasFlow(source, sink)) and
+ exists(source.getLocation().getFile().getRelativePath()) and
+ exists(sink.getLocation().getFile().getRelativePath())
select source, sink
diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.expected b/python/ql/test/experimental/dataflow/basic/globalStep.expected
index 79924c7d55a..9f228998b9c 100644
--- a/python/ql/test/experimental/dataflow/basic/globalStep.expected
+++ b/python/ql/test/experimental/dataflow/basic/globalStep.expected
@@ -1,15 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
diff --git a/python/ql/test/experimental/dataflow/basic/globalStep.ql b/python/ql/test/experimental/dataflow/basic/globalStep.ql
index 18014b2cc5f..9b19749b2d8 100644
--- a/python/ql/test/experimental/dataflow/basic/globalStep.ql
+++ b/python/ql/test/experimental/dataflow/basic/globalStep.ql
@@ -1,5 +1,8 @@
import allFlowsConfig
from DataFlow::PathNode fromNode, DataFlow::PathNode toNode
-where toNode = fromNode.getASuccessor()
+where
+ toNode = fromNode.getASuccessor() and
+ exists(fromNode.getNode().getLocation().getFile().getRelativePath()) and
+ exists(toNode.getNode().getLocation().getFile().getRelativePath())
select fromNode, toNode
diff --git a/python/ql/test/experimental/dataflow/basic/local.expected b/python/ql/test/experimental/dataflow/basic/local.expected
index 8f1455df883..cdf40018ed0 100644
--- a/python/ql/test/experimental/dataflow/basic/local.expected
+++ b/python/ql/test/experimental/dataflow/basic/local.expected
@@ -1,45 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict | file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list | file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set | file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
-| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 0 of builtins.dict | file://:0:0:0:0 | parameter position 0 of builtins.dict |
-| file://:0:0:0:0 | parameter position 0 of builtins.frozenset | file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
-| file://:0:0:0:0 | parameter position 0 of builtins.list | file://:0:0:0:0 | parameter position 0 of builtins.list |
-| file://:0:0:0:0 | parameter position 0 of builtins.reversed | file://:0:0:0:0 | parameter position 0 of builtins.reversed |
-| file://:0:0:0:0 | parameter position 0 of builtins.set | file://:0:0:0:0 | parameter position 0 of builtins.set |
-| file://:0:0:0:0 | parameter position 0 of builtins.tuple | file://:0:0:0:0 | parameter position 0 of builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ | test.py:0:0:0:0 | GSSA Variable __name__ |
| test.py:0:0:0:0 | GSSA Variable __package__ | test.py:0:0:0:0 | GSSA Variable __package__ |
| test.py:0:0:0:0 | GSSA Variable b | test.py:0:0:0:0 | GSSA Variable b |
diff --git a/python/ql/test/experimental/dataflow/basic/local.ql b/python/ql/test/experimental/dataflow/basic/local.ql
index 5541cea33dc..e13013d2210 100644
--- a/python/ql/test/experimental/dataflow/basic/local.ql
+++ b/python/ql/test/experimental/dataflow/basic/local.ql
@@ -1,5 +1,8 @@
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node fromNode, DataFlow::Node toNode
-where DataFlow::localFlow(fromNode, toNode)
+where
+ DataFlow::localFlow(fromNode, toNode) and
+ exists(fromNode.getLocation().getFile().getRelativePath()) and
+ exists(toNode.getLocation().getFile().getRelativePath())
select fromNode, toNode
diff --git a/python/ql/test/experimental/dataflow/basic/localStep.expected b/python/ql/test/experimental/dataflow/basic/localStep.expected
index 943ff65d1ea..e147bb9f4fc 100644
--- a/python/ql/test/experimental/dataflow/basic/localStep.expected
+++ b/python/ql/test/experimental/dataflow/basic/localStep.expected
@@ -1,15 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:1:1:21 | ControlFlowNode for FunctionExpr | test.py:1:5:1:17 | GSSA Variable obfuscated_id |
| test.py:1:5:1:17 | GSSA Variable obfuscated_id | test.py:7:5:7:17 | ControlFlowNode for obfuscated_id |
| test.py:1:19:1:19 | ControlFlowNode for x | test.py:1:19:1:19 | SSA variable x |
diff --git a/python/ql/test/experimental/dataflow/basic/localStep.ql b/python/ql/test/experimental/dataflow/basic/localStep.ql
index 4e32450f496..37b6bd1a7af 100644
--- a/python/ql/test/experimental/dataflow/basic/localStep.ql
+++ b/python/ql/test/experimental/dataflow/basic/localStep.ql
@@ -1,5 +1,8 @@
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node fromNode, DataFlow::Node toNode
-where DataFlow::localFlowStep(fromNode, toNode)
+where
+ DataFlow::localFlowStep(fromNode, toNode) and
+ exists(fromNode.getLocation().getFile().getRelativePath()) and
+ exists(toNode.getLocation().getFile().getRelativePath())
select fromNode, toNode
diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlows.expected b/python/ql/test/experimental/dataflow/basic/maximalFlows.expected
index b65b4b4d30a..b6f8a1730f1 100644
--- a/python/ql/test/experimental/dataflow/basic/maximalFlows.expected
+++ b/python/ql/test/experimental/dataflow/basic/maximalFlows.expected
@@ -1,4 +1,3 @@
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:1:19:1:19 | ControlFlowNode for x | test.py:4:10:4:10 | ControlFlowNode for z |
| test.py:1:19:1:19 | ControlFlowNode for x | test.py:7:1:7:1 | GSSA Variable b |
| test.py:1:19:1:19 | SSA variable x | test.py:4:10:4:10 | ControlFlowNode for z |
diff --git a/python/ql/test/experimental/dataflow/basic/maximalFlows.ql b/python/ql/test/experimental/dataflow/basic/maximalFlows.ql
index ddd673954b9..a314cfca612 100644
--- a/python/ql/test/experimental/dataflow/basic/maximalFlows.ql
+++ b/python/ql/test/experimental/dataflow/basic/maximalFlows.ql
@@ -3,5 +3,7 @@ import maximalFlowsConfig
from DataFlow::Node source, DataFlow::Node sink
where
source != sink and
- exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink))
+ exists(MaximalFlowsConfig cfg | cfg.hasFlow(source, sink)) and
+ exists(source.getLocation().getFile().getRelativePath()) and
+ exists(sink.getLocation().getFile().getRelativePath())
select source, sink
diff --git a/python/ql/test/experimental/dataflow/basic/sinks.expected b/python/ql/test/experimental/dataflow/basic/sinks.expected
index 18edca26f98..944f8190aa5 100644
--- a/python/ql/test/experimental/dataflow/basic/sinks.expected
+++ b/python/ql/test/experimental/dataflow/basic/sinks.expected
@@ -1,33 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
-| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 0 of builtins.dict |
-| file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
-| file://:0:0:0:0 | parameter position 0 of builtins.list |
-| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
-| file://:0:0:0:0 | parameter position 0 of builtins.set |
-| file://:0:0:0:0 | parameter position 0 of builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ |
| test.py:0:0:0:0 | GSSA Variable __package__ |
| test.py:0:0:0:0 | GSSA Variable b |
diff --git a/python/ql/test/experimental/dataflow/basic/sinks.ql b/python/ql/test/experimental/dataflow/basic/sinks.ql
index 8560bb99d3d..f17ea9b9b1b 100644
--- a/python/ql/test/experimental/dataflow/basic/sinks.ql
+++ b/python/ql/test/experimental/dataflow/basic/sinks.ql
@@ -1,5 +1,7 @@
import allFlowsConfig
from DataFlow::Node sink
-where exists(AllFlowsConfig cfg | cfg.isSink(sink))
+where
+ exists(AllFlowsConfig cfg | cfg.isSink(sink)) and
+ exists(sink.getLocation().getFile().getRelativePath())
select sink
diff --git a/python/ql/test/experimental/dataflow/basic/sources.expected b/python/ql/test/experimental/dataflow/basic/sources.expected
index 18edca26f98..944f8190aa5 100644
--- a/python/ql/test/experimental/dataflow/basic/sources.expected
+++ b/python/ql/test/experimental/dataflow/basic/sources.expected
@@ -1,33 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
-| file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
-| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 0 of builtins.dict |
-| file://:0:0:0:0 | parameter position 0 of builtins.frozenset |
-| file://:0:0:0:0 | parameter position 0 of builtins.list |
-| file://:0:0:0:0 | parameter position 0 of builtins.reversed |
-| file://:0:0:0:0 | parameter position 0 of builtins.set |
-| file://:0:0:0:0 | parameter position 0 of builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault |
| test.py:0:0:0:0 | GSSA Variable __name__ |
| test.py:0:0:0:0 | GSSA Variable __package__ |
| test.py:0:0:0:0 | GSSA Variable b |
diff --git a/python/ql/test/experimental/dataflow/basic/sources.ql b/python/ql/test/experimental/dataflow/basic/sources.ql
index d079d4db596..198882ceee6 100644
--- a/python/ql/test/experimental/dataflow/basic/sources.ql
+++ b/python/ql/test/experimental/dataflow/basic/sources.ql
@@ -1,5 +1,7 @@
import allFlowsConfig
from DataFlow::Node source
-where exists(AllFlowsConfig cfg | cfg.isSource(source))
+where
+ exists(AllFlowsConfig cfg | cfg.isSource(source)) and
+ exists(source.getLocation().getFile().getRelativePath())
select source
diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected
index 51fd643577a..3b3f18c5b9e 100644
--- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected
+++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.expected
@@ -1,20 +1,3 @@
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.reversed | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.reversed |
-| file://:0:0:0:0 | [summary] read: argument position 0.List element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Set element in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.frozenset |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.list | file://:0:0:0:0 | [summary] to write: return (return).List element in builtins.list |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.set | file://:0:0:0:0 | [summary] to write: return (return).Set element in builtins.set |
-| file://:0:0:0:0 | [summary] read: argument position 0.Tuple element at index 0 in builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return).Tuple element at index 0 in builtins.tuple |
-| file://:0:0:0:0 | parameter position 0 of builtins.dict | file://:0:0:0:0 | [summary] to write: return (return) in builtins.dict |
-| file://:0:0:0:0 | parameter position 0 of builtins.frozenset | file://:0:0:0:0 | [summary] to write: return (return) in builtins.frozenset |
-| file://:0:0:0:0 | parameter position 0 of builtins.list | file://:0:0:0:0 | [summary] to write: return (return) in builtins.list |
-| file://:0:0:0:0 | parameter position 0 of builtins.set | file://:0:0:0:0 | [summary] to write: return (return) in builtins.set |
-| file://:0:0:0:0 | parameter position 0 of builtins.tuple | file://:0:0:0:0 | [summary] to write: return (return) in builtins.tuple |
-| file://:0:0:0:0 | parameter position 1 of dict.setdefault | file://:0:0:0:0 | [summary] to write: return (return) in dict.setdefault |
| test.py:3:1:3:7 | GSSA Variable tainted | test.py:4:6:4:12 | ControlFlowNode for tainted |
| test.py:3:11:3:16 | ControlFlowNode for SOURCE | test.py:3:1:3:7 | GSSA Variable tainted |
| test.py:6:1:6:11 | ControlFlowNode for FunctionExpr | test.py:6:5:6:8 | GSSA Variable func |
diff --git a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql
index efafa7fec9f..acbb2bea137 100644
--- a/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql
+++ b/python/ql/test/experimental/dataflow/tainttracking/basic/LocalTaintStep.ql
@@ -3,5 +3,8 @@ import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.DataFlow
from DataFlow::Node nodeFrom, DataFlow::Node nodeTo
-where TaintTracking::localTaintStep(nodeFrom, nodeTo)
+where
+ TaintTracking::localTaintStep(nodeFrom, nodeTo) and
+ exists(nodeFrom.getLocation().getFile().getRelativePath()) and
+ exists(nodeTo.getLocation().getFile().getRelativePath())
select nodeFrom, nodeTo
From 8291b2229a7f87f174ff5d6954d7142888f8e58e Mon Sep 17 00:00:00 2001
From: Paolo Tranquilli
Date: Tue, 16 May 2023 15:11:48 +0200
Subject: [PATCH 47/67] Swift: turn internal error into a TSP warning
---
swift/logging/SwiftDiagnostics.cpp | 18 +++++-
swift/logging/SwiftDiagnostics.h | 57 ++++++++++++-------
.../IncompatibleOs.cpp | 7 ++-
swift/xcode-autobuilder/XcodeBuildRunner.cpp | 5 +-
swift/xcode-autobuilder/xcode-autobuilder.cpp | 12 ++--
5 files changed, 65 insertions(+), 34 deletions(-)
diff --git a/swift/logging/SwiftDiagnostics.cpp b/swift/logging/SwiftDiagnostics.cpp
index 690d03cbbaf..06c86f7f58a 100644
--- a/swift/logging/SwiftDiagnostics.cpp
+++ b/swift/logging/SwiftDiagnostics.cpp
@@ -8,6 +8,22 @@
namespace codeql {
+namespace {
+std::string_view severityToString(SwiftDiagnostic::Severity severity) {
+ using S = SwiftDiagnostic::Severity;
+ switch (severity) {
+ case S::note:
+ return "note";
+ case S::warning:
+ return "warning";
+ case S::error:
+ return "error";
+ default:
+ return "unknown";
+ }
+}
+} // namespace
+
nlohmann::json SwiftDiagnostic::json(const std::chrono::system_clock::time_point& timestamp,
std::string_view message) const {
nlohmann::json ret{
@@ -23,7 +39,7 @@ nlohmann::json SwiftDiagnostic::json(const std::chrono::system_clock::time_point
{"cliSummaryTable", has(Visibility::cliSummaryTable)},
{"telemetry", has(Visibility::telemetry)},
}},
- {"severity", "error"},
+ {"severity", severityToString(severity)},
{"helpLinks", std::vector(absl::StrSplit(helpLinks, ' '))},
{format == Format::markdown ? "markdownMessage" : "plaintextMessage",
absl::StrCat(message, ".\n\n", action)},
diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h
index ab227aae873..05dcfe1a8dc 100644
--- a/swift/logging/SwiftDiagnostics.h
+++ b/swift/logging/SwiftDiagnostics.h
@@ -46,34 +46,43 @@ struct SwiftDiagnostic {
all = 0b111,
};
+ // Notice that Tool Status Page severity is not necessarily the same as log severity, as the
+ // scope is different: TSP's scope is the whole analysis, log's scope is a single run
+ enum class Severity {
+ note,
+ warning,
+ error,
+ };
+
+ static constexpr std::string_view extractorName = "swift";
+
std::string_view id;
std::string_view name;
- static constexpr std::string_view extractorName = "swift";
- Format format;
std::string_view action;
+
+ Format format{Format::markdown};
+ Visibility visibility{Visibility::all};
+ Severity severity{Severity::error};
+
// space separated if more than 1. Not a vector to allow constexpr
// TODO(C++20) with vector going constexpr this can be turned to `std::vector`
- std::string_view helpLinks;
- // for the moment, we only output errors, so no need to store the severity
-
- Visibility visibility{Visibility::all};
+ std::string_view helpLinks{""};
std::optional location{};
// notice help links are really required only for plaintext messages, otherwise they should be
// directly embedded in the markdown message
+ // optional arguments can be any of
+ // * std::string_view for setting helpLinks
+ // * Severity, Visibility or Format to set the corresponding field
+ template
constexpr SwiftDiagnostic(std::string_view id,
std::string_view name,
- Format format,
- std::string_view action = "",
- std::string_view helpLinks = "",
- Visibility visibility = Visibility::all)
- : id{id},
- name{name},
- format{format},
- action{action},
- helpLinks{helpLinks},
- visibility{visibility} {}
+ std::string_view action,
+ OptionalArgs... optionalArgs)
+ : id{id}, name{name}, action{action} {
+ (setOptionalArg(optionalArgs), ...);
+ }
// create a JSON diagnostics for this source with the given `timestamp` and `message`
// Depending on format, either a plaintextMessage or markdownMessage is used that includes both
@@ -97,6 +106,11 @@ struct SwiftDiagnostic {
private:
bool has(Visibility v) const;
+
+ constexpr void setOptionalArg(std::string_view h) { helpLinks = h; }
+ constexpr void setOptionalArg(Format f) { format = f; }
+ constexpr void setOptionalArg(Visibility v) { visibility = v; }
+ constexpr void setOptionalArg(Severity s) { severity = s; }
};
inline constexpr SwiftDiagnostic::Visibility operator|(SwiftDiagnostic::Visibility lhs,
@@ -114,9 +128,12 @@ inline constexpr SwiftDiagnostic::Visibility operator&(SwiftDiagnostic::Visibili
constexpr SwiftDiagnostic internalError{
"internal-error",
"Internal error",
- SwiftDiagnostic::Format::plaintext,
- /* action=*/"",
- /* helpLinks=*/"",
- SwiftDiagnostic::Visibility::telemetry,
+ "Some or all of the Swift analysis may have failed.\n"
+ "\n"
+ "If the error persists, contact support, quoting the error message and describing what "
+ "happened, or [open an issue in our open source repository][1].\n"
+ "\n"
+ "[1]: https://github.com/github/codeql/issues/new?labels=bug&template=ql---general.md",
+ SwiftDiagnostic::Severity::warning,
};
} // namespace codeql
diff --git a/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp b/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp
index c949c360c26..d19479eae7d 100644
--- a/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp
+++ b/swift/tools/autobuilder-diagnostics/IncompatibleOs.cpp
@@ -9,8 +9,8 @@
const std::string_view codeql::programName = "autobuilder";
constexpr codeql::SwiftDiagnostic incompatibleOs{
- "incompatible-os", "Incompatible operating system (expected macOS)",
- codeql::SwiftDiagnostic::Format::markdown,
+ "incompatible-os",
+ "Incompatible operating system (expected macOS)",
"[Change the Actions runner][1] to run on macOS.\n"
"\n"
"You may be able to run analysis on Linux by setting up a [manual build command][2].\n"
@@ -22,7 +22,8 @@ constexpr codeql::SwiftDiagnostic incompatibleOs{
"https://docs.github.com/en/enterprise-server/code-security/code-scanning/"
"automatically-scanning-your-code-for-vulnerabilities-and-errors/"
"configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-"
- "language"};
+ "language",
+};
static codeql::Logger& logger() {
static codeql::Logger ret{"main"};
diff --git a/swift/xcode-autobuilder/XcodeBuildRunner.cpp b/swift/xcode-autobuilder/XcodeBuildRunner.cpp
index aedd1ada0b7..b209caa3df9 100644
--- a/swift/xcode-autobuilder/XcodeBuildRunner.cpp
+++ b/swift/xcode-autobuilder/XcodeBuildRunner.cpp
@@ -9,9 +9,8 @@
#include "swift/xcode-autobuilder/CustomizingBuildDiagnostics.h"
constexpr codeql::SwiftDiagnostic buildCommandFailed{
- "build-command-failed", "Detected build command failed",
- codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
- codeql::customizingBuildHelpLinks};
+ "build-command-failed", "Detected build command failed", codeql::customizingBuildAction,
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildHelpLinks};
static codeql::Logger& logger() {
static codeql::Logger ret{"build"};
diff --git a/swift/xcode-autobuilder/xcode-autobuilder.cpp b/swift/xcode-autobuilder/xcode-autobuilder.cpp
index 54973fe0114..067c4d24139 100644
--- a/swift/xcode-autobuilder/xcode-autobuilder.cpp
+++ b/swift/xcode-autobuilder/xcode-autobuilder.cpp
@@ -13,18 +13,16 @@ static const char* unitTest = "com.apple.product-type.bundle.unit-test";
const std::string_view codeql::programName = "autobuilder";
constexpr codeql::SwiftDiagnostic noProjectFound{
- "no-project-found", "No Xcode project or workspace detected",
- codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
- codeql::customizingBuildHelpLinks};
+ "no-project-found", "No Xcode project or workspace detected", codeql::customizingBuildAction,
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildHelpLinks};
constexpr codeql::SwiftDiagnostic noSwiftTarget{
- "no-swift-target", "No Swift compilation target found",
- codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
- codeql::customizingBuildHelpLinks};
+ "no-swift-target", "No Swift compilation target found", codeql::customizingBuildAction,
+ codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildHelpLinks};
constexpr codeql::SwiftDiagnostic spmNotSupported{
"spm-not-supported", "Swift Package Manager build unsupported by autobuild",
- codeql::SwiftDiagnostic::Format::plaintext, codeql::customizingBuildAction,
+ codeql::customizingBuildAction, codeql::SwiftDiagnostic::Format::plaintext,
codeql::customizingBuildHelpLinks};
static codeql::Logger& logger() {
From 9660b47879c5e59bd5c97106213825dcf0870ae2 Mon Sep 17 00:00:00 2001
From: "Michael B. Gale"
Date: Tue, 16 May 2023 14:14:18 +0100
Subject: [PATCH 48/67] Hide GHA variables in `java-version-too-old` test
---
.../java/diagnostics/java-version-too-old/test.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py
index 9def03947b3..e40201a8b68 100644
--- a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py
+++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py
@@ -8,6 +8,11 @@ if "JAVA_HOME_8_X64" in os.environ:
sep = ";" if platform.system() == "Windows" else ":"
os.environ["PATH"] = "".join([os.path.join(os.environ["JAVA_HOME"], "bin"), sep, os.environ["PATH"]])
+# Ensure the autobuilder *doesn't* see Java 11 or 17, which it could switch to in order to build the project:
+for k in ["JAVA_HOME_11_X64", "JAVA_HOME_17_X64"]:
+ if k in os.environ:
+ del os.environ[k]
+
run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None)
check_diagnostics()
From 35b35ec377f312e63c41527a1376603102c15a13 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 16 May 2023 14:24:59 +0100
Subject: [PATCH 49/67] Swift: Mirror changes made in the docs.
---
.../ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll
index 74779ea3b37..a52ddb6f8bd 100644
--- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll
+++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowPublic.qll
@@ -33,7 +33,7 @@ class Node extends TNode {
}
/**
- * Gets this node's underlying expression, if any.
+ * Gets the expression that corresponds to this node, if any.
*/
Expr asExpr() { none() }
@@ -43,7 +43,7 @@ class Node extends TNode {
Pattern asPattern() { none() }
/**
- * Gets this data flow node's corresponding control flow node.
+ * Gets the control flow node that corresponds to this data flow node.
*/
ControlFlowNode getCfgNode() { none() }
From 3027ed2ca821536feadbe3e879408079257cb74d Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 16 May 2023 16:02:29 +0200
Subject: [PATCH 50/67] C#: Include arguments to `ILogger` extension method
calls in `LogMessageSink`
---
.../flowsinks/ExternalLocationSink.qll | 9 ++++++-
.../Security Features/CWE-117/LogForging.cs | 5 ++++
.../CWE-117/LogForging.expected | 26 +++++++++++--------
3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll
index 26b75f06269..d19b0006eb7 100644
--- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll
+++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll
@@ -26,7 +26,14 @@ private class ExternalModelSink extends ExternalLocationSink {
* An argument to a call to a method on a logger class.
*/
class LogMessageSink extends ExternalLocationSink {
- LogMessageSink() { this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument() }
+ LogMessageSink() {
+ this.getExpr() = any(LoggerType i).getAMethod().getACall().getAnArgument()
+ or
+ this.getExpr() =
+ any(ExtensionMethodCall call |
+ call.getTarget().(ExtensionMethod).getExtendedType() instanceof LoggerType
+ ).getArgument(any(int i | i > 0))
+ }
}
/**
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs
index aac9ce65523..d3253f4a440 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs
@@ -3,6 +3,7 @@ using System.Diagnostics;
using System.IO;
using System.Net;
using System.Web;
+using Microsoft.Extensions.Logging;
class ILogger
{
@@ -24,6 +25,10 @@ public class LogForgingHandler : IHttpHandler
logger.Warn(WebUtility.HtmlEncode(username) + " logged in");
// BAD: Logged as-is to TraceSource
new TraceSource("Test").TraceInformation(username + " logged in");
+
+ Microsoft.Extensions.Logging.ILogger logger2 = null;
+ // BAD: Logged as-is
+ logger2.LogError(username);
}
public bool IsReusable
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected
index cfae0ac589e..5724f73d55b 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected
+++ b/csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected
@@ -1,19 +1,23 @@
edges
-| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:17:27:17:61 | access to indexer : String |
-| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... |
-| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... |
-| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:20:21:20:43 | ... + ... |
-| LogForging.cs:17:27:17:61 | access to indexer : String | LogForging.cs:26:50:26:72 | ... + ... |
+| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:18:27:18:61 | access to indexer : String |
+| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... |
+| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... |
+| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username |
+| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:21:21:21:43 | ... + ... |
+| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:27:50:27:72 | ... + ... |
+| LogForging.cs:18:27:18:61 | access to indexer : String | LogForging.cs:31:26:31:33 | access to local variable username |
| LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... |
nodes
-| LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
-| LogForging.cs:17:27:17:61 | access to indexer : String | semmle.label | access to indexer : String |
-| LogForging.cs:20:21:20:43 | ... + ... | semmle.label | ... + ... |
-| LogForging.cs:26:50:26:72 | ... + ... | semmle.label | ... + ... |
+| LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
+| LogForging.cs:18:27:18:61 | access to indexer : String | semmle.label | access to indexer : String |
+| LogForging.cs:21:21:21:43 | ... + ... | semmle.label | ... + ... |
+| LogForging.cs:27:50:27:72 | ... + ... | semmle.label | ... + ... |
+| LogForging.cs:31:26:31:33 | access to local variable username | semmle.label | access to local variable username |
| LogForgingAsp.cs:8:32:8:39 | username : String | semmle.label | username : String |
| LogForgingAsp.cs:12:21:12:43 | ... + ... | semmle.label | ... + ... |
subpaths
#select
-| LogForging.cs:20:21:20:43 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:20:21:20:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value |
-| LogForging.cs:26:50:26:72 | ... + ... | LogForging.cs:17:27:17:49 | access to property QueryString : NameValueCollection | LogForging.cs:26:50:26:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:17:27:17:49 | access to property QueryString | user-provided value |
+| LogForging.cs:21:21:21:43 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:21:21:21:43 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
+| LogForging.cs:27:50:27:72 | ... + ... | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:27:50:27:72 | ... + ... | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
+| LogForging.cs:31:26:31:33 | access to local variable username | LogForging.cs:18:27:18:49 | access to property QueryString : NameValueCollection | LogForging.cs:31:26:31:33 | access to local variable username | This log entry depends on a $@. | LogForging.cs:18:27:18:49 | access to property QueryString | user-provided value |
| LogForgingAsp.cs:12:21:12:43 | ... + ... | LogForgingAsp.cs:8:32:8:39 | username : String | LogForgingAsp.cs:12:21:12:43 | ... + ... | This log entry depends on a $@. | LogForgingAsp.cs:8:32:8:39 | username | user-provided value |
From 7e61e99e4a9dbd8261d3bd9babc104632a26f264 Mon Sep 17 00:00:00 2001
From: Paolo Tranquilli
Date: Tue, 16 May 2023 16:52:22 +0200
Subject: [PATCH 51/67] Swift: make help links optional argument more explicit
---
swift/logging/SwiftDiagnostics.h | 17 +++++++++++++----
.../CustomizingBuildDiagnostics.h | 5 +++--
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/swift/logging/SwiftDiagnostics.h b/swift/logging/SwiftDiagnostics.h
index 05dcfe1a8dc..5a0f5617076 100644
--- a/swift/logging/SwiftDiagnostics.h
+++ b/swift/logging/SwiftDiagnostics.h
@@ -54,6 +54,11 @@ struct SwiftDiagnostic {
error,
};
+ // wrapper for passing optional help links to constructor
+ struct HelpLinks {
+ std::string_view value;
+ };
+
static constexpr std::string_view extractorName = "swift";
std::string_view id;
@@ -72,9 +77,9 @@ struct SwiftDiagnostic {
// notice help links are really required only for plaintext messages, otherwise they should be
// directly embedded in the markdown message
- // optional arguments can be any of
- // * std::string_view for setting helpLinks
- // * Severity, Visibility or Format to set the corresponding field
+ // optional arguments can be any of HelpLinks, Severity, Visibility or Format to set the
+ // corresponding field
+ // TODO(C++20) this constructor won't really be necessary anymore with designated initializers
template
constexpr SwiftDiagnostic(std::string_view id,
std::string_view name,
@@ -107,10 +112,14 @@ struct SwiftDiagnostic {
private:
bool has(Visibility v) const;
- constexpr void setOptionalArg(std::string_view h) { helpLinks = h; }
+ constexpr void setOptionalArg(HelpLinks h) { helpLinks = h.value; }
constexpr void setOptionalArg(Format f) { format = f; }
constexpr void setOptionalArg(Visibility v) { visibility = v; }
constexpr void setOptionalArg(Severity s) { severity = s; }
+
+ // intentionally left undefined
+ template
+ constexpr void setOptionalArg(T);
};
inline constexpr SwiftDiagnostic::Visibility operator|(SwiftDiagnostic::Visibility lhs,
diff --git a/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h b/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h
index c1d7809054c..453fa70c13f 100644
--- a/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h
+++ b/swift/xcode-autobuilder/CustomizingBuildDiagnostics.h
@@ -1,12 +1,13 @@
#include
+#include "swift/logging/SwiftDiagnostics.h"
namespace codeql {
constexpr std::string_view customizingBuildAction = "Set up a manual build command.";
-constexpr std::string_view customizingBuildHelpLinks =
+constexpr SwiftDiagnostic::HelpLinks customizingBuildHelpLinks{
"https://docs.github.com/en/enterprise-server/code-security/code-scanning/"
"automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning "
"https://docs.github.com/en/enterprise-server/code-security/code-scanning/"
"automatically-scanning-your-code-for-vulnerabilities-and-errors/"
"configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-"
- "language";
+ "language"};
} // namespace codeql
From c412bfde684c536fee6b3a8dfcfc4d7e2292aff1 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 16 May 2023 16:54:59 +0200
Subject: [PATCH 52/67] Add change note
---
.../lib/change-notes/2023-05-16-ilogger-extension-methods.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
diff --git a/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md b/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
new file mode 100644
index 00000000000..fdbbb92de6b
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Arguments in calls to `ILogger` extension methods have been added to `LogMessageSink`, used by the queries `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information`.
From 984588745251eb8db38ae41c0a51e3363d15b066 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Tue, 16 May 2023 15:07:14 +0000
Subject: [PATCH 53/67] automodel java fix: export method name as 'name'
metadata parameter; export parameter name as 'parameterName' parameter
---
.../Telemetry/AutomodelFrameworkModeCharacteristics.qll | 7 ++++---
.../Telemetry/AutomodelFrameworkModeExtractCandidates.ql | 7 ++++---
.../AutomodelFrameworkModeExtractNegativeExamples.ql | 7 ++++---
.../AutomodelFrameworkModeExtractPositiveExamples.ql | 7 ++++---
4 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll b/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
index c2d119e8f29..2d71aeecfd6 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
@@ -27,7 +27,7 @@ abstract class MetadataExtractor extends string {
abstract predicate hasMetadata(
DataFlow::ParameterNode e, string package, string type, boolean subtypes, string name,
- string signature, int input
+ string signature, int input, string parameterName
);
}
@@ -167,14 +167,15 @@ class FrameworkModeMetadataExtractor extends MetadataExtractor {
override predicate hasMetadata(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
- int input
+ int input, string parameterName
) {
exists(Callable callable |
e.asParameter() = callable.getParameter(input) and
package = callable.getDeclaringType().getPackage().getName() and
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = this.considerSubtypes(callable) and
- name = e.toString() and
+ name = callable.getName() and
+ parameterName = e.toString() and
signature = ExternalFlow::paramsString(callable)
)
}
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql
index fb0a947379d..5e22050a06a 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql
@@ -17,7 +17,7 @@ private import AutomodelSharedUtil
from
Endpoint endpoint, string message, MetadataExtractor meta, string package, string type,
- boolean subtypes, string name, string signature, int input
+ boolean subtypes, string name, string signature, int input, string parameterName
where
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
u.appliesToEndpoint(endpoint)
@@ -28,7 +28,7 @@ where
// overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been
// modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it.
not CharacteristicsImpl::isSink(endpoint, _) and
- meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
+ meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and
// The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be
// a non-sink, and we surface only endpoints that have at least one such sink type.
message =
@@ -47,4 +47,5 @@ select endpoint,
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
- input.toString().(DollarAtString), "input" //
+ input.toString().(DollarAtString), "input", //
+ parameterName.(DollarAtString), "parameterName" //
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
index 368a373ffe8..d2e34f2c9b8 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
@@ -15,7 +15,7 @@ private import AutomodelSharedUtil
from
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
MetadataExtractor meta, string package, string type, boolean subtypes, string name,
- string signature, int input
+ string signature, int input, string parameterName
where
characteristic.appliesToEndpoint(endpoint) and
confidence >= SharedCharacteristics::highConfidence() and
@@ -23,7 +23,7 @@ where
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
not erroneousEndpoints(endpoint, _, _, _, _, false) and
- meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
+ meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and
// It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be
// treated by the actual query as a sanitizer, since the final logic is something like
// `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because
@@ -44,4 +44,5 @@ select endpoint,
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
- input.toString().(DollarAtString), "input" //
+ input.toString().(DollarAtString), "input", //
+ parameterName.(DollarAtString), "parameterName" //
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
index df4d94ce235..b1174a82919 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
@@ -14,12 +14,12 @@ private import AutomodelSharedUtil
from
Endpoint endpoint, SinkType sinkType, MetadataExtractor meta, string package, string type,
- boolean subtypes, string name, string signature, int input
+ boolean subtypes, string name, string signature, int input, string parameterName
where
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
not erroneousEndpoints(endpoint, _, _, _, _, false) and
- meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
+ meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, parameterName) and
// Extract positive examples of sinks belonging to the existing ATM query configurations.
CharacteristicsImpl::isKnownSink(endpoint, sinkType)
select endpoint,
@@ -31,4 +31,5 @@ select endpoint,
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
- input.toString().(DollarAtString), "input" //
+ input.toString().(DollarAtString), "input", //
+ parameterName.(DollarAtString), "parameterName" //
From 406acbe6a4b83e27da3d27f9a5801057a676b780 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 16 May 2023 17:13:21 +0200
Subject: [PATCH 54/67] Update
csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
Co-authored-by: Michael B. Gale
---
.../ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md b/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
index fdbbb92de6b..4d4f0767238 100644
--- a/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
+++ b/csharp/ql/lib/change-notes/2023-05-16-ilogger-extension-methods.md
@@ -1,4 +1,4 @@
---
category: minorAnalysis
---
-* Arguments in calls to `ILogger` extension methods have been added to `LogMessageSink`, used by the queries `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information`.
+* The `cs/log-forging`, `cs/cleartext-storage`, and `cs/exposure-of-sensitive-information` queries now correctly handle unsanitized arguments to `ILogger` extension methods.
From 2cd8a879a588618907e3e90d58e8867b7b13aab9 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Tue, 16 May 2023 17:28:02 +0200
Subject: [PATCH 55/67] use `asParameter().getName()` instead of `toString()`
Co-authored-by: Taus
---
java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll b/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
index 2d71aeecfd6..57bd397f7a8 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeCharacteristics.qll
@@ -175,7 +175,7 @@ class FrameworkModeMetadataExtractor extends MetadataExtractor {
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = this.considerSubtypes(callable) and
name = callable.getName() and
- parameterName = e.toString() and
+ parameterName = e.asParameter().getName() and
signature = ExternalFlow::paramsString(callable)
)
}
From c45032844e36f39181a19174288c3a4bacbc5459 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 16 May 2023 16:34:20 +0100
Subject: [PATCH 56/67] C++: Add example with conflation in dataflow.
---
.../dataflow-tests/dataflow-consistency.expected | 2 ++
.../library-tests/dataflow/dataflow-tests/test.cpp | 13 +++++++++++++
2 files changed, 15 insertions(+)
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected
index 26b2bd0351d..4922e0641fd 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected
@@ -125,6 +125,8 @@ postWithInFlow
| test.cpp:681:3:681:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:689:3:689:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
+| test.cpp:694:4:694:6 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
+| test.cpp:704:23:704:25 | buf [inner post update] | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge
uniqueParameterNodeAtPosition
uniqueParameterNodePosition
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
index 5fae604f4d9..bb7919f5a68 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
@@ -690,3 +690,16 @@ void test_static_local_9() {
s = 0;
}
+void increment_buf(int** buf) { // $ ast-def=buf ir-def=*buf ir-def=**buf
+ *buf += 10;
+ sink(buf); // $ SPURIOUS: ast,ir // should only be flow to the indirect argument, but there's also flow to the non-indirect argument
+}
+
+void call_increment_buf(int** buf) { // $ ast-def=buf
+ increment_buf(buf);
+}
+
+void test_conflation_regression(int* source) { // $ ast-def=source
+ int* buf = source;
+ call_increment_buf(&buf);
+}
\ No newline at end of file
From 2d8030210857e3742655338a171be2d5d349ab74 Mon Sep 17 00:00:00 2001
From: "Michael B. Gale"
Date: Tue, 16 May 2023 16:54:19 +0100
Subject: [PATCH 57/67] Use empty toolchains.xml for java-version-too-old
---
.../java/diagnostics/java-version-too-old/test.py | 8 +++++++-
.../java/diagnostics/java-version-too-old/toolchains.xml | 5 +++++
2 files changed, 12 insertions(+), 1 deletion(-)
create mode 100644 java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml
diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py
index e40201a8b68..1cb00f89f55 100644
--- a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py
+++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/test.py
@@ -13,6 +13,12 @@ for k in ["JAVA_HOME_11_X64", "JAVA_HOME_17_X64"]:
if k in os.environ:
del os.environ[k]
-run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None)
+# Use a custom, empty toolchains.xml file so the autobuilder doesn't see any Java versions that may be
+# in a system-level toolchains file
+toolchains_path = os.path.join(os.getcwd(), 'toolchains.xml')
+
+run_codeql_database_create([], lang="java", runFunction = runUnsuccessfully, db = None, extra_env={
+ 'LGTM_INDEX_MAVEN_TOOLCHAINS_FILE': toolchains_path
+})
check_diagnostics()
diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml
new file mode 100644
index 00000000000..51f20003fa9
--- /dev/null
+++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/toolchains.xml
@@ -0,0 +1,5 @@
+
+
+
From 9def3dd4405883d70b80e97a289747c3033286d5 Mon Sep 17 00:00:00 2001
From: Mathias Vorreiter Pedersen
Date: Tue, 16 May 2023 17:42:34 +0100
Subject: [PATCH 58/67] Update
swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
---
.../src/queries/Security/CWE-321/HardcodedEncryptionKey.swift | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
index b3f0af7395e..dcc273b7771 100644
--- a/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
+++ b/swift/ql/src/queries/Security/CWE-321/HardcodedEncryptionKey.swift
@@ -14,7 +14,7 @@ func encrypt(padding : Padding) {
// GOOD: Using randomly generated keys for encryption
var key = [Int8](repeating: 0, count: 10)
- let status = SecRandomCopyBytes(kSecRandomDefault, key.count, &key)
+ let status = SecRandomCopyBytes(kSecRandomDefault, key.count - 1, &key)
if status == errSecSuccess {
let keyString = String(cString: key)
let ivString = getRandomIV()
From f94fdc63480561de7197e4e81d3a89e7b8fa0ddf Mon Sep 17 00:00:00 2001
From: Asger F
Date: Wed, 17 May 2023 10:37:12 +0200
Subject: [PATCH 59/67] JS: Remove mention of TrackedNode in docs
---
.../codeql-library-for-javascript.rst | 35 ++++---------------
.../query17.qll | 7 ++--
.../tests.expected | 2 ++
.../tst.js | 6 +++-
4 files changed, 15 insertions(+), 35 deletions(-)
diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst
index 8c9c6d8cffa..e529d99b449 100644
--- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst
+++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst
@@ -700,28 +700,7 @@ The data flow graph-based analyses described so far are all intraprocedural: the
We distinguish here between data flow proper, and *taint tracking*: the latter not only considers value-preserving flow (such as from variable definitions to uses), but also cases where one value influences ("taints") another without determining it entirely. For example, in the assignment ``s2 = s1.substring(i)``, the value of ``s1`` influences the value of ``s2``, because ``s2`` is assigned a substring of ``s1``. In general, ``s2`` will not be assigned ``s1`` itself, so there is no data flow from ``s1`` to ``s2``, but ``s1`` still taints ``s2``.
-The simplest way of implementing an interprocedural data flow analysis is to extend either class ``DataFlow::TrackedNode`` or ``DataFlow::TrackedExpr``. The former is a subclass of ``DataFlow::Node``, the latter of ``Expr``, and extending them ensures that the newly added values are tracked interprocedurally. You can use the predicate ``flowsTo`` to find out which nodes/expressions the tracked value flows to.
-
-For example, suppose that we are developing an analysis to find hard-coded passwords. We might start by writing a simple query that looks for string constants flowing into variables named ``"password"``. To do this, we can extend ``TrackedExpr`` to track all constant strings, ``flowsTo`` to find cases where such a string flows into a (SSA) definition of a password variable:
-
-.. code-block:: ql
-
- import javascript
-
- class TrackedStringLiteral extends DataFlow::TrackedNode {
- TrackedStringLiteral() {
- this.asExpr() instanceof ConstantString
- }
- }
-
- from TrackedStringLiteral source, DataFlow::Node sink, SsaExplicitDefinition def
- where source.flowsTo(sink) and sink = DataFlow::ssaDefinitionNode(def) and
- def.getSourceVariable().getName().toLowerCase() = "password"
- select sink
-
-Note that ``TrackedNode`` and ``TrackedExpr`` do not restrict the set of "sinks" for the inter-procedural flow analysis, tracking flow into any expression that they might flow to. This can be expensive for large code bases, and is often unnecessary, since usually you are only interested in flow to a particular set of sinks. For example, the above query only looks for flow into assignments to password variables.
-
-This is a particular instance of a general pattern, whereby we want to specify a data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). The example does not include any sanitizers, but they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
+It is a common pattern that we wish to specify data flow or taint analysis in terms of its *sources* (where flow starts), *sinks* (where it should be tracked), and *barriers* or *sanitizers* (where flow is interrupted). Sanitizers they are very common in security analyses: for example, an analysis that tracks the flow of untrusted user input into, say, a SQL query has to keep track of code that validates the input, thereby making it safe to use. Such a validation step is an example of a sanitizer.
The classes ``DataFlow::Configuration`` and ``TaintTracking::Configuration`` allow specifying a data flow or taint analysis, respectively, by overriding the following predicates:
@@ -735,10 +714,12 @@ Since for technical reasons both ``Configuration`` classes are subtypes of ``str
The predicate ``Configuration.hasFlow`` performs the actual flow tracking, starting at a source and looking for flow to a sink that does not pass through a barrier node or edge.
-To continue with our above example, we can phrase it as a data flow configuration as follows:
+For example, suppose that we are developing an analysis to find hard-coded passwords. We might write a simple query that looks for string constants flowing into variables named ``"password"``.
.. code-block:: ql
+ import javascript
+
class PasswordTracker extends DataFlow::Configuration {
PasswordTracker() {
// unique identifier for this configuration
@@ -754,11 +735,8 @@ To continue with our above example, we can phrase it as a data flow configuratio
}
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
- exists (SsaExplicitDefinition def |
- nd = DataFlow::ssaDefinitionNode(def) and
- def.getSourceVariable() = v and
- v.getName().toLowerCase() = "password"
- )
+ v.getAnAssignedExpr() = nd.asExpr() and
+ v.getName().toLowerCase() = "password"
}
}
@@ -770,7 +748,6 @@ Now we can rephrase our query to use ``Configuration.hasFlow``:
where pt.hasFlow(source, sink) and pt.passwordVarAssign(v, sink)
select sink, "Password variable " + v + " is assigned a constant string."
-Note that while analyses implemented in this way are inter-procedural in that they track flow and taint across function calls and returns, flow through global variables is not tracked. Flow through object properties is only tracked in limited cases, for example through properties of object literals or CommonJS ``module`` and ``exports`` objects.
Syntax errors
~~~~~~~~~~~~~
diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll
index 0b21d872ad6..1de380f710b 100644
--- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll
+++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/query17.qll
@@ -11,11 +11,8 @@ class PasswordTracker extends DataFlow::Configuration {
override predicate isSink(DataFlow::Node nd) { this.passwordVarAssign(_, nd) }
predicate passwordVarAssign(Variable v, DataFlow::Node nd) {
- exists(SsaExplicitDefinition def |
- nd = DataFlow::ssaDefinitionNode(def) and
- def.getSourceVariable() = v and
- v.getName().toLowerCase() = "password"
- )
+ v.getAnAssignedExpr() = nd.asExpr() and
+ v.getName().toLowerCase() = "password"
}
}
diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected
index 57bfd73841f..bbec34be602 100644
--- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected
+++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tests.expected
@@ -9,6 +9,7 @@ test_query4
| tst.js:29:1:29:5 | 1 + 2 | This expression should be bracketed to clarify precedence rules. |
test_query19
test_query17
+| tst.js:38:18:38:23 | "blah" | Password variable password is assigned a constant string. |
test_query18
| m.js:1:1:3:0 | | 0 |
test_query8
@@ -18,6 +19,7 @@ test_query11
| tst.js:31:12:31:12 | x | Dead store of local variable. |
| tst.js:31:15:31:15 | y | Dead store of local variable. |
| tst.js:31:18:31:18 | x | Dead store of local variable. |
+| tst.js:38:7:38:23 | password = "blah" | Dead store of local variable. |
test_query12
test_query20
test_query3
diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js
index 804012a2673..0714ee8101a 100644
--- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js
+++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/tst.js
@@ -32,4 +32,8 @@ function l(x, y, x) {
for (i=0;i<10;++i);
}
-var j, j;
\ No newline at end of file
+var j, j;
+
+function foo() {
+ var password = "blah";
+}
From a5ef738bb007588c1557e1ed4073533cad723c46 Mon Sep 17 00:00:00 2001
From: Stephan Brandauer
Date: Wed, 17 May 2023 08:37:18 +0000
Subject: [PATCH 60/67] add extra parameters in query-messages
---
.../ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql | 2 +-
.../Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql | 2 +-
.../Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql
index 5e22050a06a..a64327422a0 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractCandidates.ql
@@ -39,7 +39,7 @@ where
sinkType, ", "
)
select endpoint,
- message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
+ message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
index d2e34f2c9b8..f1ba8ee4119 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractNegativeExamples.ql
@@ -36,7 +36,7 @@ where
) and
message = characteristic
select endpoint,
- message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
+ message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
diff --git a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
index b1174a82919..e216c292538 100644
--- a/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
+++ b/java/ql/src/Telemetry/AutomodelFrameworkModeExtractPositiveExamples.ql
@@ -23,7 +23,7 @@ where
// Extract positive examples of sinks belonging to the existing ATM query configurations.
CharacteristicsImpl::isKnownSink(endpoint, sinkType)
select endpoint,
- sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
+ sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
From f47acfb0838f5bb1941bffed98b4a1586120ee96 Mon Sep 17 00:00:00 2001
From: Asger F
Date: Wed, 17 May 2023 10:37:19 +0200
Subject: [PATCH 61/67] JS: Trim whitespace
---
.../codeql-language-guides/codeql-library-for-javascript.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst
index e529d99b449..6742dfa8e76 100644
--- a/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst
+++ b/docs/codeql/codeql-language-guides/codeql-library-for-javascript.rst
@@ -193,7 +193,7 @@ The class `ASTNode `__, the standard Node.js ``http`` and ``https`` modules, `Connect `__, `Koa `__, `Hapi `__ and `Restify `__.
From b1c1513a10337c2117761fc57117c42fe36aa241 Mon Sep 17 00:00:00 2001
From: Jeroen Ketema
Date: Wed, 17 May 2023 11:21:09 +0200
Subject: [PATCH 62/67] C++: Add forgotten test annotation in for
`cpp/invalid-pointer-deref` test
---
.../query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp
index 4536e2bd2e6..e18b630c26f 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/test.cpp
@@ -304,7 +304,7 @@ void test21() {
void** xs = new void*[n];
for (int i = 0; i < n; i += 2) {
- xs[i] = test21_get(i);
- xs[i+1] = test21_get(i+1);
+ xs[i] = test21_get(i); // GOOD
+ xs[i+1] = test21_get(i+1); // GOOD [FALSE POSITIVE]
}
}
From 883ec7a0e9a9880d3f38ea6da3899304ca7a9f20 Mon Sep 17 00:00:00 2001
From: Jeroen Ketema
Date: Wed, 17 May 2023 11:24:46 +0200
Subject: [PATCH 63/67] C++: Add forgotten `private` specifiers in product flow
---
.../experimental/semmle/code/cpp/dataflow/ProductFlow.qll | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
index c2c27158434..be7aadd76cf 100644
--- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
+++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll
@@ -290,9 +290,9 @@ module ProductFlow {
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) }
}
- module Flow1 = DataFlow::GlobalWithState;
+ private module Flow1 = DataFlow::GlobalWithState;
- module Config2 implements DataFlow::StateConfigSig {
+ private module Config2 implements DataFlow::StateConfigSig {
class FlowState = FlowState2;
predicate isSource(DataFlow::Node source, FlowState state) {
@@ -322,7 +322,7 @@ module ProductFlow {
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) }
}
- module Flow2 = DataFlow::GlobalWithState;
+ private module Flow2 = DataFlow::GlobalWithState;
pragma[nomagic]
private predicate reachableInterprocEntry(
From 31ae513f8cb1e5ea9a80c21d13bd48df5152c18f Mon Sep 17 00:00:00 2001
From: Jeroen Ketema
Date: Wed, 17 May 2023 11:27:37 +0200
Subject: [PATCH 64/67] C++: Implement the `subpaths` query predicate for
`cpp/invalid-pointer-deref`
---
.../Security/CWE/CWE-193/InvalidPointerDeref.ql | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql
index 1c81092ab3d..fc8b964596a 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql
@@ -345,6 +345,16 @@ query predicate edges(MergedPathNode node1, MergedPathNode node2) {
joinOn2(node1.asPathNode3(), node2.asSinkNode(), _)
}
+query predicate subpaths(
+ MergedPathNode arg, MergedPathNode par, MergedPathNode ret, MergedPathNode out
+) {
+ AllocToInvalidPointerFlow::PathGraph1::subpaths(arg.asPathNode1(), par.asPathNode1(),
+ ret.asPathNode1(), out.asPathNode1())
+ or
+ InvalidPointerToDerefFlow::PathGraph::subpaths(arg.asPathNode3(), par.asPathNode3(),
+ ret.asPathNode3(), out.asPathNode3())
+}
+
/**
* Holds if `p1` is a sink of `AllocToInvalidPointerConf` and `p2` is a source
* of `InvalidPointerToDerefConf`, and they are connected through `pai`.
From 7e153863766956ebfaa8d2bfc28db88461dc5ee2 Mon Sep 17 00:00:00 2001
From: Alex Denisov
Date: Wed, 17 May 2023 11:27:22 +0200
Subject: [PATCH 65/67] Swift: bump all versions to 0.1.0
---
swift/codeql-extractor.yml | 2 +-
swift/ql/lib/qlpack.yml | 2 +-
swift/ql/src/qlpack.yml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/swift/codeql-extractor.yml b/swift/codeql-extractor.yml
index 94a63897697..0439f0ea3e0 100644
--- a/swift/codeql-extractor.yml
+++ b/swift/codeql-extractor.yml
@@ -1,6 +1,6 @@
name: "swift"
display_name: "Swift"
-version: 0.0.1
+version: 0.1.0
column_kind: "utf8"
legacy_qltest_extraction: true
github_api_languages:
diff --git a/swift/ql/lib/qlpack.yml b/swift/ql/lib/qlpack.yml
index 3cb8840e0eb..f45d347bad3 100644
--- a/swift/ql/lib/qlpack.yml
+++ b/swift/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/swift-all
-version: 0.0.0
+version: 0.1.0
groups: swift
extractor: swift
dbscheme: swift.dbscheme
diff --git a/swift/ql/src/qlpack.yml b/swift/ql/src/qlpack.yml
index 7e473775c1c..2a0bee06578 100644
--- a/swift/ql/src/qlpack.yml
+++ b/swift/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/swift-queries
-version: 0.0.0
+version: 0.1.0
groups:
- swift
- queries
From 014eb255bb6a4c323ef66b619a382ad2590969c9 Mon Sep 17 00:00:00 2001
From: Jeroen Ketema
Date: Wed, 17 May 2023 12:09:22 +0200
Subject: [PATCH 66/67] C++: Update expected test results
---
.../CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected | 1 +
1 file changed, 1 insertion(+)
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected
index 011b1f8e161..59d89316088 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected
@@ -653,6 +653,7 @@ edges
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:6 | xs |
| test.cpp:308:5:308:6 | xs | test.cpp:308:5:308:11 | access to array |
| test.cpp:308:5:308:11 | access to array | test.cpp:308:5:308:29 | Store: ... = ... |
+subpaths
#select
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
From c2ec1b0a810fcc79a3524f5933e67cbede16f4f0 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 17 May 2023 13:11:32 +0200
Subject: [PATCH 67/67] C#: Add extension method testcase for Models as Data.
---
.../dataflow/external-models/ExternalFlow.cs | 21 +++++++++++++++++++
.../external-models/ExternalFlow.expected | 8 +++++++
.../external-models/ExternalFlow.ext.yml | 1 +
3 files changed, 30 insertions(+)
diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs
index 7f307e390ea..05772dfb29a 100644
--- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs
+++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs
@@ -214,4 +214,25 @@ namespace My.Qltest
static void Sink(object o) { }
}
+
+ public interface HI { }
+
+ public class HC : HI { }
+
+ public static class HE
+ {
+ public static object ExtensionMethod(this HI h) => throw null;
+ }
+
+ public class H
+ {
+ void M1()
+ {
+ var h = new HC();
+ var o = h.ExtensionMethod();
+ Sink(o);
+ }
+
+ static void Sink(object o) { }
+ }
}
\ No newline at end of file
diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected
index 25267c71e87..09ce9945cdf 100644
--- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected
+++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.expected
@@ -70,6 +70,9 @@ edges
| ExternalFlow.cs:197:42:197:43 | access to local variable o2 : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs |
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs |
+| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:232:21:232:21 | access to local variable h : HC |
+| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC |
+| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o |
nodes
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | semmle.label | call to method StepArgRes |
@@ -162,6 +165,10 @@ nodes
| ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | semmle.label | call to method MixedFlowArgs |
| ExternalFlow.cs:206:38:206:39 | access to local variable o2 : Object | semmle.label | access to local variable o2 : Object |
+| ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | semmle.label | object creation of type HC : HC |
+| ExternalFlow.cs:232:21:232:21 | access to local variable h : HC | semmle.label | access to local variable h : HC |
+| ExternalFlow.cs:232:21:232:39 | call to method ExtensionMethod : HC | semmle.label | call to method ExtensionMethod : HC |
+| ExternalFlow.cs:233:18:233:18 | access to local variable o | semmle.label | access to local variable o |
subpaths
#select
| ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:10:18:10:33 | call to method StepArgRes | $@ | ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | object creation of type Object : Object |
@@ -188,3 +195,4 @@ subpaths
| ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | ExternalFlow.cs:194:18:194:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:193:22:193:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | ExternalFlow.cs:197:18:197:44 | call to method GeneratedFlowArgs | $@ | ExternalFlow.cs:196:22:196:33 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | ExternalFlow.cs:206:18:206:40 | call to method MixedFlowArgs | $@ | ExternalFlow.cs:205:22:205:33 | object creation of type Object : Object | object creation of type Object : Object |
+| ExternalFlow.cs:233:18:233:18 | access to local variable o | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | ExternalFlow.cs:233:18:233:18 | access to local variable o | $@ | ExternalFlow.cs:231:21:231:28 | object creation of type HC : HC | object creation of type HC : HC |
diff --git a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml
index 99d387e5ebe..f626949e6f4 100644
--- a/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml
+++ b/csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.ext.yml
@@ -29,3 +29,4 @@ extensions:
- ["My.Qltest", "G", false, "GeneratedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[0]", "ReturnValue", "value", "df-generated"]
- ["My.Qltest", "G", false, "MixedFlowArgs", "(System.Object,System.Object)", "", "Argument[1]", "ReturnValue", "value", "manual"]
+ - ["My.Qltest", "HE", false, "ExtensionMethod", "(My.Qltest.HI)", "", "Argument[0]", "ReturnValue", "value", "manual"]