mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-18 20:49:28 +00:00
feat(pair-corpus-honesty): add vibe-py, vfc-js and agent-vfc slices with mechanism vocabulary
Tasks 1.1, 5.1, 5.2, 5.4 and the data half of 5.3. - mechanisms.toml: closed vocabulary v1 (20 ids) every expected row cites. - vibe-py: 35 Real-Vuln-Benchmark pairs (Apache-2.0), human provenance only because the LLM-generated repositories carry no license (escalated). - vfc-js: 17 Node fix-commit pairs harvested upstream (MIT/Apache-2.0), SecBench.js itself is not vendored (no license); sinks derived on 13/17. - agent-vfc: 29 agent-trailer fixes as catalog-candidates.toml plus REVIEW.md; the loaded catalog stays empty until a human reviews them. - datasets.toml and README document every slice and its review status. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
c3e841003c
commit
8ab4207618
@@ -0,0 +1,14 @@
|
||||
# vfc-js slice
|
||||
|
||||
Server-side JavaScript function pairs harvested from the **upstream fix commits** that
|
||||
[SecBench.js](https://github.com/cristianstaicu/SecBench.js) records in its package metadata
|
||||
(`fixCommit`, `sink`). SecBench.js itself has no license file, so none of its files are vendored;
|
||||
each excerpt carries the upstream package's license.
|
||||
|
||||
- Classes: command injection, path traversal, code injection first. Prototype pollution and ReDoS
|
||||
rows may be added with their own mechanism and `known_limit` until the engine can talk about them.
|
||||
- Mode: `hunk` (the function enclosing the first changed hunk on each side).
|
||||
- Provenance: `human`.
|
||||
|
||||
Rebuild: `python benchmarks/pairs/vfc-js/build_recipes.py --crawl /tmp/secbench.jsonl` then
|
||||
`--from /tmp/secbench.jsonl`, `harvest.py --slice vfc-js --all --fetch`, `catalog_gen.py --slice vfc-js`.
|
||||
@@ -0,0 +1,55 @@
|
||||
// Provenance: simonh1000/angular-http-server (fixed).
|
||||
// repo: simonh1000/angular-http-server
|
||||
// commit: 8bafc9577161469f5dea01e0b98ea9c525d063e9
|
||||
// parent: d171a771a92e4685b24fb77cb894a7b7b8024c5c
|
||||
// commit_url: https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: requestListener
|
||||
// relpath: angular-http-server.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 45
|
||||
|
||||
function requestListener(req, res) {
|
||||
// Add CORS header if option chosen
|
||||
if (argv.cors) {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Request-Method', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
|
||||
// When the request is for CORS OPTIONS (rather than a page) return just the headers
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Request is for a page instead
|
||||
// Only interested in the part before any query params
|
||||
var url = req.url.split('?')[0]
|
||||
// Attaches path prefix with --path option
|
||||
var possibleFilename = resolveUrl(url.slice(1)) || "dummy";
|
||||
|
||||
var safeFileName = path.normalize(possibleFilename).replace(/^(\.\.[\/\\])+/, '');
|
||||
var safeFullFilename = path.join(__dirname, safeFileName);
|
||||
|
||||
fs.stat(safeFullFilename, function(err, stats) {
|
||||
var fileBuffer;
|
||||
if (!err && stats.isFile()) {
|
||||
fileBuffer = fs.readFileSync(safeFullFilename);
|
||||
let ct = mime.lookup(safeFullFilename);
|
||||
log(`Sending ${safeFullFilename} with Content-Type ${ct}`);
|
||||
res.writeHead(200, { 'Content-Type': ct });
|
||||
|
||||
} else {
|
||||
log("Route %s, replacing with index.html", safeFullFilename);
|
||||
fileBuffer = returnDistFile();
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
}
|
||||
|
||||
res.write(fileBuffer);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Provenance: simonh1000/angular-http-server (vuln).
|
||||
// repo: simonh1000/angular-http-server
|
||||
// commit: d171a771a92e4685b24fb77cb894a7b7b8024c5c
|
||||
// parent: d171a771a92e4685b24fb77cb894a7b7b8024c5c
|
||||
// commit_url: https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9
|
||||
// cve:
|
||||
// license: Apache-2.0
|
||||
// function: requestListener
|
||||
// relpath: angular-http-server.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 45
|
||||
|
||||
function requestListener(req, res) {
|
||||
// Add CORS header if option chosen
|
||||
if (argv.cors) {
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Request-Method', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'authorization, content-type');
|
||||
// When the request is for CORS OPTIONS (rather than a page) return just the headers
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Request is for a page instead
|
||||
// Only interested in the part before any query params
|
||||
var url = req.url.split('?')[0]
|
||||
// Attaches path prefix with --path option
|
||||
var possibleFilename = resolveUrl(url.slice(1)) || "dummy";
|
||||
|
||||
fs.stat(possibleFilename, function(err, stats) {
|
||||
var fileBuffer;
|
||||
if (!err && stats.isFile()) {
|
||||
fileBuffer = fs.readFileSync(possibleFilename);
|
||||
let ct = mime.lookup(possibleFilename);
|
||||
log(`Sending ${possibleFilename} with Content-Type ${ct}`);
|
||||
res.writeHead(200, { 'Content-Type': ct });
|
||||
|
||||
} else {
|
||||
log("Route %s, replacing with index.html", possibleFilename);
|
||||
fileBuffer = returnDistFile();
|
||||
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
}
|
||||
|
||||
res.write(fileBuffer);
|
||||
res.end();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Provenance: vincentmorneau/apex-publish-static-files (fixed).
|
||||
// repo: vincentmorneau/apex-publish-static-files
|
||||
// commit: 2209af8f2b65c24aa55ab757e0e05b958c16f063
|
||||
// parent: 8d28fe8a9a49e5ff3f61e239293b5646528e2915
|
||||
// commit_url: https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063
|
||||
// cve: CVE-2018-16462
|
||||
// license: MIT
|
||||
// function: publish
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 7
|
||||
|
||||
module.exports = {
|
||||
// Validates a JSON object
|
||||
publish(opts) {
|
||||
// Set defaults
|
||||
const defaults = {
|
||||
sqlclPath: 'sql',
|
||||
destination: 'application'
|
||||
};
|
||||
opts = Object.assign(defaults, opts);
|
||||
|
||||
// Validate arguments
|
||||
if (typeof opts.connectString === 'undefined') {
|
||||
throw new TypeError('connectString is required.');
|
||||
}
|
||||
|
||||
if (typeof opts.directory === 'undefined') {
|
||||
throw new TypeError('directory is a required argument.');
|
||||
}
|
||||
|
||||
if (typeof opts.appID === 'undefined') {
|
||||
throw new TypeError('appID is a required argument.');
|
||||
}
|
||||
|
||||
if (opts.destination.toLowerCase() === 'plugin' && typeof opts.pluginName === 'undefined') {
|
||||
throw new Error('pluginName is a required argument.');
|
||||
}
|
||||
|
||||
if (!fs.existsSync(opts.directory)) {
|
||||
throw new Error(`Directory ${opts.directory} is not a valid path.`);
|
||||
}
|
||||
|
||||
const getAllFiles = dir =>
|
||||
fs.readdirSync(dir).reduce((files, file) => {
|
||||
const name = path.join(dir, file);
|
||||
const isDirectory = fs.statSync(name).isDirectory();
|
||||
return isDirectory ? [...files, ...getAllFiles(name)] : [...files, name];
|
||||
}, []);
|
||||
|
||||
if (getAllFiles(opts.directory).length === 0) {
|
||||
console.log(`Directory is empty.`);
|
||||
} else {
|
||||
// Execute the upload process
|
||||
try {
|
||||
switch (opts.destination.toLowerCase()) {
|
||||
case 'theme':
|
||||
console.log(`Uploading to ${opts.appID} - Theme Files...`);
|
||||
break;
|
||||
case 'workspace':
|
||||
console.log(`Uploading to ${opts.appID} - Workspace Files...`);
|
||||
break;
|
||||
case 'plugin':
|
||||
console.log(`Uploading to ${opts.appID} - ${opts.pluginName} - Plugin Files...`);
|
||||
break;
|
||||
default:
|
||||
console.log(`Uploading to ${opts.appID} - Application Static Files...`);
|
||||
}
|
||||
|
||||
const spawnOpts = [
|
||||
opts.connectString, // Connect string (user/pass@server:port/sid)
|
||||
'@' + path.resolve(__dirname, 'lib/script'), // Sql to execute
|
||||
path.resolve(__dirname, 'lib/distUpload.js'), // Param &1 (js to execute)
|
||||
path.resolve(opts.directory), // Param &2
|
||||
opts.appID, // Param &3
|
||||
opts.destination, // Param &4
|
||||
opts.pluginName // Param &5
|
||||
];
|
||||
|
||||
const childProcess = spawnSync(
|
||||
opts.sqlclPath, // Sqlcl path
|
||||
spawnOpts, {
|
||||
encoding: 'utf8'
|
||||
}
|
||||
);
|
||||
|
||||
console.log(childProcess.stdout);
|
||||
console.log('Files were uploaded successfully.');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
// Provenance: vincentmorneau/apex-publish-static-files (vuln).
|
||||
// repo: vincentmorneau/apex-publish-static-files
|
||||
// commit: 8d28fe8a9a49e5ff3f61e239293b5646528e2915
|
||||
// parent: 8d28fe8a9a49e5ff3f61e239293b5646528e2915
|
||||
// commit_url: https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063
|
||||
// cve: CVE-2018-16462
|
||||
// license: MIT
|
||||
// function: publish
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 7
|
||||
|
||||
module.exports = {
|
||||
// Validates a JSON object
|
||||
publish(opts) {
|
||||
// Set defaults
|
||||
const defaults = {
|
||||
sqlclPath: 'sql',
|
||||
destination: 'application'
|
||||
};
|
||||
opts = Object.assign(defaults, opts);
|
||||
|
||||
// Validate arguments
|
||||
if (typeof opts.connectString === 'undefined') {
|
||||
throw new TypeError('connectString is required.');
|
||||
}
|
||||
|
||||
if (typeof opts.directory === 'undefined') {
|
||||
throw new TypeError('directory is a required argument.');
|
||||
}
|
||||
|
||||
if (typeof opts.appID === 'undefined') {
|
||||
throw new TypeError('appID is a required argument.');
|
||||
}
|
||||
|
||||
if (opts.destination.toLowerCase() === 'plugin' && typeof opts.pluginName === 'undefined') {
|
||||
throw new Error('pluginName is a required argument.');
|
||||
}
|
||||
|
||||
if (!fs.existsSync(opts.directory)) {
|
||||
throw new Error(`Directory ${opts.directory} is not a valid path.`);
|
||||
}
|
||||
|
||||
// Execute the upload process
|
||||
try {
|
||||
switch (opts.destination.toLowerCase()) {
|
||||
case 'theme':
|
||||
console.log(`Uploading to ${opts.appID} - Theme Files...`);
|
||||
break;
|
||||
case 'workspace':
|
||||
console.log(`Uploading to ${opts.appID} - Workspace Files...`);
|
||||
break;
|
||||
case 'plugin':
|
||||
console.log(`Uploading to ${opts.appID} - ${opts.pluginName} - Plugin Files...`);
|
||||
break;
|
||||
default:
|
||||
console.log(`Uploading to ${opts.appID} - Application Static Files...`);
|
||||
}
|
||||
|
||||
const childProcess = execSync(
|
||||
'"' + opts.sqlclPath + '"' + // Sqlcl path
|
||||
' ' + opts.connectString + // Connect string (user/pass@server:port/sid)
|
||||
' @"' + path.resolve(__dirname, 'lib/script') + '"' + // Sql to execute
|
||||
' "' + path.resolve(__dirname, 'lib/distUpload.js') + '"' + // Param &1 (js to execute)
|
||||
' "' + path.resolve(opts.directory) + '"' + // Param &2
|
||||
' ' + opts.appID + // Param &3
|
||||
' "' + opts.destination + '"' + // Param &4
|
||||
' "' + opts.pluginName + '"' // Param &5
|
||||
, {
|
||||
encoding: 'utf8'
|
||||
}
|
||||
);
|
||||
|
||||
console.log(childProcess);
|
||||
|
||||
console.log('Files were uploaded successfully.');
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
// Provenance: nfriedly/node-bestzip (fixed).
|
||||
// repo: nfriedly/node-bestzip
|
||||
// commit: 45d4a901478c6a8f396c8b959dd6cf8fd3f955b6
|
||||
// parent: fcea252e52b6078eff6caf5531bd32c53fccb59f
|
||||
// commit_url: https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6
|
||||
// cve: CVE-2020-7730
|
||||
// license: MIT
|
||||
// function: nativeZip
|
||||
// relpath: lib/bestzip.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 66
|
||||
|
||||
const nativeZip = options =>
|
||||
new Promise((resolve, reject) => {
|
||||
const cwd = options.cwd || process.cwd();
|
||||
const command = "zip";
|
||||
expandSources(cwd, options.source, (err, sources) => {
|
||||
const args = ["--quiet", "--recurse-paths", options.destination].concat(
|
||||
sources
|
||||
);
|
||||
const zipProcess = cp.spawn(command, args, {
|
||||
stdio: "inherit",
|
||||
cwd
|
||||
});
|
||||
zipProcess.on("error", reject);
|
||||
zipProcess.on("close", exitCode => {
|
||||
if (exitCode === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
// exit code 12 means "nothing to do" right?
|
||||
//console.log('rejecting', zipProcess)
|
||||
reject(
|
||||
new Error(
|
||||
`Unexpected exit code from native zip: ${exitCode}\n executed command '${command} ${args.join(
|
||||
" "
|
||||
)}'\n executed in directory '${cwd}'`
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
// Provenance: nfriedly/node-bestzip (vuln).
|
||||
// repo: nfriedly/node-bestzip
|
||||
// commit: fcea252e52b6078eff6caf5531bd32c53fccb59f
|
||||
// parent: fcea252e52b6078eff6caf5531bd32c53fccb59f
|
||||
// commit_url: https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6
|
||||
// cve: CVE-2020-7730
|
||||
// license: MIT
|
||||
// function: nativeZip
|
||||
// relpath: lib/bestzip.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 66
|
||||
|
||||
const nativeZip = options =>
|
||||
new Promise((resolve, reject) => {
|
||||
const sources = Array.isArray(options.source)
|
||||
? options.source.join(" ")
|
||||
: options.source;
|
||||
const command = `zip --quiet --recurse-paths ${
|
||||
options.destination
|
||||
} ${sources}`;
|
||||
const zipProcess = cp.exec(command, {
|
||||
stdio: "inherit",
|
||||
cwd: options.cwd
|
||||
});
|
||||
zipProcess.on("error", reject);
|
||||
zipProcess.on("close", exitCode => {
|
||||
if (exitCode === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
// exit code 12 means "nothing to do" right?
|
||||
//console.log('rejecting', zipProcess)
|
||||
reject(
|
||||
new Error(
|
||||
`Unexpected exit code from native zip command: ${exitCode}\n executed command '${command}'\n executed inin directory '${options.cwd ||
|
||||
process.cwd()}'`
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,188 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build vfc-js recipes from SecBench.js fix commits (maintainer, network via gh).
|
||||
|
||||
SecBench.js has no license file, so nothing from it is vendored. Its package.json
|
||||
metadata names the upstream fix commit; the pair is harvested from that upstream
|
||||
repository (hunk mode: the function enclosing the first changed hunk) and carries
|
||||
the upstream package license. Crawl first:
|
||||
|
||||
python benchmarks/pairs/vfc-js/build_recipes.py --crawl /tmp/secbench.jsonl # lists modules with a GitHub fixCommit
|
||||
python benchmarks/pairs/vfc-js/build_recipes.py --from /tmp/secbench.jsonl # resolves parent, license, changed file
|
||||
python benchmarks/pairs/harvest.py --slice vfc-js --all --fetch
|
||||
python benchmarks/pairs/catalog_gen.py --slice vfc-js
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
CLASSES = {
|
||||
"command-injection": ("CWE-78", "command injection", "source_reaches_sink"),
|
||||
"path-traversal": ("CWE-22", "path traversal", "path_join_user_input"),
|
||||
"code-injection": ("CWE-94", "code injection", "source_reaches_sink"),
|
||||
"prototype-pollution": ("CWE-1321", "prototype pollution", "prototype_pollution"),
|
||||
"redos": ("CWE-1333", "regular expression denial of service", "redos"),
|
||||
}
|
||||
ACCEPTED_LICENSES = {"MIT", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "ISC", "MPL-2.0", "GPL-3.0", "GPL-2.0", "Unlicense", "0BSD"}
|
||||
_JS = re.compile(r"\.(js|mjs|cjs|ts)$")
|
||||
_SKIP = re.compile(r"(test|spec|\.d\.ts|dist/|build/|min\.js|package\.json|README)", re.I)
|
||||
|
||||
|
||||
def _gh(path: str) -> object:
|
||||
return json.loads(subprocess.check_output(["gh", "api", path], stderr=subprocess.DEVNULL))
|
||||
|
||||
|
||||
def crawl(out: Path, classes: tuple[str, ...]) -> int:
|
||||
count = 0
|
||||
with out.open("w") as handle:
|
||||
for cls in classes:
|
||||
dirs = _gh(f"repos/cristianstaicu/SecBench.js/contents/{cls}")
|
||||
for entry in dirs if isinstance(dirs, list) else []:
|
||||
if entry.get("type") != "dir":
|
||||
continue
|
||||
time.sleep(0.4)
|
||||
try:
|
||||
raw = subprocess.check_output(
|
||||
["gh", "api", f"repos/cristianstaicu/SecBench.js/contents/{cls}/{entry['name']}/package.json", "--jq", ".content"],
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
meta = json.loads(base64.b64decode(raw))
|
||||
except Exception: # noqa: BLE001 — skip unreadable modules
|
||||
continue
|
||||
fix = str(meta.get("fixCommit", "n/a"))
|
||||
if "github.com" in fix and "/commit/" in fix:
|
||||
handle.write(
|
||||
json.dumps(
|
||||
{"class": cls, "module": entry["name"], "cve": meta.get("id"), "fixCommit": fix, "sink": meta.get("sink")}
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
count += 1
|
||||
return count
|
||||
|
||||
|
||||
def build(crawl_path: Path, *, limit: int) -> tuple[list[dict[str, object]], dict[str, int]]:
|
||||
recipes: list[dict[str, object]] = []
|
||||
skipped = {"unlicensed": 0, "no_js_file": 0, "api": 0, "multi_file": 0}
|
||||
rows = [json.loads(line) for line in crawl_path.read_text().splitlines() if line.strip()]
|
||||
seen_shas: set[str] = set()
|
||||
seen_modules: set[str] = set()
|
||||
skipped.update({"duplicate_fix": 0, "module_repo_mismatch": 0})
|
||||
for row in rows:
|
||||
if len(recipes) >= limit:
|
||||
break
|
||||
match = re.search(r"github\.com/([^/]+/[^/]+)/commit/([0-9a-f]{7,40})", row["fixCommit"])
|
||||
if not match:
|
||||
continue
|
||||
repo, sha = match.group(1), match.group(2)
|
||||
module_base = re.sub(r"[^a-z0-9]", "", str(row["module"]).rsplit("_", 1)[0].lower())
|
||||
repo_base = re.sub(r"[^a-z0-9]", "", repo.split("/")[-1].lower())
|
||||
if sha[:10] in seen_shas or str(row["module"]) in seen_modules:
|
||||
skipped["duplicate_fix"] += 1 # SecBench.js records one upstream fix under several module names
|
||||
continue
|
||||
if module_base not in repo_base and repo_base not in module_base:
|
||||
skipped["module_repo_mismatch"] += 1 # the fix commit belongs to another package; do not attribute
|
||||
continue
|
||||
seen_shas.add(sha[:10])
|
||||
seen_modules.add(str(row["module"]))
|
||||
time.sleep(0.6)
|
||||
try:
|
||||
commit = _gh(f"repos/{repo}/commits/{sha}")
|
||||
info = _gh(f"repos/{repo}")
|
||||
except Exception: # noqa: BLE001 — upstream gone or renamed
|
||||
skipped["api"] += 1
|
||||
continue
|
||||
assert isinstance(commit, dict) and isinstance(info, dict)
|
||||
license_id = (info.get("license") or {}).get("spdx_id") or ""
|
||||
if license_id not in ACCEPTED_LICENSES:
|
||||
skipped["unlicensed"] += 1
|
||||
continue
|
||||
files = [f for f in commit.get("files", []) if _JS.search(f["filename"]) and not _SKIP.search(f["filename"]) and f.get("patch")]
|
||||
if not files:
|
||||
skipped["no_js_file"] += 1
|
||||
continue
|
||||
if len(files) > 3:
|
||||
skipped["multi_file"] += 1
|
||||
continue
|
||||
target = sorted(files, key=lambda f: -(f.get("additions", 0) + f.get("deletions", 0)))[0]
|
||||
parents = commit.get("parents") or []
|
||||
if not parents:
|
||||
skipped["api"] += 1
|
||||
continue
|
||||
cwe, cls_text, mechanism = CLASSES[row["class"]]
|
||||
module = str(row["module"])
|
||||
name = f"{re.sub(r'[^a-z0-9]+', '-', module.lower()).strip('-')}"[:60]
|
||||
recipes.append(
|
||||
{
|
||||
"name": name,
|
||||
"host": "github",
|
||||
"repo": repo,
|
||||
"parent": parents[0]["sha"],
|
||||
"commit": commit["sha"],
|
||||
"path": target["filename"],
|
||||
"mode": "hunk",
|
||||
"language": "typescript" if target["filename"].endswith(".ts") else "javascript",
|
||||
"relpath": target["filename"],
|
||||
"license": license_id,
|
||||
"cve": str(row.get("cve") or ""),
|
||||
"year": int(str(commit["commit"]["author"]["date"])[:4]),
|
||||
"cwe": cwe,
|
||||
"class": cls_text,
|
||||
"mechanism": mechanism,
|
||||
"provenance": "human",
|
||||
"origin": "secbench.js",
|
||||
"project": module.rsplit("_", 1)[0],
|
||||
"sink_location": str(row.get("sink") or ""),
|
||||
"secbench_class": row["class"],
|
||||
"evidence": f"SecBench.js {row['class']} sink {row.get('sink')} fixed upstream in {sha[:12]}",
|
||||
"commit_url": f"https://github.com/{repo}/commit/{commit['sha']}",
|
||||
}
|
||||
)
|
||||
for index, recipe in enumerate(sorted(recipes, key=lambda r: str(r["name"]))):
|
||||
recipe["split"] = "holdout" if index % 2 else "train"
|
||||
return recipes, skipped
|
||||
|
||||
|
||||
def to_toml(recipes: list[dict[str, object]]) -> str:
|
||||
lines = [
|
||||
"# vfc-js harvest recipes derived from SecBench.js fixCommit metadata by build_recipes.py.",
|
||||
"# Excerpts come from the upstream package repository (its license), never from SecBench.js.",
|
||||
"",
|
||||
]
|
||||
for recipe in sorted(recipes, key=lambda r: str(r["name"])):
|
||||
lines.append("[[recipe]]")
|
||||
for key, value in recipe.items():
|
||||
if isinstance(value, int) and not isinstance(value, bool):
|
||||
lines.append(f"{key} = {value}")
|
||||
else:
|
||||
lines.append(f'{key} = "{str(value).replace(chr(92), chr(92) * 2).replace(chr(34), chr(92) + chr(34))}"')
|
||||
lines.append("")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--crawl", type=Path, help="write the SecBench.js module list with GitHub fix commits to this jsonl")
|
||||
parser.add_argument("--classes", default="command-injection,path-traversal,code-injection")
|
||||
parser.add_argument("--from", dest="source", type=Path, help="jsonl produced by --crawl")
|
||||
parser.add_argument("--limit", type=int, default=40)
|
||||
parser.add_argument("--out", type=Path, default=ROOT / "recipes.toml")
|
||||
args = parser.parse_args(argv)
|
||||
if args.crawl:
|
||||
print(f"crawled {crawl(args.crawl, tuple(args.classes.split(',')))} modules -> {args.crawl}")
|
||||
if args.source:
|
||||
recipes, skipped = build(args.source, limit=args.limit)
|
||||
args.out.write_text(to_toml(recipes), encoding="utf-8")
|
||||
print(f"wrote {args.out} ({len(recipes)} recipes); skipped {skipped}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,493 @@
|
||||
# vfc-js pair slice. Reviewed isolated functions with provenance.
|
||||
# Honesty dashboard — not the local 100% CI gate.
|
||||
# Do not add these names to LANGUAGE_MANIFESTS.
|
||||
# Regenerated by benchmarks/pairs/catalog_gen.py from recipes.toml.
|
||||
|
||||
[[pair]]
|
||||
name = "angular-http-server-1-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "Apache-2.0"
|
||||
repo = "simonh1000/angular-http-server"
|
||||
cve = ""
|
||||
cwe = "CWE-22"
|
||||
commit = "8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
parent = "d171a771a92e4685b24fb77cb894a7b7b8024c5c"
|
||||
commit_url = "https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
vuln = "angular-http-server-1-0-0/vuln.js"
|
||||
fixed = "angular-http-server-1-0-0/fixed.js"
|
||||
relpath = "angular-http-server.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "angular-http-server.js"
|
||||
function = "requestListener"
|
||||
mechanism = "path_join_user_input"
|
||||
sink = "path"
|
||||
evidence = "SecBench.js path-traversal sink angular-http-server.js:16:29 fixed upstream in 8bafc9577161"
|
||||
|
||||
[[pair]]
|
||||
name = "apex-publish-static-files-2-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "vincentmorneau/apex-publish-static-files"
|
||||
cve = "CVE-2018-16462"
|
||||
cwe = "CWE-78"
|
||||
commit = "2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
parent = "8d28fe8a9a49e5ff3f61e239293b5646528e2915"
|
||||
commit_url = "https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
vuln = "apex-publish-static-files-2-0-0/vuln.js"
|
||||
fixed = "apex-publish-static-files-2-0-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "publish"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:54:25 fixed upstream in 2209af8f2b65"
|
||||
|
||||
[[pair]]
|
||||
name = "bestzip-2-1-6"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "nfriedly/node-bestzip"
|
||||
cve = "CVE-2020-7730"
|
||||
cwe = "CWE-78"
|
||||
commit = "45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
parent = "fcea252e52b6078eff6caf5531bd32c53fccb59f"
|
||||
commit_url = "https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
vuln = "bestzip-2-1-6/vuln.js"
|
||||
fixed = "bestzip-2-1-6/fixed.js"
|
||||
relpath = "lib/bestzip.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/bestzip.js"
|
||||
function = "nativeZip"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/bestzip.js:27:27 fixed upstream in 45d4a901478c"
|
||||
|
||||
[[pair]]
|
||||
name = "clamscan-1-2-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "kylefarris/clamscan"
|
||||
cve = "CVE-2020-7613"
|
||||
cwe = "CWE-78"
|
||||
commit = "5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
parent = "d474da7b89c0d3397cd681e79c7bcc592bff144b"
|
||||
commit_url = "https://github.com/kylefarris/clamscan/commit/5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
vuln = "clamscan-1-2-0/vuln.js"
|
||||
fixed = "clamscan-1-2-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "local_scan"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:495:36 fixed upstream in 5f557c970817"
|
||||
|
||||
[[pair]]
|
||||
name = "diskusage-ng-0-2-6"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "iximiuz/node-diskusage-ng"
|
||||
cve = "CVE-2020-7631"
|
||||
cwe = "CWE-78"
|
||||
commit = "48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
parent = "53c505506553c83861d1bd67823d6a382d3a5a43"
|
||||
commit_url = "https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
vuln = "diskusage-ng-0-2-6/vuln.js"
|
||||
fixed = "diskusage-ng-0-2-6/fixed.js"
|
||||
relpath = "lib/posix.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/posix.js"
|
||||
function = "diskusage"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/posix.js:11:5 fixed upstream in 48e7e093486b"
|
||||
|
||||
[[pair]]
|
||||
name = "dns-sync-0-1-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "skoranga/node-dns-sync"
|
||||
cve = "CVE-2014-9682"
|
||||
cwe = "CWE-78"
|
||||
commit = "d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
parent = "b748fe77a87749d95876028eda8e759109be4c73"
|
||||
commit_url = "https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
vuln = "dns-sync-0-1-0/vuln.js"
|
||||
fixed = "dns-sync-0-1-0/fixed.js"
|
||||
relpath = "lib/dns-sync.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/dns-sync.js"
|
||||
function = "resolve"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/dns-sync.js:21:26 fixed upstream in d9abaae384b1"
|
||||
|
||||
[[pair]]
|
||||
name = "glance-3-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "jarofghosts/glance"
|
||||
cve = "CVE-2018-3715"
|
||||
cwe = "CWE-22"
|
||||
commit = "8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
parent = "7e69a5539236386e747fb240ae87ea65ed64bb2c"
|
||||
commit_url = "https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
vuln = "glance-3-0-0/vuln.js"
|
||||
fixed = "glance-3-0-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "index.js"
|
||||
function = "Glance$serveRequest"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "SecBench.js path-traversal sink index.js:81:14 fixed upstream in 8cfd88e44ebd"
|
||||
|
||||
[[pair]]
|
||||
name = "hot-formula-parser-3-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "handsontable/formula-parser"
|
||||
cve = "CVE-2020-6836"
|
||||
cwe = "CWE-78"
|
||||
commit = "396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
parent = "944136096f44ff4ffd4ba0bcef30970ca4702fce"
|
||||
commit_url = "https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
vuln = "hot-formula-parser-3-0-0/vuln.js"
|
||||
fixed = "hot-formula-parser-3-0-0/fixed.js"
|
||||
relpath = "src/grammar-parser/grammar-parser.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "src/grammar-parser/grammar-parser.js"
|
||||
function = "performAction"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "SecBench.js command-injection sink lib/grammar-parser/grammar-parser.js:258:31 fixed upstream in 396b089738d4"
|
||||
|
||||
[[pair]]
|
||||
name = "libnmap-0-4-11"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "jas-/node-libnmap"
|
||||
cve = "CVE-2018-16461"
|
||||
cwe = "CWE-78"
|
||||
commit = "c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
parent = "49b72239b144ab7ffdf673b62e18bfd0760948f6"
|
||||
commit_url = "https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
vuln = "libnmap-0-4-11/vuln.js"
|
||||
fixed = "libnmap-0-4-11/fixed.js"
|
||||
relpath = "lib/classes/tools.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/classes/tools.js"
|
||||
function = "block"
|
||||
mechanism = "source_reaches_sink"
|
||||
evidence = "SecBench.js command-injection sink lib/classes/tools.js:114:25 fixed upstream in c235b24b0342"
|
||||
|
||||
[[pair]]
|
||||
name = "pdf-image-1-0-5"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "roest01/node-pdf-image"
|
||||
cve = "CVE-2018-3757"
|
||||
cwe = "CWE-78"
|
||||
commit = "54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
parent = "d8c0dcadd93985dbefe80b84060f5f572bfbb6ff"
|
||||
commit_url = "https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
vuln = "pdf-image-1-0-5/vuln.js"
|
||||
fixed = "pdf-image-1-0-5/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "getInfo"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:43:7 fixed upstream in 54679496a897"
|
||||
|
||||
[[pair]]
|
||||
name = "pidusage-1-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "soyuka/pidusage"
|
||||
cve = "CVE-2017-16034"
|
||||
cwe = "CWE-78"
|
||||
commit = "b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
parent = "e3660d8a8e5e61afad9b02af67356a1e239d6bde"
|
||||
commit_url = "https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
vuln = "pidusage-1-0-0/vuln.js"
|
||||
fixed = "pidusage-1-0-0/fixed.js"
|
||||
relpath = "lib/stats.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "lib/stats.js"
|
||||
function = "ps"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink lib/stats.js:108:5 fixed upstream in b70eca15f7ca"
|
||||
|
||||
[[pair]]
|
||||
name = "portprocesses-1-0-4"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "rrainn/PortProcesses"
|
||||
cve = "CVE-2021-23348"
|
||||
cwe = "CWE-78"
|
||||
commit = "86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
parent = "fffceb09aff7180afbd0bd172e820404b33c8299"
|
||||
commit_url = "https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
vuln = "portprocesses-1-0-4/vuln.js"
|
||||
fixed = "portprocesses-1-0-4/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "listProcessesOnPort"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink exec.js:5:3 fixed upstream in 86811216c9b9"
|
||||
|
||||
[[pair]]
|
||||
name = "serve-here-js-1-1-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "ChristoPy/serve-here.js"
|
||||
cve = "CVE-2019-5444"
|
||||
cwe = "CWE-22"
|
||||
commit = "cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
parent = "ad077637bf7a9fe0dee3262f011aed19a45ce92c"
|
||||
commit_url = "https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
vuln = "serve-here-js-1-1-0/vuln.js"
|
||||
fixed = "serve-here-js-1-1-0/fixed.js"
|
||||
relpath = "source/response.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
path = "source/response.js"
|
||||
function = "ConfigureFilePath"
|
||||
mechanism = "path_join_user_input"
|
||||
evidence = "SecBench.js path-traversal sink source/server.js:27:15 fixed upstream in cefb51d03290"
|
||||
|
||||
[[pair]]
|
||||
name = "static-eval-1-1-1"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "browserify/static-eval"
|
||||
cve = ""
|
||||
cwe = "CWE-94"
|
||||
commit = "32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
parent = "5bba7905b0e797460b8f6c2e38ff6869146faab3"
|
||||
commit_url = "https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
vuln = "static-eval-1-1-1/vuln.js"
|
||||
fixed = "static-eval-1-1-1/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
path = "index.js"
|
||||
function = "walk"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "eval"
|
||||
evidence = "SecBench.js code-injection sink index.js:118:20 fixed upstream in 32f8efd07262"
|
||||
|
||||
[[pair]]
|
||||
name = "thenify-3-3-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "thenables/thenify"
|
||||
cve = "CVE-2020-7677"
|
||||
cwe = "CWE-94"
|
||||
commit = "0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
parent = "aa21cfb64f47238c764d258d0faf7366a8487e36"
|
||||
commit_url = "https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
vuln = "thenify-3-3-0/vuln.js"
|
||||
fixed = "thenify-3-3-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
path = "index.js"
|
||||
function = "thenify"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "eval"
|
||||
evidence = "SecBench.js code-injection sink index.js:17:10 fixed upstream in 0d94a24eb933"
|
||||
|
||||
[[pair]]
|
||||
name = "underscore-1-13-0-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "jashkenas/underscore"
|
||||
cve = "CVE-2021-23358"
|
||||
cwe = "CWE-94"
|
||||
commit = "4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
parent = "ef646ccbbbd971e82719c83fc69f56a5585b3a01"
|
||||
commit_url = "https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
vuln = "underscore-1-13-0-0/vuln.js"
|
||||
fixed = "underscore-1-13-0-0/fixed.js"
|
||||
relpath = "modules/template.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "train"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
path = "modules/template.js"
|
||||
function = "template"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "eval"
|
||||
evidence = "SecBench.js code-injection sink modules/template.js:71:14 fixed upstream in 4c73526d4383"
|
||||
|
||||
[[pair]]
|
||||
name = "whereis-0-4-0"
|
||||
slice = "vfc-js"
|
||||
language = "javascript"
|
||||
origin = "secbench.js"
|
||||
license = "MIT"
|
||||
repo = "vvo/node-whereis"
|
||||
cve = "CVE-2018-3772"
|
||||
cwe = "CWE-78"
|
||||
commit = "0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
parent = "b8b642b1163baa37f15ed49b4064dcbdb6e1876c"
|
||||
commit_url = "https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
vuln = "whereis-0-4-0/vuln.js"
|
||||
fixed = "whereis-0-4-0/fixed.js"
|
||||
relpath = "index.js"
|
||||
min_recall = 1.0
|
||||
fix_policy = "silent"
|
||||
provenance = "human"
|
||||
split = "holdout"
|
||||
|
||||
[[pair.expected]]
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
path = "index.js"
|
||||
function = "whereis"
|
||||
mechanism = "source_reaches_sink"
|
||||
sink = "exec"
|
||||
evidence = "SecBench.js command-injection sink index.js:4:6 fixed upstream in 0f64e3780235"
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
// Provenance: iximiuz/node-diskusage-ng (fixed).
|
||||
// repo: iximiuz/node-diskusage-ng
|
||||
// commit: 48e7e093486b528f0c81ec699573e0e4a431b8d3
|
||||
// parent: 53c505506553c83861d1bd67823d6a382d3a5a43
|
||||
// commit_url: https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3
|
||||
// cve: CVE-2020-7631
|
||||
// license: MIT
|
||||
// function: diskusage
|
||||
// relpath: lib/posix.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 6
|
||||
|
||||
function diskusage(path, cb) {
|
||||
execFile('df', ['-k', path], function(err, stdout) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
try {
|
||||
cb(null, parse(stdout));
|
||||
} catch (e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: iximiuz/node-diskusage-ng (vuln).
|
||||
// repo: iximiuz/node-diskusage-ng
|
||||
// commit: 53c505506553c83861d1bd67823d6a382d3a5a43
|
||||
// parent: 53c505506553c83861d1bd67823d6a382d3a5a43
|
||||
// commit_url: https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3
|
||||
// cve: CVE-2020-7631
|
||||
// license: MIT
|
||||
// function: diskusage
|
||||
// relpath: lib/posix.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 6
|
||||
|
||||
function diskusage(path, cb) {
|
||||
if (path.indexOf('"') !== -1) {
|
||||
return cb(new Error('Paths with double quotes are not supported yet'));
|
||||
}
|
||||
|
||||
exec('df -k "' + path + '"', function(err, stdout) {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
try {
|
||||
cb(null, parse(stdout));
|
||||
} catch (e) {
|
||||
cb(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Provenance: skoranga/node-dns-sync (fixed).
|
||||
// repo: skoranga/node-dns-sync
|
||||
// commit: d9abaae384b198db1095735ad9c1c73d7b890a0d
|
||||
// parent: b748fe77a87749d95876028eda8e759109be4c73
|
||||
// commit_url: https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d
|
||||
// cve: CVE-2014-9682
|
||||
// license: MIT
|
||||
// function: resolve
|
||||
// relpath: lib/dns-sync.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 19
|
||||
|
||||
module.exports = {
|
||||
resolve: function resolve(hostname) {
|
||||
var output,
|
||||
nodeBinary = process.execPath;
|
||||
|
||||
if (!isValidHostName(hostname)) {
|
||||
console.error('Invalid hostname:', hostname);
|
||||
return null;
|
||||
}
|
||||
|
||||
var scriptPath = path.join(__dirname, "../scripts/dns-lookup-script"),
|
||||
response,
|
||||
cmd = util.format('"%s" "%s" %s', nodeBinary, scriptPath, hostname);
|
||||
|
||||
response = shell.exec(cmd, {silent: true});
|
||||
if (response && response.code === 0) {
|
||||
output = response.output;
|
||||
if (output && net.isIP(output)) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
debug('hostname', "fail to resolve hostname " + hostname);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Provenance: skoranga/node-dns-sync (vuln).
|
||||
// repo: skoranga/node-dns-sync
|
||||
// commit: b748fe77a87749d95876028eda8e759109be4c73
|
||||
// parent: b748fe77a87749d95876028eda8e759109be4c73
|
||||
// commit_url: https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d
|
||||
// cve: CVE-2014-9682
|
||||
// license: MIT
|
||||
// function: resolve
|
||||
// relpath: lib/dns-sync.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 13
|
||||
|
||||
module.exports = {
|
||||
resolve: function resolve(hostname) {
|
||||
var output,
|
||||
nodeBinary = process.execPath,
|
||||
scriptPath = path.join(__dirname, "../scripts/dns-lookup-script"),
|
||||
response,
|
||||
cmd = util.format('"%s" "%s" %s', nodeBinary, scriptPath, hostname);
|
||||
|
||||
response = shell.exec(cmd, {silent: true});
|
||||
if (response && response.code === 0) {
|
||||
output = response.output;
|
||||
if (output && net.isIP(output)) {
|
||||
return output;
|
||||
}
|
||||
}
|
||||
debug('hostname', "fail to resolve hostname " + hostname);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
// Provenance: jarofghosts/glance (fixed).
|
||||
// repo: jarofghosts/glance
|
||||
// commit: 8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19
|
||||
// parent: 7e69a5539236386e747fb240ae87ea65ed64bb2c
|
||||
// commit_url: https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19
|
||||
// cve: CVE-2018-3715
|
||||
// license: MIT
|
||||
// function: Glance$serveRequest
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 60
|
||||
|
||||
Glance.prototype.serveRequest = function Glance$serveRequest (req, res) {
|
||||
var request = {}
|
||||
var self = this
|
||||
|
||||
request.fullPath = path.join(
|
||||
self.dir,
|
||||
decodeURIComponent(parse(req.url).pathname)
|
||||
)
|
||||
|
||||
request.ip = req.socket.remoteAddress
|
||||
request.method = req.method.toLowerCase()
|
||||
request.response = res
|
||||
|
||||
// prevent traversing directories that are parents of the root
|
||||
if (request.fullPath.slice(0, self.dir.length) !== self.dir) {
|
||||
return self.emit('error', 403, request, res)
|
||||
}
|
||||
|
||||
if (request.method !== 'get') {
|
||||
return self.emit('error', 405, request, res)
|
||||
}
|
||||
|
||||
if (self.nodot && /^\./.test(path.basename(request.fullPath))) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
fs.stat(request.fullPath, statFile)
|
||||
|
||||
function statFile (err, stat) {
|
||||
if (err) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
self.emit('read', request)
|
||||
|
||||
return filed(request.fullPath).pipe(res)
|
||||
}
|
||||
|
||||
if (self.hideindex) {
|
||||
return self.emit('error', 403, request, res)
|
||||
}
|
||||
|
||||
if (!self.indices || !self.indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
var indices = self.indices.slice()
|
||||
|
||||
findIndex(indices.shift())
|
||||
|
||||
function findIndex (indexTest) {
|
||||
fileExists(path.join(request.fullPath, indexTest), check)
|
||||
|
||||
function check (hasIndex) {
|
||||
if (hasIndex) {
|
||||
req.url = req.url + '/' + indexTest
|
||||
|
||||
return self.serveRequest(req, res)
|
||||
}
|
||||
|
||||
if (!indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
findIndex(indices.shift())
|
||||
}
|
||||
}
|
||||
|
||||
function listFiles () {
|
||||
var listPath = request.fullPath.replace(/\/$/, '')
|
||||
|
||||
res.writeHead(200, RESPONSE_HEADERS)
|
||||
htmlls(listPath, {hideDot: self.nodot}).pipe(res)
|
||||
|
||||
return self.emit('read', request)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Provenance: jarofghosts/glance (vuln).
|
||||
// repo: jarofghosts/glance
|
||||
// commit: 7e69a5539236386e747fb240ae87ea65ed64bb2c
|
||||
// parent: 7e69a5539236386e747fb240ae87ea65ed64bb2c
|
||||
// commit_url: https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19
|
||||
// cve: CVE-2018-3715
|
||||
// license: MIT
|
||||
// function: Glance$serveRequest
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 60
|
||||
|
||||
Glance.prototype.serveRequest = function Glance$serveRequest (req, res) {
|
||||
var request = {}
|
||||
var self = this
|
||||
|
||||
request.fullPath = path.join(
|
||||
self.dir,
|
||||
decodeURIComponent(parse(req.url).pathname)
|
||||
)
|
||||
|
||||
request.ip = req.socket.remoteAddress
|
||||
request.method = req.method.toLowerCase()
|
||||
request.response = res
|
||||
|
||||
if (request.method !== 'get') {
|
||||
return self.emit('error', 405, request, res)
|
||||
}
|
||||
|
||||
if (self.nodot && /^\./.test(path.basename(request.fullPath))) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
fs.stat(request.fullPath, statFile)
|
||||
|
||||
function statFile (err, stat) {
|
||||
if (err) {
|
||||
return self.emit('error', 404, request, res)
|
||||
}
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
self.emit('read', request)
|
||||
|
||||
return filed(request.fullPath).pipe(res)
|
||||
}
|
||||
|
||||
if (self.hideindex) {
|
||||
return self.emit('error', 403, request, res)
|
||||
}
|
||||
|
||||
if (!self.indices || !self.indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
var indices = self.indices.slice()
|
||||
|
||||
findIndex(indices.shift())
|
||||
|
||||
function findIndex (indexTest) {
|
||||
fileExists(path.join(request.fullPath, indexTest), check)
|
||||
|
||||
function check (hasIndex) {
|
||||
if (hasIndex) {
|
||||
req.url = req.url + '/' + indexTest
|
||||
|
||||
return self.serveRequest(req, res)
|
||||
}
|
||||
|
||||
if (!indices.length) {
|
||||
return listFiles()
|
||||
}
|
||||
|
||||
findIndex(indices.shift())
|
||||
}
|
||||
}
|
||||
|
||||
function listFiles () {
|
||||
var listPath = request.fullPath.replace(/\/$/, '')
|
||||
|
||||
res.writeHead(200, RESPONSE_HEADERS)
|
||||
htmlls(listPath, {hideDot: self.nodot}).pipe(res)
|
||||
|
||||
return self.emit('read', request)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,867 @@
|
||||
// Provenance: handsontable/formula-parser (fixed).
|
||||
// repo: handsontable/formula-parser
|
||||
// commit: 396b089738d4bf30eb570a4fe6a188affa95cd5e
|
||||
// parent: 944136096f44ff4ffd4ba0bcef30970ca4702fce
|
||||
// commit_url: https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e
|
||||
// cve: CVE-2020-6836
|
||||
// license: MIT
|
||||
// function: performAction
|
||||
// relpath: src/grammar-parser/grammar-parser.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 74
|
||||
|
||||
var grammarParser = (function(){
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,8],$V2=[1,6],$V3=[1,7],$V4=[1,9],$V5=[1,14],$V6=[1,15],$V7=[1,16],$V8=[1,12],$V9=[1,13],$Va=[1,17],$Vb=[1,19],$Vc=[1,20],$Vd=[1,21],$Ve=[1,22],$Vf=[1,23],$Vg=[1,24],$Vh=[1,25],$Vi=[1,26],$Vj=[1,27],$Vk=[1,28],$Vl=[5,9,10,11,13,14,15,16,17,18,19,20,29,30],$Vm=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,32],$Vn=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,34],$Vo=[5,10,11,13,14,15,16,17,29,30],$Vp=[5,10,13,14,15,16,29,30],$Vq=[5,10,11,13,14,15,16,17,18,19,29,30],$Vr=[13,29,30];
|
||||
var parser = {trace: function trace () { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"expressions":3,"expression":4,"EOF":5,"variableSequence":6,"number":7,"STRING":8,"&":9,"=":10,"+":11,"(":12,")":13,"<":14,">":15,"NOT":16,"-":17,"*":18,"/":19,"^":20,"FUNCTION":21,"expseq":22,"cell":23,"ABSOLUTE_CELL":24,"RELATIVE_CELL":25,"MIXED_CELL":26,":":27,"ARRAY":28,";":29,",":30,"VARIABLE":31,"DECIMAL":32,"NUMBER":33,"%":34,"ERROR":35,"$accept":0,"$end":1},
|
||||
terminals_: {5:"EOF",8:"STRING",9:"&",10:"=",11:"+",12:"(",13:")",14:"<",15:">",16:"NOT",17:"-",18:"*",19:"/",20:"^",21:"FUNCTION",24:"ABSOLUTE_CELL",25:"RELATIVE_CELL",26:"MIXED_CELL",27:":",28:"ARRAY",29:";",30:",",31:"VARIABLE",32:"DECIMAL",33:"NUMBER",34:"%",35:"ERROR"},
|
||||
productions_: [0,[3,2],[4,1],[4,1],[4,1],[4,3],[4,3],[4,3],[4,3],[4,4],[4,4],[4,4],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,2],[4,2],[4,3],[4,4],[4,1],[4,1],[4,2],[23,1],[23,1],[23,1],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[22,1],[22,1],[22,3],[22,3],[6,1],[6,3],[7,1],[7,3],[7,2],[2,1]],
|
||||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
|
||||
return $$[$0-1];
|
||||
|
||||
break;
|
||||
case 2:
|
||||
|
||||
this.$ = yy.callVariable($$[$0][0]);
|
||||
|
||||
break;
|
||||
case 3:
|
||||
|
||||
this.$ = yy.toNumber($$[$0]);
|
||||
|
||||
break;
|
||||
case 4:
|
||||
|
||||
this.$ = yy.trimEdges($$[$0]);
|
||||
|
||||
break;
|
||||
case 5:
|
||||
|
||||
this.$ = yy.evaluateByOperator('&', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 6:
|
||||
|
||||
this.$ = yy.evaluateByOperator('=', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 7:
|
||||
|
||||
this.$ = yy.evaluateByOperator('+', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 8:
|
||||
|
||||
this.$ = $$[$0-1];
|
||||
|
||||
break;
|
||||
case 9:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 10:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 11:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<>', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 12:
|
||||
|
||||
this.$ = yy.evaluateByOperator('NOT', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 13:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 14:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 15:
|
||||
|
||||
this.$ = yy.evaluateByOperator('-', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 16:
|
||||
|
||||
this.$ = yy.evaluateByOperator('*', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 17:
|
||||
|
||||
this.$ = yy.evaluateByOperator('/', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 18:
|
||||
|
||||
this.$ = yy.evaluateByOperator('^', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 19:
|
||||
|
||||
var n1 = yy.invertNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 20:
|
||||
|
||||
var n1 = yy.toNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 21:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-2]);
|
||||
|
||||
break;
|
||||
case 22:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-3], $$[$0-1]);
|
||||
|
||||
break;
|
||||
case 26: case 27: case 28:
|
||||
|
||||
this.$ = yy.cellValue($$[$0]);
|
||||
|
||||
break;
|
||||
case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
|
||||
|
||||
this.$ = yy.rangeValue($$[$0-2], $$[$0]);
|
||||
|
||||
break;
|
||||
case 38: case 42:
|
||||
|
||||
this.$ = [$$[$0]];
|
||||
|
||||
break;
|
||||
case 39:
|
||||
|
||||
this.$ = yy.trimEdges(yytext).split(',');
|
||||
|
||||
break;
|
||||
case 40: case 41:
|
||||
|
||||
$$[$0-2].push($$[$0]);
|
||||
this.$ = $$[$0-2];
|
||||
|
||||
break;
|
||||
case 43:
|
||||
|
||||
this.$ = (Array.isArray($$[$0-2]) ? $$[$0-2] : [$$[$0-2]]);
|
||||
this.$.push($$[$0]);
|
||||
|
||||
break;
|
||||
case 44:
|
||||
|
||||
this.$ = $$[$0];
|
||||
|
||||
break;
|
||||
case 45:
|
||||
|
||||
this.$ = ($$[$0-2] + '.' + $$[$0]) * 1;
|
||||
|
||||
break;
|
||||
case 46:
|
||||
|
||||
this.$ = $$[$0-1] * 0.01;
|
||||
|
||||
break;
|
||||
case 47:
|
||||
|
||||
this.$ = yy.throwError($$[$0]);
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
table: [{2:11,3:1,4:2,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{1:[3]},{5:[1,18],9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vl,[2,2],{32:[1,29]}),o($Vl,[2,3],{34:[1,30]}),o($Vl,[2,4]),{2:11,4:31,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:32,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:33,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{12:[1,34]},o($Vl,[2,23]),o($Vl,[2,24],{2:35,35:$Va}),o($Vm,[2,42]),o($Vn,[2,44],{32:[1,36]}),o($Vl,[2,26],{27:[1,37]}),o($Vl,[2,27],{27:[1,38]}),o($Vl,[2,28],{27:[1,39]}),o([5,9,10,11,13,14,15,16,17,18,19,20,29,30,35],[2,47]),{1:[2,1]},{2:11,4:40,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:41,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:42,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:45,6:3,7:4,8:$V0,10:[1,43],11:$V1,12:$V2,15:[1,44],17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:47,6:3,7:4,8:$V0,10:[1,46],11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:48,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:49,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:50,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:51,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:52,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{31:[1,53]},o($Vn,[2,46]),{9:$Vb,10:$Vc,11:$Vd,13:[1,54],14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vo,[2,19],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,20],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:57,6:3,7:4,8:$V0,11:$V1,12:$V2,13:[1,55],17:$V3,21:$V4,22:56,23:10,24:$V5,25:$V6,26:$V7,28:[1,58],31:$V8,33:$V9,35:$Va},o($Vl,[2,25]),{33:[1,59]},{24:[1,60],25:[1,61],26:[1,62]},{24:[1,63],25:[1,64],26:[1,65]},{24:[1,66],25:[1,67],26:[1,68]},o($Vl,[2,5]),o([5,10,13,29,30],[2,6],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,7],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:69,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:70,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,14],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:71,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,13],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o([5,10,13,16,29,30],[2,12],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,15],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vq,[2,16],{9:$Vb,20:$Vk}),o($Vq,[2,17],{9:$Vb,20:$Vk}),o([5,10,11,13,14,15,16,17,18,19,20,29,30],[2,18],{9:$Vb}),o($Vm,[2,43]),o($Vl,[2,8]),o($Vl,[2,21]),{13:[1,72],29:[1,73],30:[1,74]},o($Vr,[2,38],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,39]),o($Vn,[2,45]),o($Vl,[2,29]),o($Vl,[2,30]),o($Vl,[2,31]),o($Vl,[2,32]),o($Vl,[2,33]),o($Vl,[2,34]),o($Vl,[2,35]),o($Vl,[2,36]),o($Vl,[2,37]),o($Vp,[2,9],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,11],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,10],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vl,[2,22]),{2:11,4:75,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:76,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vr,[2,40],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,41],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk})],
|
||||
defaultActions: {18:[2,1]},
|
||||
parseError: function parseError (str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
} else {
|
||||
var error = new Error(str);
|
||||
error.hash = hash;
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
parse: function parse (input) {
|
||||
var self = this,
|
||||
stack = [0],
|
||||
tstack = [], // token stack
|
||||
vstack = [null], // semantic value stack
|
||||
lstack = [], // location stack
|
||||
table = this.table,
|
||||
yytext = '',
|
||||
yylineno = 0,
|
||||
yyleng = 0,
|
||||
recovering = 0,
|
||||
TERROR = 2,
|
||||
EOF = 1;
|
||||
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
|
||||
//this.reductionCount = this.shiftCount = 0;
|
||||
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
// copy state
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
}
|
||||
}
|
||||
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
}
|
||||
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
}
|
||||
|
||||
_token_stack:
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
// if token isn't its numeric value, convert
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
while (true) {
|
||||
// retreive state number from top of stack
|
||||
state = stack[stack.length - 1];
|
||||
|
||||
// use default actions if available
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
}
|
||||
// read action for current state and first input
|
||||
action = table[state] && table[state][symbol];
|
||||
}
|
||||
|
||||
_handle_error:
|
||||
// handle parse error
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var error_rule_depth;
|
||||
var errStr = '';
|
||||
|
||||
// Return the rule stack depth where the nearest error rule can be found.
|
||||
// Return FALSE when no error recovery rule was found.
|
||||
function locateNearestErrorRecoveryRule(state) {
|
||||
var stack_probe = stack.length - 1;
|
||||
var depth = 0;
|
||||
|
||||
// try to recover from error
|
||||
for(;;) {
|
||||
// check for error recovery rule in this state
|
||||
if ((TERROR.toString()) in table[state]) {
|
||||
return depth;
|
||||
}
|
||||
if (state === 0 || stack_probe < 2) {
|
||||
return false; // No suitable error recovery rule available.
|
||||
}
|
||||
stack_probe -= 2; // popStack(1): [symbol, action]
|
||||
state = stack[stack_probe];
|
||||
++depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (!recovering) {
|
||||
// first see if there's any chance at hitting an error recovery rule:
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
|
||||
// Report error
|
||||
expected = [];
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push("'"+this.terminals_[p]+"'");
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+":\n"+lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'";
|
||||
} else {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
|
||||
(symbol == EOF ? "end of input" :
|
||||
("'"+(this.terminals_[symbol] || symbol)+"'"));
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
token: this.terminals_[symbol] || symbol,
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected,
|
||||
recoverable: (error_rule_depth !== false)
|
||||
});
|
||||
} else if (preErrorSymbol !== EOF) {
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
}
|
||||
|
||||
// just recovered from another error
|
||||
if (recovering == 3) {
|
||||
if (symbol === EOF || preErrorSymbol === EOF) {
|
||||
throw new Error(errStr || 'Parsing halted while starting to recover from another error.');
|
||||
}
|
||||
|
||||
// discard current lookahead and grab another
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
symbol = lex();
|
||||
}
|
||||
|
||||
// try to recover from error
|
||||
if (error_rule_depth === false) {
|
||||
throw new Error(errStr || 'Parsing halted. No suitable error recovery rule available.');
|
||||
}
|
||||
popStack(error_rule_depth);
|
||||
|
||||
preErrorSymbol = (symbol == TERROR ? null : symbol); // save the lookahead token
|
||||
symbol = TERROR; // insert generic error symbol as new lookahead
|
||||
state = stack[stack.length-1];
|
||||
action = table[state] && table[state][TERROR];
|
||||
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
|
||||
}
|
||||
|
||||
// this shouldn't happen, unless resolve defaults are off
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
|
||||
}
|
||||
|
||||
switch (action[0]) {
|
||||
case 1: // shift
|
||||
//this.shiftCount++;
|
||||
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]); // push state
|
||||
symbol = null;
|
||||
if (!preErrorSymbol) { // normal execution/no error
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
}
|
||||
} else {
|
||||
// error just occurred, resume old lookahead f/ before error
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// reduce
|
||||
//this.reductionCount++;
|
||||
|
||||
len = this.productions_[action[1]][1];
|
||||
|
||||
// perform semantic action
|
||||
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
|
||||
// default location, uses first token for firsts, last for lasts
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length-(len||1)].first_line,
|
||||
last_line: lstack[lstack.length-1].last_line,
|
||||
first_column: lstack[lstack.length-(len||1)].first_column,
|
||||
last_column: lstack[lstack.length-1].last_column
|
||||
};
|
||||
if (ranges) {
|
||||
yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]];
|
||||
}
|
||||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||||
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
}
|
||||
|
||||
// pop off stack
|
||||
if (len) {
|
||||
stack = stack.slice(0,-1*len*2);
|
||||
vstack = vstack.slice(0, -1*len);
|
||||
lstack = lstack.slice(0, -1*len);
|
||||
}
|
||||
|
||||
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
// goto new state = table[STATE][NONTERMINAL]
|
||||
newState = table[stack[stack.length-2]][stack[stack.length-1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// accept
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}};
|
||||
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function(){
|
||||
var lexer = ({
|
||||
|
||||
EOF:1,
|
||||
|
||||
parseError:function parseError(str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
} else {
|
||||
throw new Error(str);
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput:function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input:function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput:function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
//this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more:function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject:function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less:function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput:function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput:function () {
|
||||
var next = this.match;
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition:function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match:function(match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
backup = {
|
||||
yylineno: this.yylineno,
|
||||
yylloc: {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.last_line,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: this.yylloc.last_column
|
||||
},
|
||||
yytext: this.yytext,
|
||||
match: this.match,
|
||||
matches: this.matches,
|
||||
matched: this.matched,
|
||||
yyleng: this.yyleng,
|
||||
offset: this.offset,
|
||||
_more: this._more,
|
||||
_input: this._input,
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next:function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex:function lex () {
|
||||
var r = this.next();
|
||||
if (r) {
|
||||
return r;
|
||||
} else {
|
||||
return this.lex();
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin:function begin (condition) {
|
||||
this.conditionStack.push(condition);
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState:function popState () {
|
||||
var n = this.conditionStack.length - 1;
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules:function _currentRules () {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState:function topState (n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
} else {
|
||||
return "INITIAL";
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState:function pushState (condition) {
|
||||
this.begin(condition);
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize:function stateStackSize() {
|
||||
return this.conditionStack.length;
|
||||
},
|
||||
options: {},
|
||||
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
|
||||
var YYSTATE=YY_START;
|
||||
switch($avoiding_name_collisions) {
|
||||
case 0:/* skip whitespace */
|
||||
break;
|
||||
case 1:return 8;
|
||||
break;
|
||||
case 2:return 8;
|
||||
break;
|
||||
case 3:return 21;
|
||||
break;
|
||||
case 4:return 35;
|
||||
break;
|
||||
case 5:return 24;
|
||||
break;
|
||||
case 6:return 26;
|
||||
break;
|
||||
case 7:return 26;
|
||||
break;
|
||||
case 8:return 25;
|
||||
break;
|
||||
case 9:return 21;
|
||||
break;
|
||||
case 10:return 31;
|
||||
break;
|
||||
case 11:return 31;
|
||||
break;
|
||||
case 12:return 33;
|
||||
break;
|
||||
case 13:return 28;
|
||||
break;
|
||||
case 14:return 9;
|
||||
break;
|
||||
case 15:return ' ';
|
||||
break;
|
||||
case 16:return 32;
|
||||
break;
|
||||
case 17:return 27;
|
||||
break;
|
||||
case 18:return 29;
|
||||
break;
|
||||
case 19:return 30;
|
||||
break;
|
||||
case 20:return 18;
|
||||
break;
|
||||
case 21:return 19;
|
||||
break;
|
||||
case 22:return 17;
|
||||
break;
|
||||
case 23:return 11;
|
||||
break;
|
||||
case 24:return 20;
|
||||
break;
|
||||
case 25:return 12;
|
||||
break;
|
||||
case 26:return 13;
|
||||
break;
|
||||
case 27:return 15;
|
||||
break;
|
||||
case 28:return 14;
|
||||
break;
|
||||
case 29:return 16;
|
||||
break;
|
||||
case 30:return '"';
|
||||
break;
|
||||
case 31:return "'";
|
||||
break;
|
||||
case 32:return "!";
|
||||
break;
|
||||
case 33:return 10;
|
||||
break;
|
||||
case 34:return 34;
|
||||
break;
|
||||
case 35:return '#';
|
||||
break;
|
||||
case 36:return 5;
|
||||
break;
|
||||
}
|
||||
},
|
||||
rules: [/^(?:\s+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9\.]+(?=[(]))/,/^(?:#[A-Z0-9\/]+(!|\?)?)/,/^(?:\$[A-Za-z]+\$[0-9]+)/,/^(?:\$[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+\$[0-9]+)/,/^(?:[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z\.]+(?=[(]))/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)/,/^(?:[A-Za-z_]+)/,/^(?:[0-9]+)/,/^(?:\[(.*)?\])/,/^(?:&)/,/^(?: )/,/^(?:[.])/,/^(?::)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\/)/,/^(?:-)/,/^(?:\+)/,/^(?:\^)/,/^(?:\()/,/^(?:\))/,/^(?:>)/,/^(?:<)/,/^(?:NOT\b)/,/^(?:")/,/^(?:')/,/^(?:!)/,/^(?:=)/,/^(?:%)/,/^(?:[#])/,/^(?:$)/],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
@@ -0,0 +1,876 @@
|
||||
// Provenance: handsontable/formula-parser (vuln).
|
||||
// repo: handsontable/formula-parser
|
||||
// commit: 944136096f44ff4ffd4ba0bcef30970ca4702fce
|
||||
// parent: 944136096f44ff4ffd4ba0bcef30970ca4702fce
|
||||
// commit_url: https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e
|
||||
// cve: CVE-2020-6836
|
||||
// license: MIT
|
||||
// function: performAction
|
||||
// relpath: src/grammar-parser/grammar-parser.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 74
|
||||
|
||||
var grammarParser = (function(){
|
||||
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,5],$V1=[1,8],$V2=[1,6],$V3=[1,7],$V4=[1,9],$V5=[1,14],$V6=[1,15],$V7=[1,16],$V8=[1,12],$V9=[1,13],$Va=[1,17],$Vb=[1,19],$Vc=[1,20],$Vd=[1,21],$Ve=[1,22],$Vf=[1,23],$Vg=[1,24],$Vh=[1,25],$Vi=[1,26],$Vj=[1,27],$Vk=[1,28],$Vl=[5,9,10,11,13,14,15,16,17,18,19,20,29,30],$Vm=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,32],$Vn=[5,9,10,11,13,14,15,16,17,18,19,20,29,30,34],$Vo=[5,10,11,13,14,15,16,17,29,30],$Vp=[5,10,13,14,15,16,29,30],$Vq=[5,10,11,13,14,15,16,17,18,19,29,30],$Vr=[13,29,30];
|
||||
var parser = {trace: function trace() { },
|
||||
yy: {},
|
||||
symbols_: {"error":2,"expressions":3,"expression":4,"EOF":5,"variableSequence":6,"number":7,"STRING":8,"&":9,"=":10,"+":11,"(":12,")":13,"<":14,">":15,"NOT":16,"-":17,"*":18,"/":19,"^":20,"FUNCTION":21,"expseq":22,"cell":23,"ABSOLUTE_CELL":24,"RELATIVE_CELL":25,"MIXED_CELL":26,":":27,"ARRAY":28,";":29,",":30,"VARIABLE":31,"DECIMAL":32,"NUMBER":33,"%":34,"ERROR":35,"$accept":0,"$end":1},
|
||||
terminals_: {5:"EOF",8:"STRING",9:"&",10:"=",11:"+",12:"(",13:")",14:"<",15:">",16:"NOT",17:"-",18:"*",19:"/",20:"^",21:"FUNCTION",24:"ABSOLUTE_CELL",25:"RELATIVE_CELL",26:"MIXED_CELL",27:":",28:"ARRAY",29:";",30:",",31:"VARIABLE",32:"DECIMAL",33:"NUMBER",34:"%",35:"ERROR"},
|
||||
productions_: [0,[3,2],[4,1],[4,1],[4,1],[4,3],[4,3],[4,3],[4,3],[4,4],[4,4],[4,4],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,2],[4,2],[4,3],[4,4],[4,1],[4,1],[4,2],[23,1],[23,1],[23,1],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[23,3],[22,1],[22,1],[22,3],[22,3],[6,1],[6,3],[7,1],[7,3],[7,2],[2,1]],
|
||||
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
|
||||
/* this == yyval */
|
||||
|
||||
var $0 = $$.length - 1;
|
||||
switch (yystate) {
|
||||
case 1:
|
||||
|
||||
return $$[$0-1];
|
||||
|
||||
break;
|
||||
case 2:
|
||||
|
||||
this.$ = yy.callVariable($$[$0][0]);
|
||||
|
||||
break;
|
||||
case 3:
|
||||
|
||||
this.$ = yy.toNumber($$[$0]);
|
||||
|
||||
break;
|
||||
case 4:
|
||||
|
||||
this.$ = yy.trimEdges($$[$0]);
|
||||
|
||||
break;
|
||||
case 5:
|
||||
|
||||
this.$ = yy.evaluateByOperator('&', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 6:
|
||||
|
||||
this.$ = yy.evaluateByOperator('=', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 7:
|
||||
|
||||
this.$ = yy.evaluateByOperator('+', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 8:
|
||||
|
||||
this.$ = $$[$0-1];
|
||||
|
||||
break;
|
||||
case 9:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 10:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>=', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 11:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<>', [$$[$0-3], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 12:
|
||||
|
||||
this.$ = yy.evaluateByOperator('NOT', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 13:
|
||||
|
||||
this.$ = yy.evaluateByOperator('>', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 14:
|
||||
|
||||
this.$ = yy.evaluateByOperator('<', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 15:
|
||||
|
||||
this.$ = yy.evaluateByOperator('-', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 16:
|
||||
|
||||
this.$ = yy.evaluateByOperator('*', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 17:
|
||||
|
||||
this.$ = yy.evaluateByOperator('/', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 18:
|
||||
|
||||
this.$ = yy.evaluateByOperator('^', [$$[$0-2], $$[$0]]);
|
||||
|
||||
break;
|
||||
case 19:
|
||||
|
||||
var n1 = yy.invertNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 20:
|
||||
|
||||
var n1 = yy.toNumber($$[$0]);
|
||||
|
||||
this.$ = n1;
|
||||
|
||||
if (isNaN(this.$)) {
|
||||
this.$ = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 21:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-2]);
|
||||
|
||||
break;
|
||||
case 22:
|
||||
|
||||
this.$ = yy.callFunction($$[$0-3], $$[$0-1]);
|
||||
|
||||
break;
|
||||
case 26: case 27: case 28:
|
||||
|
||||
this.$ = yy.cellValue($$[$0]);
|
||||
|
||||
break;
|
||||
case 29: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
|
||||
|
||||
this.$ = yy.rangeValue($$[$0-2], $$[$0]);
|
||||
|
||||
break;
|
||||
case 38: case 42:
|
||||
|
||||
this.$ = [$$[$0]];
|
||||
|
||||
break;
|
||||
case 39:
|
||||
|
||||
var result = [];
|
||||
var arr = eval("[" + yytext + "]");
|
||||
|
||||
arr.forEach(function(item) {
|
||||
result.push(item);
|
||||
});
|
||||
|
||||
this.$ = result;
|
||||
|
||||
break;
|
||||
case 40: case 41:
|
||||
|
||||
$$[$0-2].push($$[$0]);
|
||||
this.$ = $$[$0-2];
|
||||
|
||||
break;
|
||||
case 43:
|
||||
|
||||
this.$ = (Array.isArray($$[$0-2]) ? $$[$0-2] : [$$[$0-2]]);
|
||||
this.$.push($$[$0]);
|
||||
|
||||
break;
|
||||
case 44:
|
||||
|
||||
this.$ = $$[$0];
|
||||
|
||||
break;
|
||||
case 45:
|
||||
|
||||
this.$ = ($$[$0-2] + '.' + $$[$0]) * 1;
|
||||
|
||||
break;
|
||||
case 46:
|
||||
|
||||
this.$ = $$[$0-1] * 0.01;
|
||||
|
||||
break;
|
||||
case 47:
|
||||
|
||||
this.$ = yy.throwError($$[$0]);
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
table: [{2:11,3:1,4:2,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{1:[3]},{5:[1,18],9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vl,[2,2],{32:[1,29]}),o($Vl,[2,3],{34:[1,30]}),o($Vl,[2,4]),{2:11,4:31,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:32,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:33,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{12:[1,34]},o($Vl,[2,23]),o($Vl,[2,24],{2:35,35:$Va}),o($Vm,[2,42]),o($Vn,[2,44],{32:[1,36]}),o($Vl,[2,26],{27:[1,37]}),o($Vl,[2,27],{27:[1,38]}),o($Vl,[2,28],{27:[1,39]}),o([5,9,10,11,13,14,15,16,17,18,19,20,29,30,35],[2,47]),{1:[2,1]},{2:11,4:40,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:41,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:42,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:45,6:3,7:4,8:$V0,10:[1,43],11:$V1,12:$V2,15:[1,44],17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:47,6:3,7:4,8:$V0,10:[1,46],11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:48,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:49,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:50,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:51,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:52,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{31:[1,53]},o($Vn,[2,46]),{9:$Vb,10:$Vc,11:$Vd,13:[1,54],14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk},o($Vo,[2,19],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,20],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:57,6:3,7:4,8:$V0,11:$V1,12:$V2,13:[1,55],17:$V3,21:$V4,22:56,23:10,24:$V5,25:$V6,26:$V7,28:[1,58],31:$V8,33:$V9,35:$Va},o($Vl,[2,25]),{33:[1,59]},{24:[1,60],25:[1,61],26:[1,62]},{24:[1,63],25:[1,64],26:[1,65]},{24:[1,66],25:[1,67],26:[1,68]},o($Vl,[2,5]),o([5,10,13,29,30],[2,6],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,7],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:69,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:70,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,14],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),{2:11,4:71,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vp,[2,13],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o([5,10,13,16,29,30],[2,12],{9:$Vb,11:$Vd,14:$Ve,15:$Vf,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vo,[2,15],{9:$Vb,18:$Vi,19:$Vj,20:$Vk}),o($Vq,[2,16],{9:$Vb,20:$Vk}),o($Vq,[2,17],{9:$Vb,20:$Vk}),o([5,10,11,13,14,15,16,17,18,19,20,29,30],[2,18],{9:$Vb}),o($Vm,[2,43]),o($Vl,[2,8]),o($Vl,[2,21]),{13:[1,72],29:[1,73],30:[1,74]},o($Vr,[2,38],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,39]),o($Vn,[2,45]),o($Vl,[2,29]),o($Vl,[2,30]),o($Vl,[2,31]),o($Vl,[2,32]),o($Vl,[2,33]),o($Vl,[2,34]),o($Vl,[2,35]),o($Vl,[2,36]),o($Vl,[2,37]),o($Vp,[2,9],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,11],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vp,[2,10],{9:$Vb,11:$Vd,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vl,[2,22]),{2:11,4:75,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},{2:11,4:76,6:3,7:4,8:$V0,11:$V1,12:$V2,17:$V3,21:$V4,23:10,24:$V5,25:$V6,26:$V7,31:$V8,33:$V9,35:$Va},o($Vr,[2,40],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk}),o($Vr,[2,41],{9:$Vb,10:$Vc,11:$Vd,14:$Ve,15:$Vf,16:$Vg,17:$Vh,18:$Vi,19:$Vj,20:$Vk})],
|
||||
defaultActions: {18:[2,1]},
|
||||
parseError: function parseError(str, hash) {
|
||||
if (hash.recoverable) {
|
||||
this.trace(str);
|
||||
} else {
|
||||
function _parseError (msg, hash) {
|
||||
this.message = msg;
|
||||
this.hash = hash;
|
||||
}
|
||||
_parseError.prototype = Error;
|
||||
|
||||
throw new _parseError(str, hash);
|
||||
}
|
||||
},
|
||||
parse: function parse(input) {
|
||||
var self = this,
|
||||
stack = [0],
|
||||
tstack = [], // token stack
|
||||
vstack = [null], // semantic value stack
|
||||
lstack = [], // location stack
|
||||
table = this.table,
|
||||
yytext = '',
|
||||
yylineno = 0,
|
||||
yyleng = 0,
|
||||
recovering = 0,
|
||||
TERROR = 2,
|
||||
EOF = 1;
|
||||
|
||||
var args = lstack.slice.call(arguments, 1);
|
||||
|
||||
//this.reductionCount = this.shiftCount = 0;
|
||||
|
||||
var lexer = Object.create(this.lexer);
|
||||
var sharedState = { yy: {} };
|
||||
// copy state
|
||||
for (var k in this.yy) {
|
||||
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
|
||||
sharedState.yy[k] = this.yy[k];
|
||||
}
|
||||
}
|
||||
|
||||
lexer.setInput(input, sharedState.yy);
|
||||
sharedState.yy.lexer = lexer;
|
||||
sharedState.yy.parser = this;
|
||||
if (typeof lexer.yylloc == 'undefined') {
|
||||
lexer.yylloc = {};
|
||||
}
|
||||
var yyloc = lexer.yylloc;
|
||||
lstack.push(yyloc);
|
||||
|
||||
var ranges = lexer.options && lexer.options.ranges;
|
||||
|
||||
if (typeof sharedState.yy.parseError === 'function') {
|
||||
this.parseError = sharedState.yy.parseError;
|
||||
} else {
|
||||
this.parseError = Object.getPrototypeOf(this).parseError;
|
||||
}
|
||||
|
||||
function popStack (n) {
|
||||
stack.length = stack.length - 2 * n;
|
||||
vstack.length = vstack.length - n;
|
||||
lstack.length = lstack.length - n;
|
||||
}
|
||||
|
||||
var lex = function () {
|
||||
var token;
|
||||
token = lexer.lex() || EOF;
|
||||
// if token isn't its numeric value, convert
|
||||
if (typeof token !== 'number') {
|
||||
token = self.symbols_[token] || token;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
|
||||
while (true) {
|
||||
// retreive state number from top of stack
|
||||
state = stack[stack.length - 1];
|
||||
|
||||
// use default actions if available
|
||||
if (this.defaultActions[state]) {
|
||||
action = this.defaultActions[state];
|
||||
} else {
|
||||
if (symbol === null || typeof symbol == 'undefined') {
|
||||
symbol = lex();
|
||||
}
|
||||
// read action for current state and first input
|
||||
action = table[state] && table[state][symbol];
|
||||
}
|
||||
|
||||
// handle parse error
|
||||
if (typeof action === 'undefined' || !action.length || !action[0]) {
|
||||
var error_rule_depth;
|
||||
var errStr = '';
|
||||
|
||||
// Return the rule stack depth where the nearest error rule can be found.
|
||||
// Return FALSE when no error recovery rule was found.
|
||||
function locateNearestErrorRecoveryRule(state) {
|
||||
var stack_probe = stack.length - 1;
|
||||
var depth = 0;
|
||||
|
||||
// try to recover from error
|
||||
for(;;) {
|
||||
// check for error recovery rule in this state
|
||||
if ((TERROR.toString()) in table[state]) {
|
||||
return depth;
|
||||
}
|
||||
if (state === 0 || stack_probe < 2) {
|
||||
return false; // No suitable error recovery rule available.
|
||||
}
|
||||
stack_probe -= 2; // popStack(1): [symbol, action]
|
||||
state = stack[stack_probe];
|
||||
++depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (!recovering) {
|
||||
// first see if there's any chance at hitting an error recovery rule:
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
|
||||
// Report error
|
||||
expected = [];
|
||||
for (p in table[state]) {
|
||||
if (this.terminals_[p] && p > TERROR) {
|
||||
expected.push("'"+this.terminals_[p]+"'");
|
||||
}
|
||||
}
|
||||
if (lexer.showPosition) {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+":\n"+lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'";
|
||||
} else {
|
||||
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
|
||||
(symbol == EOF ? "end of input" :
|
||||
("'"+(this.terminals_[symbol] || symbol)+"'"));
|
||||
}
|
||||
this.parseError(errStr, {
|
||||
text: lexer.match,
|
||||
token: this.terminals_[symbol] || symbol,
|
||||
line: lexer.yylineno,
|
||||
loc: yyloc,
|
||||
expected: expected,
|
||||
recoverable: (error_rule_depth !== false)
|
||||
});
|
||||
} else if (preErrorSymbol !== EOF) {
|
||||
error_rule_depth = locateNearestErrorRecoveryRule(state);
|
||||
}
|
||||
|
||||
// just recovered from another error
|
||||
if (recovering == 3) {
|
||||
if (symbol === EOF || preErrorSymbol === EOF) {
|
||||
throw new Error(errStr || 'Parsing halted while starting to recover from another error.');
|
||||
}
|
||||
|
||||
// discard current lookahead and grab another
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
symbol = lex();
|
||||
}
|
||||
|
||||
// try to recover from error
|
||||
if (error_rule_depth === false) {
|
||||
throw new Error(errStr || 'Parsing halted. No suitable error recovery rule available.');
|
||||
}
|
||||
popStack(error_rule_depth);
|
||||
|
||||
preErrorSymbol = (symbol == TERROR ? null : symbol); // save the lookahead token
|
||||
symbol = TERROR; // insert generic error symbol as new lookahead
|
||||
state = stack[stack.length-1];
|
||||
action = table[state] && table[state][TERROR];
|
||||
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
|
||||
}
|
||||
|
||||
// this shouldn't happen, unless resolve defaults are off
|
||||
if (action[0] instanceof Array && action.length > 1) {
|
||||
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
|
||||
}
|
||||
|
||||
switch (action[0]) {
|
||||
case 1: // shift
|
||||
//this.shiftCount++;
|
||||
|
||||
stack.push(symbol);
|
||||
vstack.push(lexer.yytext);
|
||||
lstack.push(lexer.yylloc);
|
||||
stack.push(action[1]); // push state
|
||||
symbol = null;
|
||||
if (!preErrorSymbol) { // normal execution/no error
|
||||
yyleng = lexer.yyleng;
|
||||
yytext = lexer.yytext;
|
||||
yylineno = lexer.yylineno;
|
||||
yyloc = lexer.yylloc;
|
||||
if (recovering > 0) {
|
||||
recovering--;
|
||||
}
|
||||
} else {
|
||||
// error just occurred, resume old lookahead f/ before error
|
||||
symbol = preErrorSymbol;
|
||||
preErrorSymbol = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// reduce
|
||||
//this.reductionCount++;
|
||||
|
||||
len = this.productions_[action[1]][1];
|
||||
|
||||
// perform semantic action
|
||||
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
|
||||
// default location, uses first token for firsts, last for lasts
|
||||
yyval._$ = {
|
||||
first_line: lstack[lstack.length-(len||1)].first_line,
|
||||
last_line: lstack[lstack.length-1].last_line,
|
||||
first_column: lstack[lstack.length-(len||1)].first_column,
|
||||
last_column: lstack[lstack.length-1].last_column
|
||||
};
|
||||
if (ranges) {
|
||||
yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]];
|
||||
}
|
||||
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
|
||||
|
||||
if (typeof r !== 'undefined') {
|
||||
return r;
|
||||
}
|
||||
|
||||
// pop off stack
|
||||
if (len) {
|
||||
stack = stack.slice(0,-1*len*2);
|
||||
vstack = vstack.slice(0, -1*len);
|
||||
lstack = lstack.slice(0, -1*len);
|
||||
}
|
||||
|
||||
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
|
||||
vstack.push(yyval.$);
|
||||
lstack.push(yyval._$);
|
||||
// goto new state = table[STATE][NONTERMINAL]
|
||||
newState = table[stack[stack.length-2]][stack[stack.length-1]];
|
||||
stack.push(newState);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// accept
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}};
|
||||
|
||||
/* generated by jison-lex 0.3.4 */
|
||||
var lexer = (function(){
|
||||
var lexer = ({
|
||||
|
||||
EOF:1,
|
||||
|
||||
parseError:function parseError(str, hash) {
|
||||
if (this.yy.parser) {
|
||||
this.yy.parser.parseError(str, hash);
|
||||
} else {
|
||||
throw new Error(str);
|
||||
}
|
||||
},
|
||||
|
||||
// resets the lexer, sets new input
|
||||
setInput:function (input, yy) {
|
||||
this.yy = yy || this.yy || {};
|
||||
this._input = input;
|
||||
this._more = this._backtrack = this.done = false;
|
||||
this.yylineno = this.yyleng = 0;
|
||||
this.yytext = this.matched = this.match = '';
|
||||
this.conditionStack = ['INITIAL'];
|
||||
this.yylloc = {
|
||||
first_line: 1,
|
||||
first_column: 0,
|
||||
last_line: 1,
|
||||
last_column: 0
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [0,0];
|
||||
}
|
||||
this.offset = 0;
|
||||
return this;
|
||||
},
|
||||
|
||||
// consumes and returns one char from the input
|
||||
input:function () {
|
||||
var ch = this._input[0];
|
||||
this.yytext += ch;
|
||||
this.yyleng++;
|
||||
this.offset++;
|
||||
this.match += ch;
|
||||
this.matched += ch;
|
||||
var lines = ch.match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno++;
|
||||
this.yylloc.last_line++;
|
||||
} else {
|
||||
this.yylloc.last_column++;
|
||||
}
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range[1]++;
|
||||
}
|
||||
|
||||
this._input = this._input.slice(1);
|
||||
return ch;
|
||||
},
|
||||
|
||||
// unshifts one char (or a string) into the input
|
||||
unput:function (ch) {
|
||||
var len = ch.length;
|
||||
var lines = ch.split(/(?:\r\n?|\n)/g);
|
||||
|
||||
this._input = ch + this._input;
|
||||
this.yytext = this.yytext.substr(0, this.yytext.length - len);
|
||||
//this.yyleng -= len;
|
||||
this.offset -= len;
|
||||
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
|
||||
this.match = this.match.substr(0, this.match.length - 1);
|
||||
this.matched = this.matched.substr(0, this.matched.length - 1);
|
||||
|
||||
if (lines.length - 1) {
|
||||
this.yylineno -= lines.length - 1;
|
||||
}
|
||||
var r = this.yylloc.range;
|
||||
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: lines ?
|
||||
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
|
||||
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
|
||||
this.yylloc.first_column - len
|
||||
};
|
||||
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
|
||||
}
|
||||
this.yyleng = this.yytext.length;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, caches matched text and appends it on next action
|
||||
more:function () {
|
||||
this._more = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
|
||||
reject:function () {
|
||||
if (this.options.backtrack_lexer) {
|
||||
this._backtrack = true;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// retain first n characters of the match
|
||||
less:function (n) {
|
||||
this.unput(this.match.slice(n));
|
||||
},
|
||||
|
||||
// displays already matched input, i.e. for error messages
|
||||
pastInput:function () {
|
||||
var past = this.matched.substr(0, this.matched.length - this.match.length);
|
||||
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays upcoming input, i.e. for error messages
|
||||
upcomingInput:function () {
|
||||
var next = this.match;
|
||||
if (next.length < 20) {
|
||||
next += this._input.substr(0, 20-next.length);
|
||||
}
|
||||
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
|
||||
},
|
||||
|
||||
// displays the character position where the lexing error occurred, i.e. for error messages
|
||||
showPosition:function () {
|
||||
var pre = this.pastInput();
|
||||
var c = new Array(pre.length + 1).join("-");
|
||||
return pre + this.upcomingInput() + "\n" + c + "^";
|
||||
},
|
||||
|
||||
// test the lexed token: return FALSE when not a match, otherwise return token
|
||||
test_match:function (match, indexed_rule) {
|
||||
var token,
|
||||
lines,
|
||||
backup;
|
||||
|
||||
if (this.options.backtrack_lexer) {
|
||||
// save context
|
||||
backup = {
|
||||
yylineno: this.yylineno,
|
||||
yylloc: {
|
||||
first_line: this.yylloc.first_line,
|
||||
last_line: this.last_line,
|
||||
first_column: this.yylloc.first_column,
|
||||
last_column: this.yylloc.last_column
|
||||
},
|
||||
yytext: this.yytext,
|
||||
match: this.match,
|
||||
matches: this.matches,
|
||||
matched: this.matched,
|
||||
yyleng: this.yyleng,
|
||||
offset: this.offset,
|
||||
_more: this._more,
|
||||
_input: this._input,
|
||||
yy: this.yy,
|
||||
conditionStack: this.conditionStack.slice(0),
|
||||
done: this.done
|
||||
};
|
||||
if (this.options.ranges) {
|
||||
backup.yylloc.range = this.yylloc.range.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
lines = match[0].match(/(?:\r\n?|\n).*/g);
|
||||
if (lines) {
|
||||
this.yylineno += lines.length;
|
||||
}
|
||||
this.yylloc = {
|
||||
first_line: this.yylloc.last_line,
|
||||
last_line: this.yylineno + 1,
|
||||
first_column: this.yylloc.last_column,
|
||||
last_column: lines ?
|
||||
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
|
||||
this.yylloc.last_column + match[0].length
|
||||
};
|
||||
this.yytext += match[0];
|
||||
this.match += match[0];
|
||||
this.matches = match;
|
||||
this.yyleng = this.yytext.length;
|
||||
if (this.options.ranges) {
|
||||
this.yylloc.range = [this.offset, this.offset += this.yyleng];
|
||||
}
|
||||
this._more = false;
|
||||
this._backtrack = false;
|
||||
this._input = this._input.slice(match[0].length);
|
||||
this.matched += match[0];
|
||||
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
|
||||
if (this.done && this._input) {
|
||||
this.done = false;
|
||||
}
|
||||
if (token) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
// recover context
|
||||
for (var k in backup) {
|
||||
this[k] = backup[k];
|
||||
}
|
||||
return false; // rule action called reject() implying the next rule should be tested instead.
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// return next match in input
|
||||
next:function () {
|
||||
if (this.done) {
|
||||
return this.EOF;
|
||||
}
|
||||
if (!this._input) {
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
var token,
|
||||
match,
|
||||
tempMatch,
|
||||
index;
|
||||
if (!this._more) {
|
||||
this.yytext = '';
|
||||
this.match = '';
|
||||
}
|
||||
var rules = this._currentRules();
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
tempMatch = this._input.match(this.rules[rules[i]]);
|
||||
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
|
||||
match = tempMatch;
|
||||
index = i;
|
||||
if (this.options.backtrack_lexer) {
|
||||
token = this.test_match(tempMatch, rules[i]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
} else if (this._backtrack) {
|
||||
match = false;
|
||||
continue; // rule action called reject() implying a rule MISmatch.
|
||||
} else {
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
} else if (!this.options.flex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
token = this.test_match(match, rules[index]);
|
||||
if (token !== false) {
|
||||
return token;
|
||||
}
|
||||
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
|
||||
return false;
|
||||
}
|
||||
if (this._input === "") {
|
||||
return this.EOF;
|
||||
} else {
|
||||
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
|
||||
text: "",
|
||||
token: null,
|
||||
line: this.yylineno
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// return next match that has a token
|
||||
lex:function lex() {
|
||||
var r = this.next();
|
||||
if (r) {
|
||||
return r;
|
||||
} else {
|
||||
return this.lex();
|
||||
}
|
||||
},
|
||||
|
||||
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
|
||||
begin:function begin(condition) {
|
||||
this.conditionStack.push(condition);
|
||||
},
|
||||
|
||||
// pop the previously active lexer condition state off the condition stack
|
||||
popState:function popState() {
|
||||
var n = this.conditionStack.length - 1;
|
||||
if (n > 0) {
|
||||
return this.conditionStack.pop();
|
||||
} else {
|
||||
return this.conditionStack[0];
|
||||
}
|
||||
},
|
||||
|
||||
// produce the lexer rule set which is active for the currently active lexer condition state
|
||||
_currentRules:function _currentRules() {
|
||||
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
|
||||
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
|
||||
} else {
|
||||
return this.conditions["INITIAL"].rules;
|
||||
}
|
||||
},
|
||||
|
||||
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
|
||||
topState:function topState(n) {
|
||||
n = this.conditionStack.length - 1 - Math.abs(n || 0);
|
||||
if (n >= 0) {
|
||||
return this.conditionStack[n];
|
||||
} else {
|
||||
return "INITIAL";
|
||||
}
|
||||
},
|
||||
|
||||
// alias for begin(condition)
|
||||
pushState:function pushState(condition) {
|
||||
this.begin(condition);
|
||||
},
|
||||
|
||||
// return the number of states currently on the stack
|
||||
stateStackSize:function stateStackSize() {
|
||||
return this.conditionStack.length;
|
||||
},
|
||||
options: {},
|
||||
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
|
||||
var YYSTATE=YY_START;
|
||||
switch($avoiding_name_collisions) {
|
||||
case 0:/* skip whitespace */
|
||||
break;
|
||||
case 1:return 8;
|
||||
break;
|
||||
case 2:return 8;
|
||||
break;
|
||||
case 3:return 21;
|
||||
break;
|
||||
case 4:return 35;
|
||||
break;
|
||||
case 5:return 24;
|
||||
break;
|
||||
case 6:return 26;
|
||||
break;
|
||||
case 7:return 26;
|
||||
break;
|
||||
case 8:return 25;
|
||||
break;
|
||||
case 9:return 21;
|
||||
break;
|
||||
case 10:return 31;
|
||||
break;
|
||||
case 11:return 31;
|
||||
break;
|
||||
case 12:return 33;
|
||||
break;
|
||||
case 13:return 28;
|
||||
break;
|
||||
case 14:return 9;
|
||||
break;
|
||||
case 15:return ' ';
|
||||
break;
|
||||
case 16:return 32;
|
||||
break;
|
||||
case 17:return 27;
|
||||
break;
|
||||
case 18:return 29;
|
||||
break;
|
||||
case 19:return 30;
|
||||
break;
|
||||
case 20:return 18;
|
||||
break;
|
||||
case 21:return 19;
|
||||
break;
|
||||
case 22:return 17;
|
||||
break;
|
||||
case 23:return 11;
|
||||
break;
|
||||
case 24:return 20;
|
||||
break;
|
||||
case 25:return 12;
|
||||
break;
|
||||
case 26:return 13;
|
||||
break;
|
||||
case 27:return 15;
|
||||
break;
|
||||
case 28:return 14;
|
||||
break;
|
||||
case 29:return 16;
|
||||
break;
|
||||
case 30:return '"';
|
||||
break;
|
||||
case 31:return "'";
|
||||
break;
|
||||
case 32:return "!";
|
||||
break;
|
||||
case 33:return 10;
|
||||
break;
|
||||
case 34:return 34;
|
||||
break;
|
||||
case 35:return '#';
|
||||
break;
|
||||
case 36:return 5;
|
||||
break;
|
||||
}
|
||||
},
|
||||
rules: [/^(?:\s+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9\.]+(?=[(]))/,/^(?:#[A-Z0-9\/]+(!|\?)?)/,/^(?:\$[A-Za-z]+\$[0-9]+)/,/^(?:\$[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+\$[0-9]+)/,/^(?:[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z\.]+(?=[(]))/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)/,/^(?:[A-Za-z_]+)/,/^(?:[0-9]+)/,/^(?:\[(.*)?\])/,/^(?:&)/,/^(?: )/,/^(?:[.])/,/^(?::)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\/)/,/^(?:-)/,/^(?:\+)/,/^(?:\^)/,/^(?:\()/,/^(?:\))/,/^(?:>)/,/^(?:<)/,/^(?:NOT\b)/,/^(?:")/,/^(?:')/,/^(?:!)/,/^(?:=)/,/^(?:%)/,/^(?:[#])/,/^(?:$)/],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
})();
|
||||
parser.lexer = lexer;
|
||||
function Parser () {
|
||||
this.yy = {};
|
||||
}
|
||||
Parser.prototype = parser;parser.Parser = Parser;
|
||||
return new Parser;
|
||||
})();
|
||||
@@ -0,0 +1,234 @@
|
||||
// Provenance: jas-/node-libnmap (fixed).
|
||||
// repo: jas-/node-libnmap
|
||||
// commit: c235b24b0342e12a5dbf502f89daabe95883b6c8
|
||||
// parent: 49b72239b144ab7ffdf673b62e18bfd0760948f6
|
||||
// commit_url: https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8
|
||||
// cve: CVE-2018-16461
|
||||
// license: MIT
|
||||
// function: block
|
||||
// relpath: lib/classes/tools.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 20
|
||||
|
||||
class tools extends emitter {
|
||||
|
||||
/**
|
||||
* @function merge
|
||||
* Perform preliminary option/default object merge
|
||||
*
|
||||
* @param {Object} defaults Application defaults
|
||||
* @param {Object} obj User supplied object
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
merge(defaults, obj) {
|
||||
return merge(defaults, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function chunk
|
||||
* Defines new property for array's
|
||||
*
|
||||
* @param {Array} obj Supplied array
|
||||
* @param {Integer} offset Supplied offset
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
chunk(obj, offset) {
|
||||
let idx = 0;
|
||||
const alength = obj.length;
|
||||
const tarray = [];
|
||||
|
||||
for (idx = 0; idx < alength; idx += offset) {
|
||||
tarray.push(obj.slice(idx, idx + offset).join(' '));
|
||||
}
|
||||
|
||||
return tarray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function flatten
|
||||
* Flattens nested arrays into one flat array
|
||||
*
|
||||
* @param {Array} arr Array combinator
|
||||
* @param {Array} obj User supplied array
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
flatten(arr, obj) {
|
||||
let value;
|
||||
const result = [];
|
||||
|
||||
for (let i = 0, length = arr.length; i < length; i++) {
|
||||
|
||||
value = arr[i];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return this.flatten(value, obj);
|
||||
}
|
||||
else {
|
||||
result.push(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function funcs
|
||||
* Create functions for use as callbacks
|
||||
*
|
||||
* @param {Obect} opts Application defaults
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
funcs(opts) {
|
||||
const scope = this;
|
||||
const funcs = {};
|
||||
let cmd = false;
|
||||
const errors = [];
|
||||
const reports = [];
|
||||
|
||||
if (opts.range.length <= 0)
|
||||
return "Range of hosts could not be created";
|
||||
|
||||
Object.keys(opts.range).forEach(function blocks(block) {
|
||||
|
||||
// Acquire an array of ranges
|
||||
const range = opts.range[block];
|
||||
|
||||
// Create a new function for each range block
|
||||
funcs[range] = function block(callback) {
|
||||
const report = [];
|
||||
|
||||
|
||||
// Capture the flags, & ranges as a command string
|
||||
cmd = scope.command(opts, range);
|
||||
|
||||
// Split up cmd for .spawn()
|
||||
const obj = cmd.split(" ");
|
||||
cmd = obj[0];
|
||||
const args = obj.slice(1);
|
||||
|
||||
if (opts.verbose)
|
||||
console.log(`Running: ${cmd}`);
|
||||
|
||||
// Push it on to the heap
|
||||
const execute = proc(cmd, args);
|
||||
|
||||
// Discard stderr for now, maybe log?
|
||||
execute.stderr.on('data', (chunk) => {
|
||||
/* Silently discard stderr messages to not interupt scans */
|
||||
});
|
||||
|
||||
// Push to array of reports
|
||||
execute.stdout.on('data', (chunk) => {
|
||||
report.push(chunk);
|
||||
});
|
||||
|
||||
// Push report array to reporting function on stream end
|
||||
execute.stdout.on('end', () => {
|
||||
if (report.length > 0)
|
||||
return reporting.reports(opts, report, callback);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function command
|
||||
* Generate nmap command string
|
||||
*
|
||||
* @param {Object} opts - User supplied options
|
||||
* @param {String} block - Network block
|
||||
*
|
||||
* @returns {String} NMAP scan string
|
||||
*/
|
||||
command(opts, block) {
|
||||
const flags = opts.flags.join(' ');
|
||||
const proto = (opts.udp) ? ' -sU' : ' ';
|
||||
const to = `--host-timeout=${opts.timeout}s `;
|
||||
const ipv6 = (validation.test(validation.patterns.IPv6, block)) ?
|
||||
' -6 ' : ' ';
|
||||
|
||||
return (opts.ports) ?
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}-p${opts.ports} ${block}` :
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}${block}`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function worker
|
||||
* Executes object of functions
|
||||
*
|
||||
* @param {Object} obj User supplied object
|
||||
* @param {Function} fn Return function
|
||||
*/
|
||||
worker(obj, fn) {
|
||||
async.parallelLimit(obj.funcs, obj.threshold, fn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function init
|
||||
* @scope private
|
||||
* Merges supplied options & builds functions
|
||||
*
|
||||
* @param {Object} defaults libnmap default options
|
||||
* @param {Object} opts User supplied configuration object
|
||||
* @param {Function} cb Callback
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
init(defaults, opts, cb) {
|
||||
let funcs = [];
|
||||
const ranges = [];
|
||||
const called = caller.get()[1].getFunctionName();
|
||||
|
||||
/* Override 'defaults.flags' array with 'opts.flags' (prevents merge) */
|
||||
if (/array/.test(typeof opts.flags))
|
||||
defaults.flags = opts.flags;
|
||||
|
||||
opts = this.merge(defaults, opts);
|
||||
|
||||
/* Ensure we can always parse the report */
|
||||
if (opts.flags.indexOf('-oX -') === -1)
|
||||
opts.flags.push('-oX -');
|
||||
|
||||
/* If we are in a discover mode get adapters for associated network(s) */
|
||||
if (/nmap.discover/.test(called)) {
|
||||
|
||||
/* Bail early if we cannot determine any ranges */
|
||||
if (!(opts.range = network.adapters(opts)))
|
||||
return cb(validation.messages.version);
|
||||
|
||||
/* Set scan options as static values for 'discover' mode */
|
||||
opts.ports = '';
|
||||
opts.flags = [
|
||||
'-n',
|
||||
'-oX -',
|
||||
'-sn',
|
||||
'-PR'
|
||||
];
|
||||
}
|
||||
|
||||
validation.init(opts, (err, result) => {
|
||||
if (err)
|
||||
return cb(err);
|
||||
|
||||
opts.range = network.calculate(opts);
|
||||
funcs = this.funcs(opts);
|
||||
|
||||
return cb(null, {
|
||||
opts,
|
||||
funcs
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
// Provenance: jas-/node-libnmap (vuln).
|
||||
// repo: jas-/node-libnmap
|
||||
// commit: 49b72239b144ab7ffdf673b62e18bfd0760948f6
|
||||
// parent: 49b72239b144ab7ffdf673b62e18bfd0760948f6
|
||||
// commit_url: https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8
|
||||
// cve: CVE-2018-16461
|
||||
// license: MIT
|
||||
// function: block
|
||||
// relpath: lib/classes/tools.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 20
|
||||
|
||||
class tools extends emitter {
|
||||
|
||||
/**
|
||||
* @function merge
|
||||
* Perform preliminary option/default object merge
|
||||
*
|
||||
* @param {Object} defaults Application defaults
|
||||
* @param {Object} obj User supplied object
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
merge(defaults, obj) {
|
||||
return merge(defaults, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function chunk
|
||||
* Defines new property for array's
|
||||
*
|
||||
* @param {Array} obj Supplied array
|
||||
* @param {Integer} offset Supplied offset
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
chunk(obj, offset) {
|
||||
let idx = 0;
|
||||
const alength = obj.length;
|
||||
const tarray = [];
|
||||
|
||||
for (idx = 0; idx < alength; idx += offset) {
|
||||
tarray.push(obj.slice(idx, idx + offset).join(' '));
|
||||
}
|
||||
|
||||
return tarray;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function flatten
|
||||
* Flattens nested arrays into one flat array
|
||||
*
|
||||
* @param {Array} arr Array combinator
|
||||
* @param {Array} obj User supplied array
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
flatten(arr, obj) {
|
||||
let value;
|
||||
const result = [];
|
||||
|
||||
for (let i = 0, length = arr.length; i < length; i++) {
|
||||
|
||||
value = arr[i];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return this.flatten(value, obj);
|
||||
} else {
|
||||
result.push(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function funcs
|
||||
* Create functions for use as callbacks
|
||||
*
|
||||
* @param {Obect} opts Application defaults
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
funcs(opts) {
|
||||
const scope = this;
|
||||
const funcs = {};
|
||||
let cmd = false;
|
||||
const errors = [];
|
||||
const reports = [];
|
||||
|
||||
if (opts.range.length <= 0)
|
||||
return "Range of hosts could not be created";
|
||||
|
||||
Object.keys(opts.range).forEach(function blocks(block) {
|
||||
|
||||
const range = opts.range[block];
|
||||
funcs[range] = function block(callback) {
|
||||
cmd = scope.command(opts, range);
|
||||
|
||||
if (opts.verbose)
|
||||
console.log(`Running: ${cmd}`);
|
||||
|
||||
const report = [];
|
||||
|
||||
const execute = proc(cmd, (err, stdout, stderr) => {
|
||||
if (err)
|
||||
return reporting.reports(opts, err, callback);
|
||||
});
|
||||
|
||||
execute.stderr.on('data', (chunk) => {
|
||||
/* Silently discard stderr messages to not interupt scans */
|
||||
});
|
||||
|
||||
execute.stdout.on('data', (chunk) => {
|
||||
report.push(chunk);
|
||||
});
|
||||
|
||||
execute.stdout.on('end', () => {
|
||||
if (report.length > 0)
|
||||
return reporting.reports(opts, report, callback);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
return funcs;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function command
|
||||
* Generate nmap command string
|
||||
*
|
||||
* @param {Object} opts - User supplied options
|
||||
* @param {String} block - Network block
|
||||
*
|
||||
* @returns {String} NMAP scan string
|
||||
*/
|
||||
command(opts, block) {
|
||||
const flags = opts.flags.join(' ');
|
||||
const proto = (opts.udp) ? ' -sU' : ' ';
|
||||
const to = `--host-timeout=${opts.timeout}s `;
|
||||
const ipv6 = (validation.test(validation.patterns.IPv6, block)) ?
|
||||
' -6 ' : ' ';
|
||||
|
||||
return (opts.ports) ?
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}-p${opts.ports} ${block}` :
|
||||
`${opts.nmap+proto} ${to}${flags}${ipv6}${block}`;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function worker
|
||||
* Executes object of functions
|
||||
*
|
||||
* @param {Object} obj User supplied object
|
||||
* @param {Function} fn Return function
|
||||
*/
|
||||
worker(obj, fn) {
|
||||
async.parallelLimit(obj.funcs, obj.threshold, fn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @function init
|
||||
* @scope private
|
||||
* Merges supplied options & builds functions
|
||||
*
|
||||
* @param {Object} defaults libnmap default options
|
||||
* @param {Object} opts User supplied configuration object
|
||||
* @param {Function} cb Callback
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
init(defaults, opts, cb) {
|
||||
let funcs = [];
|
||||
const ranges = [];
|
||||
const called = caller.get()[1].getFunctionName();
|
||||
|
||||
/* Override 'defaults.flags' array with 'opts.flags' (prevents merge) */
|
||||
if (/array/.test(typeof opts.flags))
|
||||
defaults.flags = opts.flags;
|
||||
|
||||
opts = this.merge(defaults, opts);
|
||||
|
||||
/* Ensure we can always parse the report */
|
||||
if (opts.flags.indexOf('-oX -') === -1)
|
||||
opts.flags.push('-oX -');
|
||||
|
||||
/* If we are in a discover mode get adapters for associated network(s) */
|
||||
if (/nmap.discover/.test(called)) {
|
||||
|
||||
/* Bail early if we cannot determine any ranges */
|
||||
if (!(opts.range = network.adapters(opts)))
|
||||
return cb(validation.messages.version);
|
||||
|
||||
/* Set scan options as static values for 'discover' mode */
|
||||
opts.ports = '';
|
||||
opts.flags = [
|
||||
'-n',
|
||||
'-oX -',
|
||||
'-sn',
|
||||
'-PR'
|
||||
];
|
||||
}
|
||||
|
||||
validation.init(opts, (err, result) => {
|
||||
if (err)
|
||||
return cb(err);
|
||||
|
||||
opts.range = network.calculate(opts);
|
||||
funcs = this.funcs(opts);
|
||||
|
||||
return cb(null, {
|
||||
opts,
|
||||
funcs
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
// Provenance: roest01/node-pdf-image (fixed).
|
||||
// repo: roest01/node-pdf-image
|
||||
// commit: 54679496a89738443917608c2bbe2f6e5dd20e83
|
||||
// parent: d8c0dcadd93985dbefe80b84060f5f572bfbb6ff
|
||||
// commit_url: https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83
|
||||
// cve: CVE-2018-3757
|
||||
// license: MIT
|
||||
// function: getInfo
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 24
|
||||
|
||||
PDFImage.prototype = {
|
||||
constructGetInfoCommand: function () {
|
||||
return {
|
||||
cmd: "pdfinfo",
|
||||
args: [this.pdfFilePath]
|
||||
};
|
||||
},
|
||||
parseGetInfoCommandOutput: function (output) {
|
||||
var info = {};
|
||||
output.split("\n").forEach(function (line) {
|
||||
if (line.match(/^(.*?):[ \t]*(.*)$/)) {
|
||||
info[RegExp.$1] = RegExp.$2;
|
||||
}
|
||||
});
|
||||
return info;
|
||||
},
|
||||
getInfo: function () {
|
||||
var self = this;
|
||||
var getInfoCommand = this.constructGetInfoCommand();
|
||||
return new Promise(function (resolve, reject) {
|
||||
spawn(getInfoCommand.cmd, getInfoCommand.args, { capture: [ 'stdout', 'stderr' ]})
|
||||
.then(function (cmdResult) {
|
||||
resolve(self.parseGetInfoCommandOutput(cmdResult.stdout.toString()));
|
||||
}).catch(reject);
|
||||
});
|
||||
},
|
||||
numberOfPages: function () {
|
||||
return this.getInfo().then(function (info) {
|
||||
return info["Pages"];
|
||||
});
|
||||
},
|
||||
getOutputImagePathForPage: function (pageNumber) {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "-" + pageNumber + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
getOutputImagePathForFile: function () {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
setConvertOptions: function (convertOptions) {
|
||||
this.convertOptions = convertOptions || {};
|
||||
},
|
||||
setPdfFileBaseName: function(pdfFileBaseName) {
|
||||
this.pdfFileBaseName = pdfFileBaseName || path.basename(this.pdfFilePath, ".pdf");
|
||||
},
|
||||
setConvertExtension: function (convertExtension) {
|
||||
this.convertExtension = convertExtension || "png";
|
||||
},
|
||||
constructConvertCommandForPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertOptions = this.constructConvertOptions();
|
||||
var args = [];
|
||||
if (convertOptions) args = convertOptions.slice();
|
||||
args.push(pdfFilePath+"["+pageNumber+"]");
|
||||
args.push(outputImagePath);
|
||||
|
||||
return {
|
||||
cmd: this.useGM ? "gm convert" : "convert",
|
||||
args: args
|
||||
};
|
||||
},
|
||||
constructCombineCommandForFile: function (imagePaths) {
|
||||
var args = imagePaths.slice();
|
||||
args.push(this.getOutputImagePathForFile());
|
||||
args.unshift("-append");
|
||||
return {
|
||||
cmd: this.useGM ? "gm convert" : "convert",
|
||||
args: args
|
||||
};
|
||||
},
|
||||
constructConvertOptions: function () {
|
||||
var convertOptions = [];
|
||||
Object.keys(this.convertOptions).sort().map(function (optionName) {
|
||||
if (this.convertOptions[optionName] !== null) {
|
||||
convertOptions.push(optionName);
|
||||
convertOptions.push(this.convertOptions[optionName]);
|
||||
} else {
|
||||
convertOptions.push(optionName);
|
||||
}
|
||||
}, this);
|
||||
return convertOptions;
|
||||
},
|
||||
combineImages: function(imagePaths) {
|
||||
var pdfImage = this;
|
||||
var combineCommand = pdfImage.constructCombineCommandForFile(imagePaths);
|
||||
return new Promise(function (resolve, reject) {
|
||||
spawn(combineCommand.cmd, combineCommand.args, { capture: [ 'stdout', 'stderr' ]})
|
||||
.then(function () {
|
||||
spawn("rm", imagePaths); //cleanUp
|
||||
resolve(pdfImage.getOutputImagePathForFile());
|
||||
}).catch(function(error){
|
||||
reject({
|
||||
message: "Failed to combine images",
|
||||
error: error.message,
|
||||
stdout: error.stdout,
|
||||
stderr: error.stderr
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
convertFile: function () {
|
||||
var pdfImage = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
pdfImage.numberOfPages().then(function (totalPages) {
|
||||
var convertPromise = new Promise(function (resolve, reject){
|
||||
var imagePaths = [];
|
||||
for (var i = 0; i < totalPages; i++) {
|
||||
pdfImage.convertPage(i).then(function(imagePath){
|
||||
imagePaths.push(imagePath);
|
||||
if (imagePaths.length === parseInt(totalPages)){
|
||||
imagePaths.sort(); //because of asyc pages we have to reSort pages
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
convertPromise.then(function(imagePaths){
|
||||
if (pdfImage.combinedImage){
|
||||
pdfImage.combineImages(imagePaths).then(function(imagePath){
|
||||
resolve(imagePath);
|
||||
});
|
||||
} else {
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
convertPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertCommand = this.constructConvertCommandForPage(pageNumber);
|
||||
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
function convertPageToImage() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
spawn(convertCommand.cmd, convertCommand.args, { capture: [ 'stdout', 'stderr' ]})
|
||||
.then(function () {
|
||||
resolve(outputImagePath);
|
||||
}).catch(function(error){
|
||||
reject({
|
||||
message: "Failed to convert page to image",
|
||||
error: error.message,
|
||||
stdout: error.stdout,
|
||||
stderr: error.stderr
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fs.stat(outputImagePath, function (err, imageFileStat) {
|
||||
var imageNotExists = err && err.code === "ENOENT";
|
||||
if (!imageNotExists && err) {
|
||||
return reject({
|
||||
message: "Failed to stat image file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
// convert when (1) image doesn't exits or (2) image exists
|
||||
// but its timestamp is older than pdf's one
|
||||
|
||||
if (imageNotExists) {
|
||||
// (1)
|
||||
convertPageToImage().then(function(result){
|
||||
resolve(result);
|
||||
}).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
// image exist. check timestamp.
|
||||
fs.stat(pdfFilePath, function (err, pdfFileStat) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to stat PDF file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
if (imageFileStat.mtime < pdfFileStat.mtime) {
|
||||
// (2)
|
||||
convertPageToImage().then(function(result){
|
||||
resolve(result);
|
||||
}).catch(reject);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,212 @@
|
||||
// Provenance: roest01/node-pdf-image (vuln).
|
||||
// repo: roest01/node-pdf-image
|
||||
// commit: d8c0dcadd93985dbefe80b84060f5f572bfbb6ff
|
||||
// parent: d8c0dcadd93985dbefe80b84060f5f572bfbb6ff
|
||||
// commit_url: https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83
|
||||
// cve: CVE-2018-3757
|
||||
// license: MIT
|
||||
// function: getInfo
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 24
|
||||
|
||||
PDFImage.prototype = {
|
||||
constructGetInfoCommand: function () {
|
||||
return util.format(
|
||||
"pdfinfo \"%s\"",
|
||||
this.pdfFilePath
|
||||
);
|
||||
},
|
||||
parseGetInfoCommandOutput: function (output) {
|
||||
var info = {};
|
||||
output.split("\n").forEach(function (line) {
|
||||
if (line.match(/^(.*?):[ \t]*(.*)$/)) {
|
||||
info[RegExp.$1] = RegExp.$2;
|
||||
}
|
||||
});
|
||||
return info;
|
||||
},
|
||||
getInfo: function () {
|
||||
var self = this;
|
||||
var getInfoCommand = this.constructGetInfoCommand();
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
exec(getInfoCommand, function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to get PDF'S information",
|
||||
error: err,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
return resolve(self.parseGetInfoCommandOutput(stdout));
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
numberOfPages: function () {
|
||||
return this.getInfo().then(function (info) {
|
||||
return info["Pages"];
|
||||
});
|
||||
},
|
||||
getOutputImagePathForPage: function (pageNumber) {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "-" + pageNumber + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
getOutputImagePathForFile: function () {
|
||||
return path.join(
|
||||
this.outputDirectory,
|
||||
this.pdfFileBaseName + "." + this.convertExtension
|
||||
);
|
||||
},
|
||||
setConvertOptions: function (convertOptions) {
|
||||
this.convertOptions = convertOptions || {};
|
||||
},
|
||||
setPdfFileBaseName: function(pdfFileBaseName) {
|
||||
this.pdfFileBaseName = pdfFileBaseName || path.basename(this.pdfFilePath, ".pdf");
|
||||
},
|
||||
setConvertExtension: function (convertExtension) {
|
||||
this.convertExtension = convertExtension || "png";
|
||||
},
|
||||
constructConvertCommandForPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertOptionsString = this.constructConvertOptions();
|
||||
return util.format(
|
||||
"%s %s\"%s[%d]\" \"%s\"",
|
||||
this.useGM ? "gm convert" : "convert",
|
||||
convertOptionsString ? convertOptionsString + " " : "",
|
||||
pdfFilePath, pageNumber, outputImagePath
|
||||
);
|
||||
},
|
||||
constructCombineCommandForFile: function (imagePaths) {
|
||||
return util.format(
|
||||
"%s -append %s \"%s\"",
|
||||
this.useGM ? "gm convert" : "convert",
|
||||
imagePaths.join(' '),
|
||||
this.getOutputImagePathForFile()
|
||||
);
|
||||
},
|
||||
constructConvertOptions: function () {
|
||||
return Object.keys(this.convertOptions).sort().map(function (optionName) {
|
||||
if (this.convertOptions[optionName] !== null) {
|
||||
return optionName + " " + this.convertOptions[optionName];
|
||||
} else {
|
||||
return optionName;
|
||||
}
|
||||
}, this).join(" ");
|
||||
},
|
||||
combineImages: function(imagePaths) {
|
||||
var pdfImage = this;
|
||||
var combineCommand = pdfImage.constructCombineCommandForFile(imagePaths);
|
||||
return new Promise(function (resolve, reject) {
|
||||
exec(combineCommand, function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to combine images",
|
||||
error: err,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
exec("rm "+imagePaths.join(' ')); //cleanUp
|
||||
return resolve(pdfImage.getOutputImagePathForFile());
|
||||
});
|
||||
});
|
||||
},
|
||||
convertFile: function () {
|
||||
var pdfImage = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
pdfImage.numberOfPages().then(function (totalPages) {
|
||||
var convertPromise = new Promise(function (resolve, reject){
|
||||
var imagePaths = [];
|
||||
for (var i = 0; i < totalPages; i++) {
|
||||
pdfImage.convertPage(i).then(function(imagePath){
|
||||
imagePaths.push(imagePath);
|
||||
if (imagePaths.length === parseInt(totalPages)){
|
||||
imagePaths.sort(); //because of asyc pages we have to reSort pages
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
convertPromise.then(function(imagePaths){
|
||||
if (pdfImage.combinedImage){
|
||||
pdfImage.combineImages(imagePaths).then(function(imagePath){
|
||||
resolve(imagePath);
|
||||
});
|
||||
} else {
|
||||
resolve(imagePaths);
|
||||
}
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
convertPage: function (pageNumber) {
|
||||
var pdfFilePath = this.pdfFilePath;
|
||||
var outputImagePath = this.getOutputImagePathForPage(pageNumber);
|
||||
var convertCommand = this.constructConvertCommandForPage(pageNumber);
|
||||
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
function convertPageToImage() {
|
||||
exec(convertCommand, function (err, stdout, stderr) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to convert page to image",
|
||||
error: err,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
});
|
||||
}
|
||||
return resolve(outputImagePath);
|
||||
});
|
||||
}
|
||||
|
||||
fs.stat(outputImagePath, function (err, imageFileStat) {
|
||||
var imageNotExists = err && err.code === "ENOENT";
|
||||
if (!imageNotExists && err) {
|
||||
return reject({
|
||||
message: "Failed to stat image file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
// convert when (1) image doesn't exits or (2) image exists
|
||||
// but its timestamp is older than pdf's one
|
||||
|
||||
if (imageNotExists) {
|
||||
// (1)
|
||||
convertPageToImage();
|
||||
return;
|
||||
}
|
||||
|
||||
// image exist. check timestamp.
|
||||
fs.stat(pdfFilePath, function (err, pdfFileStat) {
|
||||
if (err) {
|
||||
return reject({
|
||||
message: "Failed to stat PDF file",
|
||||
error: err
|
||||
});
|
||||
}
|
||||
|
||||
if (imageFileStat.mtime < pdfFileStat.mtime) {
|
||||
// (2)
|
||||
convertPageToImage();
|
||||
return;
|
||||
}
|
||||
|
||||
return resolve(outputImagePath);
|
||||
});
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,198 @@
|
||||
// Provenance: soyuka/pidusage (fixed).
|
||||
// repo: soyuka/pidusage
|
||||
// commit: b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d
|
||||
// parent: e3660d8a8e5e61afad9b02af67356a1e239d6bde
|
||||
// commit_url: https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d
|
||||
// cve: CVE-2017-16034
|
||||
// license: MIT
|
||||
// function: ps
|
||||
// relpath: lib/stats.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 1
|
||||
|
||||
var os = require('os')
|
||||
var fs = require('fs')
|
||||
var p = require('path')
|
||||
var exec = require('child_process').exec
|
||||
var spawn = require('child_process').spawn
|
||||
var helpers = require('./helpers')
|
||||
var format = require('util').format
|
||||
|
||||
var stats = {
|
||||
history: {},
|
||||
cpu: null, //used to store cpu informations
|
||||
proc: function(pid, options, done) {
|
||||
var self = this
|
||||
|
||||
if(this.cpu !== null) {
|
||||
fs.readFile('/proc/uptime', 'utf8', function(err, uptime) {
|
||||
if(err) {
|
||||
return done(err, null)
|
||||
}
|
||||
|
||||
if(uptime === undefined) {
|
||||
console.error("[pidusage] We couldn't find uptime from /proc/uptime")
|
||||
self.cpu.uptime = os.uptime()
|
||||
} else {
|
||||
self.cpu.uptime = uptime.split(' ')[0]
|
||||
}
|
||||
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
} else {
|
||||
helpers.cpu(function(err, cpu) {
|
||||
if(err) {
|
||||
return done(err, null)
|
||||
}
|
||||
|
||||
self.cpu = cpu
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
}
|
||||
},
|
||||
proc_calc: function(pid, options, done) {
|
||||
pid = parseInt(pid, 10)
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
var cpu = this.cpu
|
||||
var self = this
|
||||
|
||||
//Arguments to path.join must be strings
|
||||
fs.readFile(p.join('/proc', ''+pid, 'stat'), 'utf8', function(err, infos) {
|
||||
if(err) {
|
||||
return done(err, null)
|
||||
}
|
||||
|
||||
//https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
|
||||
//preventing process space in name by removing values before last ) (pid (name) ...)
|
||||
var index = infos.lastIndexOf(')')
|
||||
infos = infos.substr(index + 2).split(' ')
|
||||
|
||||
//according to http://man7.org/linux/man-pages/man5/proc.5.html (index 0 based - 2)
|
||||
//In kernels before Linux 2.6, start was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
|
||||
var stat = {
|
||||
utime: parseFloat(infos[11]),
|
||||
stime: parseFloat(infos[12]),
|
||||
cutime: parseFloat(infos[13]),
|
||||
cstime: parseFloat(infos[14]),
|
||||
start: parseFloat(infos[19]) / cpu.clock_tick,
|
||||
rss: parseFloat(infos[21])
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/16726779/total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599
|
||||
|
||||
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
|
||||
|
||||
var total = stat.stime - (history.stime || 0) + stat.utime - (history.utime || 0) + childrens
|
||||
|
||||
total = total / cpu.clock_tick
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? cpu.uptime - history.uptime : stat.start - cpu.uptime
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stat
|
||||
self.history[pid].uptime = cpu.uptime
|
||||
|
||||
return done(null, {
|
||||
cpu: (total / seconds) * 100,
|
||||
memory: stat.rss * cpu.pagesize
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Get pid informations through ps command
|
||||
* @param {int} pid
|
||||
* @return {Function} done (err, stat)
|
||||
* on os x skip headers with pcpu=,rss=
|
||||
* on linux it could be --no-header
|
||||
* on solaris 11 can't figure out a way to do this properly so...
|
||||
*/
|
||||
ps: function(pid, options, done) {
|
||||
pid = parseInt(pid, 10)
|
||||
var cmd = 'ps -o pcpu,rss -p '
|
||||
|
||||
if(os.platform() == 'aix')
|
||||
cmd = 'ps -o pcpu,rssize -p ' //this one could work on other platforms
|
||||
|
||||
exec(cmd + pid, function(err, stdout, stderr) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
stdout = stdout.split(os.EOL)[1]
|
||||
stdout = stdout.replace(/^\s+/, '').replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
return done(null, {
|
||||
cpu: parseFloat(stdout[0].replace(',', '.')),
|
||||
memory: parseFloat(stdout[1]) * 1024
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* This is really in a beta stage
|
||||
*/
|
||||
win: function(pid, options, done) {
|
||||
pid = parseInt(pid, 10)
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/469ec6b7-4727-4773-9dc7-6e3de40e87b8/cpu-usage-in-for-each-active-process-how-is-this-best-determined-and-implemented-in-an?forum=csharplanguage
|
||||
var args = 'PROCESS ' + pid + ' get workingsetsize,usermodetime,kernelmodetime'
|
||||
|
||||
var wmic = spawn('wmic', args.split(' '), {detached: true})
|
||||
var stdout = ''
|
||||
var stderr = ''
|
||||
var self = this
|
||||
var uptime = os.uptime()
|
||||
|
||||
wmic.stdout.on('data', function(d) {
|
||||
stdout += d.toString()
|
||||
})
|
||||
|
||||
wmic.stderr.on('data', function(d) {
|
||||
stderr += d.toString()
|
||||
})
|
||||
|
||||
wmic.on('error', function(err) {
|
||||
console.error('[pidusage] Command "wmic ' + args + '" failed with error %s', err)
|
||||
})
|
||||
|
||||
wmic.on('close', function(code) {
|
||||
stdout = stdout.trim()
|
||||
stderr = stderr.trim()
|
||||
|
||||
if(!stdout || code !== 0) {
|
||||
var error = format('%s Wmic errored, please open an issue on https://github.com/soyuka/pidusage with this message.%s', new Date().toString(), os.EOL)
|
||||
error += format('Command was "wmic %s" %s System informations: %s - release: %s %s - type %s %s', args, os.EOL, os.EOL, os.release(), os.EOL, os.type(), os.EOL)
|
||||
stderr = error + (stderr ? format('Wmic reported the following error: %s.', stderr) : 'Wmic reported no errors (stderr empty).')
|
||||
stderr = format('%s%s%sWmic exited with code %d.', os.EOL, stderr, os.EOL, code)
|
||||
stderr = format('%s%sStdout was %s', stderr, os.EOL, stdout ? stdout : 'empty')
|
||||
|
||||
return done(new Error(stderr, null))
|
||||
}
|
||||
|
||||
stdout = stdout.split(os.EOL)[1].replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
var stats = {
|
||||
kernelmodetime: parseFloat(stdout[0]),
|
||||
usermodetime: parseFloat(stdout[1]),
|
||||
}
|
||||
|
||||
var workingsetsize = parseFloat(stdout[2])
|
||||
|
||||
//process usage since last call
|
||||
var total = stats.kernelmodetime - (history.kernelmodetime || 0) + stats.usermodetime - (history.usermodetime || 0)
|
||||
total = total / 10000000
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? uptime - history.uptime : 0
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stats
|
||||
self.history[pid].uptime = uptime
|
||||
|
||||
return done(null, {cpu: (total / seconds) * 100, memory: workingsetsize})
|
||||
})
|
||||
wmic.stdin.end()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
// Provenance: soyuka/pidusage (vuln).
|
||||
// repo: soyuka/pidusage
|
||||
// commit: e3660d8a8e5e61afad9b02af67356a1e239d6bde
|
||||
// parent: e3660d8a8e5e61afad9b02af67356a1e239d6bde
|
||||
// commit_url: https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d
|
||||
// cve: CVE-2017-16034
|
||||
// license: MIT
|
||||
// function: ps
|
||||
// relpath: lib/stats.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 1
|
||||
|
||||
var os = require('os')
|
||||
var fs = require('fs')
|
||||
var p = require('path')
|
||||
var exec = require('child_process').exec
|
||||
var spawn = require('child_process').spawn
|
||||
var helpers = require('./helpers')
|
||||
var format = require('util').format
|
||||
|
||||
var stats = {
|
||||
history: {},
|
||||
cpu: null, //used to store cpu informations
|
||||
proc: function(pid, options, done) {
|
||||
var self = this
|
||||
|
||||
if(this.cpu !== null) {
|
||||
fs.readFile('/proc/uptime', 'utf8', function(err, uptime) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
if(uptime === undefined) {
|
||||
console.error("[pidusage] We couldn't find uptime from /proc/uptime")
|
||||
self.cpu.uptime = os.uptime()
|
||||
} else {
|
||||
self.cpu.uptime = uptime.split(' ')[0]
|
||||
}
|
||||
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
} else {
|
||||
helpers.cpu(function(err, cpu) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
self.cpu = cpu
|
||||
return self.proc_calc(pid, options, done)
|
||||
})
|
||||
}
|
||||
},
|
||||
proc_calc: function(pid, options, done) {
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
var cpu = this.cpu
|
||||
var self = this
|
||||
|
||||
//Arguments to path.join must be strings
|
||||
fs.readFile(p.join('/proc', ''+pid, 'stat'), 'utf8', function(err, infos) {
|
||||
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
//https://github.com/arunoda/node-usage/commit/a6ca74ecb8dd452c3c00ed2bde93294d7bb75aa8
|
||||
//preventing process space in name by removing values before last ) (pid (name) ...)
|
||||
var index = infos.lastIndexOf(')')
|
||||
infos = infos.substr(index + 2).split(' ')
|
||||
|
||||
//according to http://man7.org/linux/man-pages/man5/proc.5.html (index 0 based - 2)
|
||||
//In kernels before Linux 2.6, start was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
|
||||
var stat = {
|
||||
utime: parseFloat(infos[11]),
|
||||
stime: parseFloat(infos[12]),
|
||||
cutime: parseFloat(infos[13]),
|
||||
cstime: parseFloat(infos[14]),
|
||||
start: parseFloat(infos[19]) / cpu.clock_tick,
|
||||
rss: parseFloat(infos[21])
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/16726779/total-cpu-usage-of-an-application-from-proc-pid-stat/16736599#16736599
|
||||
|
||||
var childrens = options.childrens ? stat.cutime + stat.cstime : 0
|
||||
|
||||
var total = stat.stime - (history.stime || 0) + stat.utime - (history.utime || 0) + childrens
|
||||
|
||||
total = total / cpu.clock_tick
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? cpu.uptime - history.uptime : stat.start - cpu.uptime
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stat
|
||||
self.history[pid].uptime = cpu.uptime
|
||||
|
||||
return done(null, {
|
||||
cpu: (total / seconds) * 100,
|
||||
memory: stat.rss * cpu.pagesize
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* Get pid informations through ps command
|
||||
* @param {int} pid
|
||||
* @return {Function} done (err, stat)
|
||||
* on os x skip headers with pcpu=,rss=
|
||||
* on linux it could be --no-header
|
||||
* on solaris 11 can't figure out a way to do this properly so...
|
||||
*/
|
||||
ps: function(pid, options, done) {
|
||||
|
||||
var cmd = 'ps -o pcpu,rss -p '
|
||||
|
||||
if(os.platform() == 'aix')
|
||||
cmd = 'ps -o pcpu,rssize -p ' //this one could work on other platforms
|
||||
|
||||
exec(cmd + pid, function(err, stdout, stderr) {
|
||||
if(err)
|
||||
return done(err, null)
|
||||
|
||||
stdout = stdout.split(os.EOL)[1]
|
||||
stdout = stdout.replace(/^\s+/, '').replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
return done(null, {
|
||||
cpu: parseFloat(stdout[0].replace(',', '.')),
|
||||
memory: parseFloat(stdout[1]) * 1024
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* This is really in a beta stage
|
||||
*/
|
||||
win: function(pid, options, done) {
|
||||
var history = this.history[pid] ? this.history[pid] : {}
|
||||
// http://social.msdn.microsoft.com/Forums/en-US/469ec6b7-4727-4773-9dc7-6e3de40e87b8/cpu-usage-in-for-each-active-process-how-is-this-best-determined-and-implemented-in-an?forum=csharplanguage
|
||||
var args = 'PROCESS ' + pid + ' get workingsetsize,usermodetime,kernelmodetime'
|
||||
|
||||
var wmic = spawn('wmic', args.split(' '), {detached: true})
|
||||
var stdout = ''
|
||||
var stderr = ''
|
||||
var self = this
|
||||
var uptime = os.uptime()
|
||||
|
||||
wmic.stdout.on('data', function(d) {
|
||||
stdout += d.toString()
|
||||
})
|
||||
|
||||
wmic.stderr.on('data', function(d) {
|
||||
stderr += d.toString()
|
||||
})
|
||||
|
||||
wmic.on('error', function(err) {
|
||||
console.error('[pidusage] Command "wmic ' + args + '" failed with error %s', err)
|
||||
})
|
||||
|
||||
wmic.on('close', function(code) {
|
||||
stdout = stdout.trim()
|
||||
stderr = stderr.trim()
|
||||
|
||||
if(!stdout || code !== 0) {
|
||||
var error = format('%s Wmic errored, please open an issue on https://github.com/soyuka/pidusage with this message.%s', new Date().toString(), os.EOL)
|
||||
error += format('Command was "wmic %s" %s System informations: %s - release: %s %s - type %s %s', args, os.EOL, os.EOL, os.release(), os.EOL, os.type(), os.EOL)
|
||||
stderr = error + (stderr ? format('Wmic reported the following error: %s.', stderr) : 'Wmic reported no errors (stderr empty).')
|
||||
stderr = format('%s%s%sWmic exited with code %d.', os.EOL, stderr, os.EOL, code)
|
||||
stderr = format('%s%sStdout was %s', stderr, os.EOL, stdout ? stdout : 'empty')
|
||||
|
||||
return done(new Error(stderr, null))
|
||||
}
|
||||
|
||||
stdout = stdout.split(os.EOL)[1].replace(/\s\s+/g, ' ').split(' ')
|
||||
|
||||
var stats = {
|
||||
kernelmodetime: parseFloat(stdout[0]),
|
||||
usermodetime: parseFloat(stdout[1]),
|
||||
}
|
||||
|
||||
var workingsetsize = parseFloat(stdout[2])
|
||||
|
||||
//process usage since last call
|
||||
var total = stats.kernelmodetime - (history.kernelmodetime || 0) + stats.usermodetime - (history.usermodetime || 0)
|
||||
total = total / 10000000
|
||||
|
||||
//time elapsed between calls
|
||||
var seconds = history.uptime !== undefined ? uptime - history.uptime : 0
|
||||
seconds = Math.abs(seconds)
|
||||
seconds = seconds === 0 ? 1 : seconds //we sure can't divide through 0
|
||||
|
||||
self.history[pid] = stats
|
||||
self.history[pid].uptime = uptime
|
||||
|
||||
return done(null, {cpu: (total / seconds) * 100, memory: workingsetsize})
|
||||
})
|
||||
wmic.stdin.end()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Provenance: rrainn/PortProcesses (fixed).
|
||||
// repo: rrainn/PortProcesses
|
||||
// commit: 86811216c9b97b01b5722f879f8c88a7aa4214e1
|
||||
// parent: fffceb09aff7180afbd0bd172e820404b33c8299
|
||||
// commit_url: https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1
|
||||
// cve: CVE-2021-23348
|
||||
// license: MIT
|
||||
// function: listProcessesOnPort
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 2
|
||||
|
||||
const listProcessesOnPort = module.exports.listProcessesOnPort = async port => {
|
||||
const portNumber = parseInt(port, 10);
|
||||
if (Number.isNaN(portNumber)) {
|
||||
console.error("Must provide number for port.");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = (await exec(`lsof -i :${portNumber}`)).output.split('\n');
|
||||
const headers = result.shift().split(' ').filter(item => !!item.trim() && item.trim() !== "").map(item => item.toLowerCase());
|
||||
return result.filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue) => {
|
||||
accumulator.push(currentValue.split(' ').filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue, index) => {
|
||||
if (index > headers.length - 1) {
|
||||
accumulator[headers[headers.length - 1]] = (!!accumulator[headers[headers.length - 1]].trim() && accumulator[headers[headers.length - 1]].trim() !== "") ? `${accumulator[headers[headers.length - 1]]} ${currentValue}` : currentValue;
|
||||
} else {
|
||||
accumulator[headers[index]] = currentValue;
|
||||
}
|
||||
return accumulator;
|
||||
}, {}));
|
||||
return accumulator;
|
||||
}, []);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
// Provenance: rrainn/PortProcesses (vuln).
|
||||
// repo: rrainn/PortProcesses
|
||||
// commit: fffceb09aff7180afbd0bd172e820404b33c8299
|
||||
// parent: fffceb09aff7180afbd0bd172e820404b33c8299
|
||||
// commit_url: https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1
|
||||
// cve: CVE-2021-23348
|
||||
// license: MIT
|
||||
// function: listProcessesOnPort
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 2
|
||||
|
||||
const listProcessesOnPort = module.exports.listProcessesOnPort = async port => {
|
||||
try {
|
||||
const result = (await exec(`lsof -i :${port}`)).output.split('\n');
|
||||
const headers = result.shift().split(' ').filter(item => !!item.trim() && item.trim() !== "").map(item => item.toLowerCase());
|
||||
return result.filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue) => {
|
||||
accumulator.push(currentValue.split(' ').filter(item => !!item.trim() && item.trim() !== "").reduce((accumulator, currentValue, index) => {
|
||||
if (index > headers.length - 1) {
|
||||
accumulator[headers[headers.length - 1]] = (!!accumulator[headers[headers.length - 1]].trim() && accumulator[headers[headers.length - 1]].trim() !== "") ? `${accumulator[headers[headers.length - 1]]} ${currentValue}` : currentValue;
|
||||
} else {
|
||||
accumulator[headers[index]] = currentValue;
|
||||
}
|
||||
return accumulator;
|
||||
}, {}));
|
||||
return accumulator;
|
||||
}, []);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,602 @@
|
||||
# vfc-js harvest recipes derived from SecBench.js fixCommit metadata by build_recipes.py.
|
||||
# Excerpts come from the upstream package repository (its license), never from SecBench.js.
|
||||
|
||||
[[recipe]]
|
||||
name = "angular-http-server-1-0-0"
|
||||
host = "github"
|
||||
repo = "simonh1000/angular-http-server"
|
||||
parent = "d171a771a92e4685b24fb77cb894a7b7b8024c5c"
|
||||
commit = "8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
path = "angular-http-server.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "angular-http-server.js"
|
||||
license = "Apache-2.0"
|
||||
cve = ""
|
||||
year = 2018
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "angular-http-server"
|
||||
sink_location = "angular-http-server.js:16:29"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink angular-http-server.js:16:29 fixed upstream in 8bafc9577161"
|
||||
commit_url = "https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "apex-publish-static-files-2-0-0"
|
||||
host = "github"
|
||||
repo = "vincentmorneau/apex-publish-static-files"
|
||||
parent = "8d28fe8a9a49e5ff3f61e239293b5646528e2915"
|
||||
commit = "2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-16462"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "apex-publish-static-files"
|
||||
sink_location = "index.js:54:25"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:54:25 fixed upstream in 2209af8f2b65"
|
||||
commit_url = "https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "arpping-2-0-0"
|
||||
host = "github"
|
||||
repo = "haf-decent/arpping"
|
||||
parent = "ce9efe8ab7f059ddf45ae4f8f7587689ac3c068c"
|
||||
commit = "0db06723f8c3c73a5cc0829c667d45cba25ca44d"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2021
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "arpping"
|
||||
sink_location = "index.js:120:13"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:120:13 fixed upstream in 0db06723f8c3"
|
||||
commit_url = "https://github.com/haf-decent/arpping/commit/0db06723f8c3c73a5cc0829c667d45cba25ca44d"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "bestzip-2-1-6"
|
||||
host = "github"
|
||||
repo = "nfriedly/node-bestzip"
|
||||
parent = "fcea252e52b6078eff6caf5531bd32c53fccb59f"
|
||||
commit = "45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
path = "lib/bestzip.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/bestzip.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7730"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "bestzip"
|
||||
sink_location = "lib/bestzip.js:27:27"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/bestzip.js:27:27 fixed upstream in 45d4a901478c"
|
||||
commit_url = "https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "clamscan-1-2-0"
|
||||
host = "github"
|
||||
repo = "kylefarris/clamscan"
|
||||
parent = "d474da7b89c0d3397cd681e79c7bcc592bff144b"
|
||||
commit = "5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7613"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "clamscan"
|
||||
sink_location = "index.js:495:36"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:495:36 fixed upstream in 5f557c970817"
|
||||
commit_url = "https://github.com/kylefarris/clamscan/commit/5f557c970817fe8c578ec3f7ad3bcbcef4cf5538"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "codecov-3-6-4"
|
||||
host = "github"
|
||||
repo = "codecov/codecov-node"
|
||||
parent = "5f6cc62d4f83bf3a75c973868259798814cd231e"
|
||||
commit = "c0711c656686e902af2cd92d6aecc8074de4d83d"
|
||||
path = "lib/codecov.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/codecov.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-15123"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "codecov"
|
||||
sink_location = "lib/codecov.js:419:7"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/codecov.js:419:7 fixed upstream in c0711c656686"
|
||||
commit_url = "https://github.com/codecov/codecov-node/commit/c0711c656686e902af2cd92d6aecc8074de4d83d"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "crud-file-server-0-7-0"
|
||||
host = "github"
|
||||
repo = "omphalos/crud-file-server"
|
||||
parent = "833e7fcc2bc8406b9c76836a51ae173f50c56bf0"
|
||||
commit = "4fc3b404f718abb789f4ce4272c39c7a138c7a82"
|
||||
path = "crud-file-server.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "crud-file-server.js"
|
||||
license = "Unlicense"
|
||||
cve = "CVE-2018-3733"
|
||||
year = 2018
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "crud-file-server"
|
||||
sink_location = "crud-file-server.js:170:14"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink crud-file-server.js:170:14 fixed upstream in 4fc3b404f718"
|
||||
commit_url = "https://github.com/omphalos/crud-file-server/commit/4fc3b404f718abb789f4ce4272c39c7a138c7a82"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "diskusage-ng-0-2-6"
|
||||
host = "github"
|
||||
repo = "iximiuz/node-diskusage-ng"
|
||||
parent = "53c505506553c83861d1bd67823d6a382d3a5a43"
|
||||
commit = "48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
path = "lib/posix.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/posix.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7631"
|
||||
year = 2020
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "diskusage-ng"
|
||||
sink_location = "lib/posix.js:11:5"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/posix.js:11:5 fixed upstream in 48e7e093486b"
|
||||
commit_url = "https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "dns-sync-0-1-0"
|
||||
host = "github"
|
||||
repo = "skoranga/node-dns-sync"
|
||||
parent = "b748fe77a87749d95876028eda8e759109be4c73"
|
||||
commit = "d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
path = "lib/dns-sync.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/dns-sync.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2014-9682"
|
||||
year = 2014
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "dns-sync"
|
||||
sink_location = "lib/dns-sync.js:21:26"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/dns-sync.js:21:26 fixed upstream in d9abaae384b1"
|
||||
commit_url = "https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "get-npm-package-version-1-0-6"
|
||||
host = "github"
|
||||
repo = "hoperyy/get-npm-package-version"
|
||||
parent = "52797864df09049ea28d65d14620774257a965b0"
|
||||
commit = "40b1cf31a0607ea66f9e30a0c3af1383b52b2dec"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "ISC"
|
||||
cve = "CVE-2020-7795"
|
||||
year = 2021
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "get-npm-package-version"
|
||||
sink_location = "index.js:16:48"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:16:48 fixed upstream in 40b1cf31a060"
|
||||
commit_url = "https://github.com/hoperyy/get-npm-package-version/commit/40b1cf31a0607ea66f9e30a0c3af1383b52b2dec"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "glance-3-0-0"
|
||||
host = "github"
|
||||
repo = "jarofghosts/glance"
|
||||
parent = "7e69a5539236386e747fb240ae87ea65ed64bb2c"
|
||||
commit = "8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-3715"
|
||||
year = 2018
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "glance"
|
||||
sink_location = "index.js:81:14"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink index.js:81:14 fixed upstream in 8cfd88e44ebd"
|
||||
commit_url = "https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "hostr-2-0-0"
|
||||
host = "github"
|
||||
repo = "henrytseng/hostr"
|
||||
parent = "5827ba48fd4a08c26604b97798c57d45fe1cd51e"
|
||||
commit = "789a00047459fd80b6f0a9701a1378a47fb73ba8"
|
||||
path = "lib/routes/statics.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/routes/statics.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2017-16029"
|
||||
year = 2016
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "hostr"
|
||||
sink_location = "lib/routes/static.js:56:27"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink lib/routes/static.js:56:27 fixed upstream in 789a00047459"
|
||||
commit_url = "https://github.com/henrytseng/hostr/commit/789a00047459fd80b6f0a9701a1378a47fb73ba8"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "hot-formula-parser-3-0-0"
|
||||
host = "github"
|
||||
repo = "handsontable/formula-parser"
|
||||
parent = "944136096f44ff4ffd4ba0bcef30970ca4702fce"
|
||||
commit = "396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
path = "src/grammar-parser/grammar-parser.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "src/grammar-parser/grammar-parser.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-6836"
|
||||
year = 2019
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "hot-formula-parser"
|
||||
sink_location = "lib/grammar-parser/grammar-parser.js:258:31"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/grammar-parser/grammar-parser.js:258:31 fixed upstream in 396b089738d4"
|
||||
commit_url = "https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "is-my-json-valid-2-20-0"
|
||||
host = "github"
|
||||
repo = "mafintosh/is-my-json-valid"
|
||||
parent = "adf40bd9f22f6c9ee7d4c612c4193a7b835416bc"
|
||||
commit = "3419563687df463b4ca709a2b46be8e15d6a2b3d"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2020
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "is-my-json-valid"
|
||||
sink_location = "index.js:172:21"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink index.js:172:21 fixed upstream in 3419563687df"
|
||||
commit_url = "https://github.com/mafintosh/is-my-json-valid/commit/3419563687df463b4ca709a2b46be8e15d6a2b3d"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "libnmap-0-4-11"
|
||||
host = "github"
|
||||
repo = "jas-/node-libnmap"
|
||||
parent = "49b72239b144ab7ffdf673b62e18bfd0760948f6"
|
||||
commit = "c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
path = "lib/classes/tools.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/classes/tools.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-16461"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "libnmap"
|
||||
sink_location = "lib/classes/tools.js:114:25"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/classes/tools.js:114:25 fixed upstream in c235b24b0342"
|
||||
commit_url = "https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "node-simple-router-0-10-0"
|
||||
host = "github"
|
||||
repo = "sandy98/node-simple-router"
|
||||
parent = "91da4299aee0086cc1e0cc837763578af6f82cea"
|
||||
commit = "dfdd52e2e80607af433097d940b3834fd96df488"
|
||||
path = "lib/router.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/router.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2017-16083"
|
||||
year = 2017
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "node-simple-router"
|
||||
sink_location = "lib/router.js:757:27"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink lib/router.js:757:27 fixed upstream in dfdd52e2e806"
|
||||
commit_url = "https://github.com/sandy98/node-simple-router/commit/dfdd52e2e80607af433097d940b3834fd96df488"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "pdf-image-1-0-5"
|
||||
host = "github"
|
||||
repo = "roest01/node-pdf-image"
|
||||
parent = "d8c0dcadd93985dbefe80b84060f5f572bfbb6ff"
|
||||
commit = "54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-3757"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "pdf-image"
|
||||
sink_location = "index.js:43:7"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:43:7 fixed upstream in 54679496a897"
|
||||
commit_url = "https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "pidusage-1-0-0"
|
||||
host = "github"
|
||||
repo = "soyuka/pidusage"
|
||||
parent = "e3660d8a8e5e61afad9b02af67356a1e239d6bde"
|
||||
commit = "b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
path = "lib/stats.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "lib/stats.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2017-16034"
|
||||
year = 2017
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "pidusage"
|
||||
sink_location = "lib/stats.js:108:5"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink lib/stats.js:108:5 fixed upstream in b70eca15f7ca"
|
||||
commit_url = "https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "portprocesses-1-0-4"
|
||||
host = "github"
|
||||
repo = "rrainn/PortProcesses"
|
||||
parent = "fffceb09aff7180afbd0bd172e820404b33c8299"
|
||||
commit = "86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2021-23348"
|
||||
year = 2021
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "portprocesses"
|
||||
sink_location = "exec.js:5:3"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink exec.js:5:3 fixed upstream in 86811216c9b9"
|
||||
commit_url = "https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "serve-here-js-1-1-0"
|
||||
host = "github"
|
||||
repo = "ChristoPy/serve-here.js"
|
||||
parent = "ad077637bf7a9fe0dee3262f011aed19a45ce92c"
|
||||
commit = "cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
path = "source/response.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "source/response.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2019-5444"
|
||||
year = 2019
|
||||
cwe = "CWE-22"
|
||||
class = "path traversal"
|
||||
mechanism = "path_join_user_input"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "serve-here.js"
|
||||
sink_location = "source/server.js:27:15"
|
||||
secbench_class = "path-traversal"
|
||||
evidence = "SecBench.js path-traversal sink source/server.js:27:15 fixed upstream in cefb51d03290"
|
||||
commit_url = "https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "static-eval-1-1-1"
|
||||
host = "github"
|
||||
repo = "browserify/static-eval"
|
||||
parent = "5bba7905b0e797460b8f6c2e38ff6869146faab3"
|
||||
commit = "32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = ""
|
||||
year = 2019
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "static-eval"
|
||||
sink_location = "index.js:118:20"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink index.js:118:20 fixed upstream in 32f8efd07262"
|
||||
commit_url = "https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "thenify-3-3-0"
|
||||
host = "github"
|
||||
repo = "thenables/thenify"
|
||||
parent = "aa21cfb64f47238c764d258d0faf7366a8487e36"
|
||||
commit = "0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2020-7677"
|
||||
year = 2020
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "thenify"
|
||||
sink_location = "index.js:17:10"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink index.js:17:10 fixed upstream in 0d94a24eb933"
|
||||
commit_url = "https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a"
|
||||
split = "holdout"
|
||||
|
||||
[[recipe]]
|
||||
name = "underscore-1-13-0-0"
|
||||
host = "github"
|
||||
repo = "jashkenas/underscore"
|
||||
parent = "ef646ccbbbd971e82719c83fc69f56a5585b3a01"
|
||||
commit = "4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
path = "modules/template.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "modules/template.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2021-23358"
|
||||
year = 2021
|
||||
cwe = "CWE-94"
|
||||
class = "code injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "underscore"
|
||||
sink_location = "modules/template.js:71:14"
|
||||
secbench_class = "code-injection"
|
||||
evidence = "SecBench.js code-injection sink modules/template.js:71:14 fixed upstream in 4c73526d4383"
|
||||
commit_url = "https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66"
|
||||
split = "train"
|
||||
|
||||
[[recipe]]
|
||||
name = "whereis-0-4-0"
|
||||
host = "github"
|
||||
repo = "vvo/node-whereis"
|
||||
parent = "b8b642b1163baa37f15ed49b4064dcbdb6e1876c"
|
||||
commit = "0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
path = "index.js"
|
||||
mode = "hunk"
|
||||
language = "javascript"
|
||||
relpath = "index.js"
|
||||
license = "MIT"
|
||||
cve = "CVE-2018-3772"
|
||||
year = 2018
|
||||
cwe = "CWE-78"
|
||||
class = "command injection"
|
||||
mechanism = "source_reaches_sink"
|
||||
provenance = "human"
|
||||
origin = "secbench.js"
|
||||
project = "whereis"
|
||||
sink_location = "index.js:4:6"
|
||||
secbench_class = "command-injection"
|
||||
evidence = "SecBench.js command-injection sink index.js:4:6 fixed upstream in 0f64e3780235"
|
||||
commit_url = "https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b"
|
||||
split = "holdout"
|
||||
@@ -0,0 +1,29 @@
|
||||
// Provenance: ChristoPy/serve-here.js (fixed).
|
||||
// repo: ChristoPy/serve-here.js
|
||||
// commit: cefb51d03290b6a88dd13143ab2de31b8cf57c39
|
||||
// parent: ad077637bf7a9fe0dee3262f011aed19a45ce92c
|
||||
// commit_url: https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39
|
||||
// cve: CVE-2019-5444
|
||||
// license: MIT
|
||||
// function: ConfigureFilePath
|
||||
// relpath: source/response.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 14
|
||||
|
||||
module.exports.ConfigureFilePath = (Options, FilePath) => {
|
||||
|
||||
const Slash = FilePath.split ("")[FilePath.split ("").length - 1] === "/";
|
||||
|
||||
if (FilePath === "/") {
|
||||
return `${Options.RootFolder}/${Options.IndexFile}`;
|
||||
} else {
|
||||
const IsMalicious = HasMaliciousPath(Options, FilePath);
|
||||
|
||||
if (IsMalicious) {
|
||||
return null;
|
||||
} else {
|
||||
return (Slash ? `${Options.RootFolder}${FilePath.slice (0, -1)}` : `${Options.RootFolder}${FilePath}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Provenance: ChristoPy/serve-here.js (vuln).
|
||||
// repo: ChristoPy/serve-here.js
|
||||
// commit: ad077637bf7a9fe0dee3262f011aed19a45ce92c
|
||||
// parent: ad077637bf7a9fe0dee3262f011aed19a45ce92c
|
||||
// commit_url: https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39
|
||||
// cve: CVE-2019-5444
|
||||
// license: MIT
|
||||
// function: ConfigureFilePath
|
||||
// relpath: source/response.js
|
||||
// provenance: human
|
||||
// mechanism: path_join_user_input
|
||||
// upstream_start: 5
|
||||
|
||||
module.exports.ConfigureFilePath = (Options, FilePath) => {
|
||||
|
||||
const Slash = FilePath.split ("")[FilePath.split ("").length - 1] === "/";
|
||||
|
||||
switch (FilePath) {
|
||||
|
||||
case "/": return `${Options.RootFolder}/${Options.IndexFile}`;
|
||||
default: return (Slash ? `${Options.RootFolder}${FilePath.slice (0, -1)}` : `${Options.RootFolder}${FilePath}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
// Provenance: browserify/static-eval (fixed).
|
||||
// repo: browserify/static-eval
|
||||
// commit: 32f8efd072625e267aa7237d2daff35738c50d2a
|
||||
// parent: 5bba7905b0e797460b8f6c2e38ff6869146faab3
|
||||
// commit_url: https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: walk
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 3
|
||||
|
||||
module.exports = function (ast, vars) {
|
||||
if (!vars) vars = {};
|
||||
var FAIL = {};
|
||||
|
||||
var result = (function walk (node, scopeVars) {
|
||||
if (node.type === 'Literal') {
|
||||
return node.value;
|
||||
}
|
||||
else if (node.type === 'UnaryExpression'){
|
||||
var val = walk(node.argument)
|
||||
if (node.operator === '+') return +val
|
||||
if (node.operator === '-') return -val
|
||||
if (node.operator === '~') return ~val
|
||||
if (node.operator === '!') return !val
|
||||
return FAIL
|
||||
}
|
||||
else if (node.type === 'ArrayExpression') {
|
||||
var xs = [];
|
||||
for (var i = 0, l = node.elements.length; i < l; i++) {
|
||||
var x = walk(node.elements[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
xs.push(x);
|
||||
}
|
||||
return xs;
|
||||
}
|
||||
else if (node.type === 'ObjectExpression') {
|
||||
var obj = {};
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
var value = prop.value === null
|
||||
? prop.value
|
||||
: walk(prop.value)
|
||||
;
|
||||
if (value === FAIL) return FAIL;
|
||||
obj[prop.key.value || prop.key.name] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
else if (node.type === 'BinaryExpression' ||
|
||||
node.type === 'LogicalExpression') {
|
||||
var l = walk(node.left);
|
||||
if (l === FAIL) return FAIL;
|
||||
var r = walk(node.right);
|
||||
if (r === FAIL) return FAIL;
|
||||
|
||||
var op = node.operator;
|
||||
if (op === '==') return l == r;
|
||||
if (op === '===') return l === r;
|
||||
if (op === '!=') return l != r;
|
||||
if (op === '!==') return l !== r;
|
||||
if (op === '+') return l + r;
|
||||
if (op === '-') return l - r;
|
||||
if (op === '*') return l * r;
|
||||
if (op === '/') return l / r;
|
||||
if (op === '%') return l % r;
|
||||
if (op === '<') return l < r;
|
||||
if (op === '<=') return l <= r;
|
||||
if (op === '>') return l > r;
|
||||
if (op === '>=') return l >= r;
|
||||
if (op === '|') return l | r;
|
||||
if (op === '&') return l & r;
|
||||
if (op === '^') return l ^ r;
|
||||
if (op === '&&') return l && r;
|
||||
if (op === '||') return l || r;
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
else if (node.type === 'Identifier') {
|
||||
if ({}.hasOwnProperty.call(vars, node.name)) {
|
||||
return vars[node.name];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'ThisExpression') {
|
||||
if ({}.hasOwnProperty.call(vars, 'this')) {
|
||||
return vars['this'];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'CallExpression') {
|
||||
var callee = walk(node.callee);
|
||||
if (callee === FAIL) return FAIL;
|
||||
if (typeof callee !== 'function') return FAIL;
|
||||
|
||||
var ctx = node.callee.object ? walk(node.callee.object) : FAIL;
|
||||
if (ctx === FAIL) ctx = null;
|
||||
|
||||
var args = [];
|
||||
for (var i = 0, l = node.arguments.length; i < l; i++) {
|
||||
var x = walk(node.arguments[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
args.push(x);
|
||||
}
|
||||
return callee.apply(ctx, args);
|
||||
}
|
||||
else if (node.type === 'MemberExpression') {
|
||||
var obj = walk(node.object);
|
||||
// do not allow access to methods on Function
|
||||
if((obj === FAIL) || (typeof obj == 'function')){
|
||||
return FAIL;
|
||||
}
|
||||
if (node.property.type === 'Identifier') {
|
||||
return obj[node.property.name];
|
||||
}
|
||||
var prop = walk(node.property);
|
||||
if (prop === FAIL) return FAIL;
|
||||
return obj[prop];
|
||||
}
|
||||
else if (node.type === 'ConditionalExpression') {
|
||||
var val = walk(node.test)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val ? walk(node.consequent) : walk(node.alternate)
|
||||
}
|
||||
else if (node.type === 'ExpressionStatement') {
|
||||
var val = walk(node.expression)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val;
|
||||
}
|
||||
else if (node.type === 'ReturnStatement') {
|
||||
return walk(node.argument)
|
||||
}
|
||||
else if (node.type === 'FunctionExpression') {
|
||||
|
||||
var bodies = node.body.body;
|
||||
|
||||
// Create a "scope" for our arguments
|
||||
var oldVars = {};
|
||||
Object.keys(vars).forEach(function(element){
|
||||
oldVars[element] = vars[element];
|
||||
})
|
||||
|
||||
node.params.forEach(function(key) {
|
||||
if(key.type == 'Identifier'){
|
||||
vars[key.name] = null;
|
||||
}
|
||||
else return FAIL;
|
||||
});
|
||||
for(var i in bodies){
|
||||
if(walk(bodies[i]) === FAIL){
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
// restore the vars and scope after we walk
|
||||
vars = oldVars;
|
||||
|
||||
var keys = Object.keys(vars);
|
||||
var vals = keys.map(function(key) {
|
||||
return vars[key];
|
||||
});
|
||||
return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals);
|
||||
}
|
||||
else if (node.type === 'TemplateLiteral') {
|
||||
var str = '';
|
||||
for (var i = 0; i < node.expressions.length; i++) {
|
||||
str += walk(node.quasis[i]);
|
||||
str += walk(node.expressions[i]);
|
||||
}
|
||||
str += walk(node.quasis[i]);
|
||||
return str;
|
||||
}
|
||||
else if (node.type === 'TaggedTemplateExpression') {
|
||||
var tag = walk(node.tag);
|
||||
var quasi = node.quasi;
|
||||
var strings = quasi.quasis.map(walk);
|
||||
var values = quasi.expressions.map(walk);
|
||||
return tag.apply(null, [strings].concat(values));
|
||||
}
|
||||
else if (node.type === 'TemplateElement') {
|
||||
return node.value.cooked;
|
||||
}
|
||||
else return FAIL;
|
||||
})(ast);
|
||||
|
||||
return result === FAIL ? undefined : result;
|
||||
};
|
||||
@@ -0,0 +1,187 @@
|
||||
// Provenance: browserify/static-eval (vuln).
|
||||
// repo: browserify/static-eval
|
||||
// commit: 5bba7905b0e797460b8f6c2e38ff6869146faab3
|
||||
// parent: 5bba7905b0e797460b8f6c2e38ff6869146faab3
|
||||
// commit_url: https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a
|
||||
// cve:
|
||||
// license: MIT
|
||||
// function: walk
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 3
|
||||
|
||||
module.exports = function (ast, vars) {
|
||||
if (!vars) vars = {};
|
||||
var FAIL = {};
|
||||
|
||||
var result = (function walk (node, scopeVars) {
|
||||
if (node.type === 'Literal') {
|
||||
return node.value;
|
||||
}
|
||||
else if (node.type === 'UnaryExpression'){
|
||||
var val = walk(node.argument)
|
||||
if (node.operator === '+') return +val
|
||||
if (node.operator === '-') return -val
|
||||
if (node.operator === '~') return ~val
|
||||
if (node.operator === '!') return !val
|
||||
return FAIL
|
||||
}
|
||||
else if (node.type === 'ArrayExpression') {
|
||||
var xs = [];
|
||||
for (var i = 0, l = node.elements.length; i < l; i++) {
|
||||
var x = walk(node.elements[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
xs.push(x);
|
||||
}
|
||||
return xs;
|
||||
}
|
||||
else if (node.type === 'ObjectExpression') {
|
||||
var obj = {};
|
||||
for (var i = 0; i < node.properties.length; i++) {
|
||||
var prop = node.properties[i];
|
||||
var value = prop.value === null
|
||||
? prop.value
|
||||
: walk(prop.value)
|
||||
;
|
||||
if (value === FAIL) return FAIL;
|
||||
obj[prop.key.value || prop.key.name] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
else if (node.type === 'BinaryExpression' ||
|
||||
node.type === 'LogicalExpression') {
|
||||
var l = walk(node.left);
|
||||
if (l === FAIL) return FAIL;
|
||||
var r = walk(node.right);
|
||||
if (r === FAIL) return FAIL;
|
||||
|
||||
var op = node.operator;
|
||||
if (op === '==') return l == r;
|
||||
if (op === '===') return l === r;
|
||||
if (op === '!=') return l != r;
|
||||
if (op === '!==') return l !== r;
|
||||
if (op === '+') return l + r;
|
||||
if (op === '-') return l - r;
|
||||
if (op === '*') return l * r;
|
||||
if (op === '/') return l / r;
|
||||
if (op === '%') return l % r;
|
||||
if (op === '<') return l < r;
|
||||
if (op === '<=') return l <= r;
|
||||
if (op === '>') return l > r;
|
||||
if (op === '>=') return l >= r;
|
||||
if (op === '|') return l | r;
|
||||
if (op === '&') return l & r;
|
||||
if (op === '^') return l ^ r;
|
||||
if (op === '&&') return l && r;
|
||||
if (op === '||') return l || r;
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
else if (node.type === 'Identifier') {
|
||||
if ({}.hasOwnProperty.call(vars, node.name)) {
|
||||
return vars[node.name];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'ThisExpression') {
|
||||
if ({}.hasOwnProperty.call(vars, 'this')) {
|
||||
return vars['this'];
|
||||
}
|
||||
else return FAIL;
|
||||
}
|
||||
else if (node.type === 'CallExpression') {
|
||||
var callee = walk(node.callee);
|
||||
if (callee === FAIL) return FAIL;
|
||||
if (typeof callee !== 'function') return FAIL;
|
||||
|
||||
var ctx = node.callee.object ? walk(node.callee.object) : FAIL;
|
||||
if (ctx === FAIL) ctx = null;
|
||||
|
||||
var args = [];
|
||||
for (var i = 0, l = node.arguments.length; i < l; i++) {
|
||||
var x = walk(node.arguments[i]);
|
||||
if (x === FAIL) return FAIL;
|
||||
args.push(x);
|
||||
}
|
||||
return callee.apply(ctx, args);
|
||||
}
|
||||
else if (node.type === 'MemberExpression') {
|
||||
var obj = walk(node.object);
|
||||
// do not allow access to methods on Function
|
||||
if((obj === FAIL) || (typeof obj == 'function')){
|
||||
return FAIL;
|
||||
}
|
||||
if (node.property.type === 'Identifier') {
|
||||
return obj[node.property.name];
|
||||
}
|
||||
var prop = walk(node.property);
|
||||
if (prop === FAIL) return FAIL;
|
||||
return obj[prop];
|
||||
}
|
||||
else if (node.type === 'ConditionalExpression') {
|
||||
var val = walk(node.test)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val ? walk(node.consequent) : walk(node.alternate)
|
||||
}
|
||||
else if (node.type === 'ExpressionStatement') {
|
||||
var val = walk(node.expression)
|
||||
if (val === FAIL) return FAIL;
|
||||
return val;
|
||||
}
|
||||
else if (node.type === 'ReturnStatement') {
|
||||
return walk(node.argument)
|
||||
}
|
||||
else if (node.type === 'FunctionExpression') {
|
||||
|
||||
var bodies = node.body.body;
|
||||
|
||||
// Create a "scope" for our arguments
|
||||
var oldVars = {};
|
||||
Object.keys(vars).forEach(function(element){
|
||||
oldVars[element] = vars[element];
|
||||
})
|
||||
|
||||
node.params.forEach(function(key) {
|
||||
if(key.type == 'Identifier'){
|
||||
vars[key.name] = null;
|
||||
}
|
||||
});
|
||||
for(var i in bodies){
|
||||
if(walk(bodies[i]) === FAIL){
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
// restore the vars and scope after we walk
|
||||
vars = oldVars;
|
||||
|
||||
var keys = Object.keys(vars);
|
||||
var vals = keys.map(function(key) {
|
||||
return vars[key];
|
||||
});
|
||||
return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals);
|
||||
}
|
||||
else if (node.type === 'TemplateLiteral') {
|
||||
var str = '';
|
||||
for (var i = 0; i < node.expressions.length; i++) {
|
||||
str += walk(node.quasis[i]);
|
||||
str += walk(node.expressions[i]);
|
||||
}
|
||||
str += walk(node.quasis[i]);
|
||||
return str;
|
||||
}
|
||||
else if (node.type === 'TaggedTemplateExpression') {
|
||||
var tag = walk(node.tag);
|
||||
var quasi = node.quasi;
|
||||
var strings = quasi.quasis.map(walk);
|
||||
var values = quasi.expressions.map(walk);
|
||||
return tag.apply(null, [strings].concat(values));
|
||||
}
|
||||
else if (node.type === 'TemplateElement') {
|
||||
return node.value.cooked;
|
||||
}
|
||||
else return FAIL;
|
||||
})(ast);
|
||||
|
||||
return result === FAIL ? undefined : result;
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: thenables/thenify (fixed).
|
||||
// repo: thenables/thenify
|
||||
// commit: 0d94a24eb933bc835d568f3009f4d269c4c4c17a
|
||||
// parent: aa21cfb64f47238c764d258d0faf7366a8487e36
|
||||
// commit_url: https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a
|
||||
// cve: CVE-2020-7677
|
||||
// license: MIT
|
||||
// function: thenify
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 2
|
||||
|
||||
var Promise = require('any-promise')
|
||||
var assert = require('assert')
|
||||
|
||||
module.exports = thenify
|
||||
|
||||
/**
|
||||
* Turn async functions into promises
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function thenify(fn, options) {
|
||||
assert(typeof fn === 'function')
|
||||
return createWrapper(fn, options)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Provenance: thenables/thenify (vuln).
|
||||
// repo: thenables/thenify
|
||||
// commit: aa21cfb64f47238c764d258d0faf7366a8487e36
|
||||
// parent: aa21cfb64f47238c764d258d0faf7366a8487e36
|
||||
// commit_url: https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a
|
||||
// cve: CVE-2020-7677
|
||||
// license: MIT
|
||||
// function: thenify
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 2
|
||||
|
||||
var Promise = require('any-promise')
|
||||
var assert = require('assert')
|
||||
|
||||
module.exports = thenify
|
||||
|
||||
/**
|
||||
* Turn async functions into promises
|
||||
*
|
||||
* @param {Function} $$__fn__$$
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function thenify($$__fn__$$, options) {
|
||||
assert(typeof $$__fn__$$ === 'function')
|
||||
return eval(createWrapper($$__fn__$$.name, options))
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{"class": "path traversal", "commit": "d171a771a92e4685b24fb77cb894a7b7b8024c5c", "commit_url": "https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9", "cve": "", "cwe": "CWE-22", "file": "angular-http-server-1-0-0/vuln.js", "function": "requestListener", "id": "angular-http-server-1-0-0:vuln", "label": "vuln", "license": "Apache-2.0", "mechanism": "path_join_user_input", "pair": "angular-http-server-1-0-0", "project": "angular-http-server", "provenance": "human", "relpath": "angular-http-server.js", "repo": "simonh1000/angular-http-server", "split": "train", "year": 2018}
|
||||
{"class": "path traversal", "commit": "8bafc9577161469f5dea01e0b98ea9c525d063e9", "commit_url": "https://github.com/simonh1000/angular-http-server/commit/8bafc9577161469f5dea01e0b98ea9c525d063e9", "cve": "", "cwe": "CWE-22", "file": "angular-http-server-1-0-0/fixed.js", "function": "requestListener", "id": "angular-http-server-1-0-0:fixed", "label": "fixed", "license": "Apache-2.0", "mechanism": "path_join_user_input", "pair": "angular-http-server-1-0-0", "project": "angular-http-server", "provenance": "human", "relpath": "angular-http-server.js", "repo": "simonh1000/angular-http-server", "split": "train", "year": 2018}
|
||||
{"class": "command injection", "commit": "8d28fe8a9a49e5ff3f61e239293b5646528e2915", "commit_url": "https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063", "cve": "CVE-2018-16462", "cwe": "CWE-78", "file": "apex-publish-static-files-2-0-0/vuln.js", "function": "publish", "id": "apex-publish-static-files-2-0-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "apex-publish-static-files-2-0-0", "project": "apex-publish-static-files", "provenance": "human", "relpath": "index.js", "repo": "vincentmorneau/apex-publish-static-files", "split": "holdout", "year": 2018}
|
||||
{"class": "command injection", "commit": "2209af8f2b65c24aa55ab757e0e05b958c16f063", "commit_url": "https://github.com/vincentmorneau/apex-publish-static-files/commit/2209af8f2b65c24aa55ab757e0e05b958c16f063", "cve": "CVE-2018-16462", "cwe": "CWE-78", "file": "apex-publish-static-files-2-0-0/fixed.js", "function": "publish", "id": "apex-publish-static-files-2-0-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "apex-publish-static-files-2-0-0", "project": "apex-publish-static-files", "provenance": "human", "relpath": "index.js", "repo": "vincentmorneau/apex-publish-static-files", "split": "holdout", "year": 2018}
|
||||
{"class": "command injection", "commit": "fcea252e52b6078eff6caf5531bd32c53fccb59f", "commit_url": "https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6", "cve": "CVE-2020-7730", "cwe": "CWE-78", "file": "bestzip-2-1-6/vuln.js", "function": "nativeZip", "id": "bestzip-2-1-6:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "bestzip-2-1-6", "project": "bestzip", "provenance": "human", "relpath": "lib/bestzip.js", "repo": "nfriedly/node-bestzip", "split": "holdout", "year": 2020}
|
||||
{"class": "command injection", "commit": "45d4a901478c6a8f396c8b959dd6cf8fd3f955b6", "commit_url": "https://github.com/nfriedly/node-bestzip/commit/45d4a901478c6a8f396c8b959dd6cf8fd3f955b6", "cve": "CVE-2020-7730", "cwe": "CWE-78", "file": "bestzip-2-1-6/fixed.js", "function": "nativeZip", "id": "bestzip-2-1-6:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "bestzip-2-1-6", "project": "bestzip", "provenance": "human", "relpath": "lib/bestzip.js", "repo": "nfriedly/node-bestzip", "split": "holdout", "year": 2020}
|
||||
{"class": "command injection", "commit": "d474da7b89c0d3397cd681e79c7bcc592bff144b", "commit_url": "https://github.com/kylefarris/clamscan/commit/5f557c970817fe8c578ec3f7ad3bcbcef4cf5538", "cve": "CVE-2020-7613", "cwe": "CWE-78", "file": "clamscan-1-2-0/vuln.js", "function": "local_scan", "id": "clamscan-1-2-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "clamscan-1-2-0", "project": "clamscan", "provenance": "human", "relpath": "index.js", "repo": "kylefarris/clamscan", "split": "train", "year": 2020}
|
||||
{"class": "command injection", "commit": "5f557c970817fe8c578ec3f7ad3bcbcef4cf5538", "commit_url": "https://github.com/kylefarris/clamscan/commit/5f557c970817fe8c578ec3f7ad3bcbcef4cf5538", "cve": "CVE-2020-7613", "cwe": "CWE-78", "file": "clamscan-1-2-0/fixed.js", "function": "local_scan", "id": "clamscan-1-2-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "clamscan-1-2-0", "project": "clamscan", "provenance": "human", "relpath": "index.js", "repo": "kylefarris/clamscan", "split": "train", "year": 2020}
|
||||
{"class": "command injection", "commit": "53c505506553c83861d1bd67823d6a382d3a5a43", "commit_url": "https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3", "cve": "CVE-2020-7631", "cwe": "CWE-78", "file": "diskusage-ng-0-2-6/vuln.js", "function": "diskusage", "id": "diskusage-ng-0-2-6:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "diskusage-ng-0-2-6", "project": "diskusage-ng", "provenance": "human", "relpath": "lib/posix.js", "repo": "iximiuz/node-diskusage-ng", "split": "holdout", "year": 2020}
|
||||
{"class": "command injection", "commit": "48e7e093486b528f0c81ec699573e0e4a431b8d3", "commit_url": "https://github.com/iximiuz/node-diskusage-ng/commit/48e7e093486b528f0c81ec699573e0e4a431b8d3", "cve": "CVE-2020-7631", "cwe": "CWE-78", "file": "diskusage-ng-0-2-6/fixed.js", "function": "diskusage", "id": "diskusage-ng-0-2-6:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "diskusage-ng-0-2-6", "project": "diskusage-ng", "provenance": "human", "relpath": "lib/posix.js", "repo": "iximiuz/node-diskusage-ng", "split": "holdout", "year": 2020}
|
||||
{"class": "command injection", "commit": "b748fe77a87749d95876028eda8e759109be4c73", "commit_url": "https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d", "cve": "CVE-2014-9682", "cwe": "CWE-78", "file": "dns-sync-0-1-0/vuln.js", "function": "resolve", "id": "dns-sync-0-1-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "dns-sync-0-1-0", "project": "dns-sync", "provenance": "human", "relpath": "lib/dns-sync.js", "repo": "skoranga/node-dns-sync", "split": "train", "year": 2014}
|
||||
{"class": "command injection", "commit": "d9abaae384b198db1095735ad9c1c73d7b890a0d", "commit_url": "https://github.com/skoranga/node-dns-sync/commit/d9abaae384b198db1095735ad9c1c73d7b890a0d", "cve": "CVE-2014-9682", "cwe": "CWE-78", "file": "dns-sync-0-1-0/fixed.js", "function": "resolve", "id": "dns-sync-0-1-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "dns-sync-0-1-0", "project": "dns-sync", "provenance": "human", "relpath": "lib/dns-sync.js", "repo": "skoranga/node-dns-sync", "split": "train", "year": 2014}
|
||||
{"class": "path traversal", "commit": "7e69a5539236386e747fb240ae87ea65ed64bb2c", "commit_url": "https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19", "cve": "CVE-2018-3715", "cwe": "CWE-22", "file": "glance-3-0-0/vuln.js", "function": "Glance$serveRequest", "id": "glance-3-0-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "path_join_user_input", "pair": "glance-3-0-0", "project": "glance", "provenance": "human", "relpath": "index.js", "repo": "jarofghosts/glance", "split": "train", "year": 2018}
|
||||
{"class": "path traversal", "commit": "8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19", "commit_url": "https://github.com/jarofghosts/glance/commit/8cfd88e44ebd3f07e3a2eaf376a3e758b6c4ca19", "cve": "CVE-2018-3715", "cwe": "CWE-22", "file": "glance-3-0-0/fixed.js", "function": "Glance$serveRequest", "id": "glance-3-0-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "path_join_user_input", "pair": "glance-3-0-0", "project": "glance", "provenance": "human", "relpath": "index.js", "repo": "jarofghosts/glance", "split": "train", "year": 2018}
|
||||
{"class": "command injection", "commit": "944136096f44ff4ffd4ba0bcef30970ca4702fce", "commit_url": "https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e", "cve": "CVE-2020-6836", "cwe": "CWE-78", "file": "hot-formula-parser-3-0-0/vuln.js", "function": "performAction", "id": "hot-formula-parser-3-0-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "hot-formula-parser-3-0-0", "project": "hot-formula-parser", "provenance": "human", "relpath": "src/grammar-parser/grammar-parser.js", "repo": "handsontable/formula-parser", "split": "train", "year": 2019}
|
||||
{"class": "command injection", "commit": "396b089738d4bf30eb570a4fe6a188affa95cd5e", "commit_url": "https://github.com/handsontable/formula-parser/commit/396b089738d4bf30eb570a4fe6a188affa95cd5e", "cve": "CVE-2020-6836", "cwe": "CWE-78", "file": "hot-formula-parser-3-0-0/fixed.js", "function": "performAction", "id": "hot-formula-parser-3-0-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "hot-formula-parser-3-0-0", "project": "hot-formula-parser", "provenance": "human", "relpath": "src/grammar-parser/grammar-parser.js", "repo": "handsontable/formula-parser", "split": "train", "year": 2019}
|
||||
{"class": "command injection", "commit": "49b72239b144ab7ffdf673b62e18bfd0760948f6", "commit_url": "https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8", "cve": "CVE-2018-16461", "cwe": "CWE-78", "file": "libnmap-0-4-11/vuln.js", "function": "block", "id": "libnmap-0-4-11:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "libnmap-0-4-11", "project": "libnmap", "provenance": "human", "relpath": "lib/classes/tools.js", "repo": "jas-/node-libnmap", "split": "train", "year": 2018}
|
||||
{"class": "command injection", "commit": "c235b24b0342e12a5dbf502f89daabe95883b6c8", "commit_url": "https://github.com/jas-/node-libnmap/commit/c235b24b0342e12a5dbf502f89daabe95883b6c8", "cve": "CVE-2018-16461", "cwe": "CWE-78", "file": "libnmap-0-4-11/fixed.js", "function": "block", "id": "libnmap-0-4-11:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "libnmap-0-4-11", "project": "libnmap", "provenance": "human", "relpath": "lib/classes/tools.js", "repo": "jas-/node-libnmap", "split": "train", "year": 2018}
|
||||
{"class": "command injection", "commit": "d8c0dcadd93985dbefe80b84060f5f572bfbb6ff", "commit_url": "https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83", "cve": "CVE-2018-3757", "cwe": "CWE-78", "file": "pdf-image-1-0-5/vuln.js", "function": "getInfo", "id": "pdf-image-1-0-5:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "pdf-image-1-0-5", "project": "pdf-image", "provenance": "human", "relpath": "index.js", "repo": "roest01/node-pdf-image", "split": "train", "year": 2018}
|
||||
{"class": "command injection", "commit": "54679496a89738443917608c2bbe2f6e5dd20e83", "commit_url": "https://github.com/roest01/node-pdf-image/commit/54679496a89738443917608c2bbe2f6e5dd20e83", "cve": "CVE-2018-3757", "cwe": "CWE-78", "file": "pdf-image-1-0-5/fixed.js", "function": "getInfo", "id": "pdf-image-1-0-5:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "pdf-image-1-0-5", "project": "pdf-image", "provenance": "human", "relpath": "index.js", "repo": "roest01/node-pdf-image", "split": "train", "year": 2018}
|
||||
{"class": "command injection", "commit": "e3660d8a8e5e61afad9b02af67356a1e239d6bde", "commit_url": "https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d", "cve": "CVE-2017-16034", "cwe": "CWE-78", "file": "pidusage-1-0-0/vuln.js", "function": "ps", "id": "pidusage-1-0-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "pidusage-1-0-0", "project": "pidusage", "provenance": "human", "relpath": "lib/stats.js", "repo": "soyuka/pidusage", "split": "holdout", "year": 2017}
|
||||
{"class": "command injection", "commit": "b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d", "commit_url": "https://github.com/soyuka/pidusage/commit/b70eca15f7ca7f1b82a15f8a5d4bb48737f5a89d", "cve": "CVE-2017-16034", "cwe": "CWE-78", "file": "pidusage-1-0-0/fixed.js", "function": "ps", "id": "pidusage-1-0-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "pidusage-1-0-0", "project": "pidusage", "provenance": "human", "relpath": "lib/stats.js", "repo": "soyuka/pidusage", "split": "holdout", "year": 2017}
|
||||
{"class": "command injection", "commit": "fffceb09aff7180afbd0bd172e820404b33c8299", "commit_url": "https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1", "cve": "CVE-2021-23348", "cwe": "CWE-78", "file": "portprocesses-1-0-4/vuln.js", "function": "listProcessesOnPort", "id": "portprocesses-1-0-4:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "portprocesses-1-0-4", "project": "portprocesses", "provenance": "human", "relpath": "index.js", "repo": "rrainn/PortProcesses", "split": "train", "year": 2021}
|
||||
{"class": "command injection", "commit": "86811216c9b97b01b5722f879f8c88a7aa4214e1", "commit_url": "https://github.com/rrainn/PortProcesses/commit/86811216c9b97b01b5722f879f8c88a7aa4214e1", "cve": "CVE-2021-23348", "cwe": "CWE-78", "file": "portprocesses-1-0-4/fixed.js", "function": "listProcessesOnPort", "id": "portprocesses-1-0-4:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "portprocesses-1-0-4", "project": "portprocesses", "provenance": "human", "relpath": "index.js", "repo": "rrainn/PortProcesses", "split": "train", "year": 2021}
|
||||
{"class": "path traversal", "commit": "ad077637bf7a9fe0dee3262f011aed19a45ce92c", "commit_url": "https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39", "cve": "CVE-2019-5444", "cwe": "CWE-22", "file": "serve-here-js-1-1-0/vuln.js", "function": "ConfigureFilePath", "id": "serve-here-js-1-1-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "path_join_user_input", "pair": "serve-here-js-1-1-0", "project": "serve-here.js", "provenance": "human", "relpath": "source/response.js", "repo": "ChristoPy/serve-here.js", "split": "holdout", "year": 2019}
|
||||
{"class": "path traversal", "commit": "cefb51d03290b6a88dd13143ab2de31b8cf57c39", "commit_url": "https://github.com/ChristoPy/serve-here.js/commit/cefb51d03290b6a88dd13143ab2de31b8cf57c39", "cve": "CVE-2019-5444", "cwe": "CWE-22", "file": "serve-here-js-1-1-0/fixed.js", "function": "ConfigureFilePath", "id": "serve-here-js-1-1-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "path_join_user_input", "pair": "serve-here-js-1-1-0", "project": "serve-here.js", "provenance": "human", "relpath": "source/response.js", "repo": "ChristoPy/serve-here.js", "split": "holdout", "year": 2019}
|
||||
{"class": "code injection", "commit": "5bba7905b0e797460b8f6c2e38ff6869146faab3", "commit_url": "https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a", "cve": "", "cwe": "CWE-94", "file": "static-eval-1-1-1/vuln.js", "function": "walk", "id": "static-eval-1-1-1:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "static-eval-1-1-1", "project": "static-eval", "provenance": "human", "relpath": "index.js", "repo": "browserify/static-eval", "split": "train", "year": 2019}
|
||||
{"class": "code injection", "commit": "32f8efd072625e267aa7237d2daff35738c50d2a", "commit_url": "https://github.com/browserify/static-eval/commit/32f8efd072625e267aa7237d2daff35738c50d2a", "cve": "", "cwe": "CWE-94", "file": "static-eval-1-1-1/fixed.js", "function": "walk", "id": "static-eval-1-1-1:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "static-eval-1-1-1", "project": "static-eval", "provenance": "human", "relpath": "index.js", "repo": "browserify/static-eval", "split": "train", "year": 2019}
|
||||
{"class": "code injection", "commit": "aa21cfb64f47238c764d258d0faf7366a8487e36", "commit_url": "https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a", "cve": "CVE-2020-7677", "cwe": "CWE-94", "file": "thenify-3-3-0/vuln.js", "function": "thenify", "id": "thenify-3-3-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "thenify-3-3-0", "project": "thenify", "provenance": "human", "relpath": "index.js", "repo": "thenables/thenify", "split": "holdout", "year": 2020}
|
||||
{"class": "code injection", "commit": "0d94a24eb933bc835d568f3009f4d269c4c4c17a", "commit_url": "https://github.com/thenables/thenify/commit/0d94a24eb933bc835d568f3009f4d269c4c4c17a", "cve": "CVE-2020-7677", "cwe": "CWE-94", "file": "thenify-3-3-0/fixed.js", "function": "thenify", "id": "thenify-3-3-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "thenify-3-3-0", "project": "thenify", "provenance": "human", "relpath": "index.js", "repo": "thenables/thenify", "split": "holdout", "year": 2020}
|
||||
{"class": "code injection", "commit": "ef646ccbbbd971e82719c83fc69f56a5585b3a01", "commit_url": "https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66", "cve": "CVE-2021-23358", "cwe": "CWE-94", "file": "underscore-1-13-0-0/vuln.js", "function": "template", "id": "underscore-1-13-0-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "underscore-1-13-0-0", "project": "underscore", "provenance": "human", "relpath": "modules/template.js", "repo": "jashkenas/underscore", "split": "train", "year": 2021}
|
||||
{"class": "code injection", "commit": "4c73526d43838ad6ab43a6134728776632adeb66", "commit_url": "https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66", "cve": "CVE-2021-23358", "cwe": "CWE-94", "file": "underscore-1-13-0-0/fixed.js", "function": "template", "id": "underscore-1-13-0-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "underscore-1-13-0-0", "project": "underscore", "provenance": "human", "relpath": "modules/template.js", "repo": "jashkenas/underscore", "split": "train", "year": 2021}
|
||||
{"class": "command injection", "commit": "b8b642b1163baa37f15ed49b4064dcbdb6e1876c", "commit_url": "https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b", "cve": "CVE-2018-3772", "cwe": "CWE-78", "file": "whereis-0-4-0/vuln.js", "function": "whereis", "id": "whereis-0-4-0:vuln", "label": "vuln", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "whereis-0-4-0", "project": "whereis", "provenance": "human", "relpath": "index.js", "repo": "vvo/node-whereis", "split": "holdout", "year": 2018}
|
||||
{"class": "command injection", "commit": "0f64e3780235004fb6e43bfd153ea3e0e210ee2b", "commit_url": "https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b", "cve": "CVE-2018-3772", "cwe": "CWE-78", "file": "whereis-0-4-0/fixed.js", "function": "whereis", "id": "whereis-0-4-0:fixed", "label": "fixed", "license": "MIT", "mechanism": "source_reaches_sink", "pair": "whereis-0-4-0", "project": "whereis", "provenance": "human", "relpath": "index.js", "repo": "vvo/node-whereis", "split": "holdout", "year": 2018}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Provenance: jashkenas/underscore (fixed).
|
||||
// repo: jashkenas/underscore
|
||||
// commit: 4c73526d43838ad6ab43a6134728776632adeb66
|
||||
// parent: ef646ccbbbd971e82719c83fc69f56a5585b3a01
|
||||
// commit_url: https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66
|
||||
// cve: CVE-2021-23358
|
||||
// license: MIT
|
||||
// function: template
|
||||
// relpath: modules/template.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 38
|
||||
|
||||
export default function template(text, settings, oldSettings) {
|
||||
if (!settings && oldSettings) settings = oldSettings;
|
||||
settings = defaults({}, settings, _.templateSettings);
|
||||
|
||||
// Combine delimiters into one regular expression via alternation.
|
||||
var matcher = RegExp([
|
||||
(settings.escape || noMatch).source,
|
||||
(settings.interpolate || noMatch).source,
|
||||
(settings.evaluate || noMatch).source
|
||||
].join('|') + '|$', 'g');
|
||||
|
||||
// Compile the template source, escaping string literals appropriately.
|
||||
var index = 0;
|
||||
var source = "__p+='";
|
||||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||||
source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
|
||||
index = offset + match.length;
|
||||
|
||||
if (escape) {
|
||||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||||
} else if (interpolate) {
|
||||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||||
} else if (evaluate) {
|
||||
source += "';\n" + evaluate + "\n__p+='";
|
||||
}
|
||||
|
||||
// Adobe VMs need the match returned to produce the correct offset.
|
||||
return match;
|
||||
});
|
||||
source += "';\n";
|
||||
|
||||
var argument = settings.variable;
|
||||
if (argument) {
|
||||
// Insure against third-party code injection.
|
||||
if (!bareIdentifier.test(argument)) throw new Error(
|
||||
'variable is not a bare identifier: ' + argument
|
||||
);
|
||||
} else {
|
||||
// If a variable is not specified, place data values in local scope.
|
||||
source = 'with(obj||{}){\n' + source + '}\n';
|
||||
argument = 'obj';
|
||||
}
|
||||
|
||||
source = "var __t,__p='',__j=Array.prototype.join," +
|
||||
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
||||
source + 'return __p;\n';
|
||||
|
||||
var render;
|
||||
try {
|
||||
render = new Function(argument, '_', source);
|
||||
} catch (e) {
|
||||
e.source = source;
|
||||
throw e;
|
||||
}
|
||||
|
||||
var template = function(data) {
|
||||
return render.call(this, data, _);
|
||||
};
|
||||
|
||||
// Provide the compiled source as a convenience for precompilation.
|
||||
template.source = 'function(' + argument + '){\n' + source + '}';
|
||||
|
||||
return template;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Provenance: jashkenas/underscore (vuln).
|
||||
// repo: jashkenas/underscore
|
||||
// commit: ef646ccbbbd971e82719c83fc69f56a5585b3a01
|
||||
// parent: ef646ccbbbd971e82719c83fc69f56a5585b3a01
|
||||
// commit_url: https://github.com/jashkenas/underscore/commit/4c73526d43838ad6ab43a6134728776632adeb66
|
||||
// cve: CVE-2021-23358
|
||||
// license: MIT
|
||||
// function: template
|
||||
// relpath: modules/template.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 31
|
||||
|
||||
export default function template(text, settings, oldSettings) {
|
||||
if (!settings && oldSettings) settings = oldSettings;
|
||||
settings = defaults({}, settings, _.templateSettings);
|
||||
|
||||
// Combine delimiters into one regular expression via alternation.
|
||||
var matcher = RegExp([
|
||||
(settings.escape || noMatch).source,
|
||||
(settings.interpolate || noMatch).source,
|
||||
(settings.evaluate || noMatch).source
|
||||
].join('|') + '|$', 'g');
|
||||
|
||||
// Compile the template source, escaping string literals appropriately.
|
||||
var index = 0;
|
||||
var source = "__p+='";
|
||||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||||
source += text.slice(index, offset).replace(escapeRegExp, escapeChar);
|
||||
index = offset + match.length;
|
||||
|
||||
if (escape) {
|
||||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||||
} else if (interpolate) {
|
||||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||||
} else if (evaluate) {
|
||||
source += "';\n" + evaluate + "\n__p+='";
|
||||
}
|
||||
|
||||
// Adobe VMs need the match returned to produce the correct offset.
|
||||
return match;
|
||||
});
|
||||
source += "';\n";
|
||||
|
||||
// If a variable is not specified, place data values in local scope.
|
||||
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
||||
|
||||
source = "var __t,__p='',__j=Array.prototype.join," +
|
||||
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
||||
source + 'return __p;\n';
|
||||
|
||||
var render;
|
||||
try {
|
||||
render = new Function(settings.variable || 'obj', '_', source);
|
||||
} catch (e) {
|
||||
e.source = source;
|
||||
throw e;
|
||||
}
|
||||
|
||||
var template = function(data) {
|
||||
return render.call(this, data, _);
|
||||
};
|
||||
|
||||
// Provide the compiled source as a convenience for precompilation.
|
||||
var argument = settings.variable || 'obj';
|
||||
template.source = 'function(' + argument + '){\n' + source + '}';
|
||||
|
||||
return template;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Provenance: vvo/node-whereis (fixed).
|
||||
// repo: vvo/node-whereis
|
||||
// commit: 0f64e3780235004fb6e43bfd153ea3e0e210ee2b
|
||||
// parent: b8b642b1163baa37f15ed49b4064dcbdb6e1876c
|
||||
// commit_url: https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b
|
||||
// cve: CVE-2018-3772
|
||||
// license: MIT
|
||||
// function: whereis
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 3
|
||||
|
||||
module.exports = function whereis(name, cb) {
|
||||
cp.execFile('which', [name], function(error, stdout, stderr) {
|
||||
stdout = stdout.split('\n')[0];
|
||||
if (error || stderr || stdout === '' || stdout.charAt(0) !== '/') {
|
||||
stdout = stdout.split('\n')[0];
|
||||
cp.execFile('whereis', [name], function(error, stdout, stderr) {
|
||||
if (error || stderr || stdout === '' || stdout.indexOf( '/' ) === -1) {
|
||||
cp.execFile('where', [name], function (error, stdout, stderr) { //windows
|
||||
if (error || stderr || stdout === '' || stdout.indexOf('\\') === -1) {
|
||||
cp.exec('for %i in (' + name + '.exe) do @echo. %~$PATH:i', function (error, stdout, stderr) { //windows xp
|
||||
if (error || stderr || stdout === '' || stdout.indexOf('\\') === -1) {
|
||||
return cb(new Error('Could not find ' + name + ' on your system'));
|
||||
}
|
||||
return cb(null, stdout);
|
||||
});
|
||||
} else {
|
||||
return cb(null, stdout);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return cb(null, stdout.split(' ')[1]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return cb(null, stdout);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
// Provenance: vvo/node-whereis (vuln).
|
||||
// repo: vvo/node-whereis
|
||||
// commit: b8b642b1163baa37f15ed49b4064dcbdb6e1876c
|
||||
// parent: b8b642b1163baa37f15ed49b4064dcbdb6e1876c
|
||||
// commit_url: https://github.com/vvo/node-whereis/commit/0f64e3780235004fb6e43bfd153ea3e0e210ee2b
|
||||
// cve: CVE-2018-3772
|
||||
// license: MIT
|
||||
// function: whereis
|
||||
// relpath: index.js
|
||||
// provenance: human
|
||||
// mechanism: source_reaches_sink
|
||||
// upstream_start: 3
|
||||
|
||||
module.exports = function whereis(name, cb) {
|
||||
cp.exec('which ' + name, function(error, stdout, stderr) {
|
||||
stdout = stdout.split('\n')[0];
|
||||
if (error || stderr || stdout === '' || stdout.charAt(0) !== '/') {
|
||||
stdout = stdout.split('\n')[0];
|
||||
cp.exec('whereis ' + name, function(error, stdout, stderr) {
|
||||
if (error || stderr || stdout === '' || stdout.indexOf( '/' ) === -1) {
|
||||
cp.exec('where ' + name, function (error, stdout, stderr) { //windows
|
||||
if (error || stderr || stdout === '' || stdout.indexOf('\\') === -1) {
|
||||
cp.exec('for %i in (' + name + '.exe) do @echo. %~$PATH:i', function (error, stdout, stderr) { //windows xp
|
||||
if (error || stderr || stdout === '' || stdout.indexOf('\\') === -1) {
|
||||
return cb(new Error('Could not find ' + name + ' on your system'));
|
||||
}
|
||||
return cb(null, stdout);
|
||||
});
|
||||
} else {
|
||||
return cb(null, stdout);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
return cb(null, stdout.split(' ')[1]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return cb(null, stdout);
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user