UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

105 lines 5.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FILE_PATH_VALIDITY = void 0; const linter_format_1 = require("../linter-format"); const flowr_search_builder_1 = require("../../search/flowr-search-builder"); const range_1 = require("../../util/range"); const dependencies_query_format_1 = require("../../queries/catalog/dependencies-query/dependencies-query-format"); const built_in_source_1 = require("../../dataflow/internal/process/functions/call/built-in/built-in-source"); const logic_1 = require("../../util/logic"); const happens_before_1 = require("../../control-flow/happens-before"); const linter_tags_1 = require("../linter-tags"); const search_enrichers_1 = require("../../search/search-executor/search-enrichers"); exports.FILE_PATH_VALIDITY = { createSearch: (config) => flowr_search_builder_1.Q.fromQuery({ type: 'dependencies', enabledCategories: ['read', 'write'], readFunctions: config.additionalReadFunctions, writeFunctions: config.additionalWriteFunctions }).with(search_enrichers_1.Enrichment.CfgInformation), processSearchResult: (elements, config, data) => { const cfg = elements.enrichmentContent(search_enrichers_1.Enrichment.CfgInformation).cfg.graph; const metadata = { totalReads: 0, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0 }; const results = elements.enrichmentContent(search_enrichers_1.Enrichment.QueryData).queries['dependencies']; return { results: elements.getElements().flatMap(element => { const matchingRead = results.read.find(r => r.nodeId === element.node.info.id); if (!matchingRead) { return []; } metadata.totalReads++; const loc = range_1.SourceLocation.fromNode(element.node); if (!loc) { return []; } // check if we can't parse the file path statically if (matchingRead.value === dependencies_query_format_1.Unknown) { metadata.totalUnknown++; if (config.includeUnknown) { return [{ involvedId: matchingRead.nodeId, loc, filePath: dependencies_query_format_1.Unknown, certainty: linter_format_1.LintingResultCertainty.Uncertain }]; } else { return []; } } // check if any write to the same file happens before the read, and exclude this case if so const writesToFile = results.write.filter(r => samePath(r.value, matchingRead.value, data.analyzer.flowrConfig.solver.resolveSource?.ignoreCapitalization)); const writesBefore = writesToFile.map(w => (0, happens_before_1.happensBefore)(cfg, w.nodeId, element.node.info.id)); if (writesBefore.some(w => w === logic_1.Ternary.Always)) { metadata.totalWritesBeforeAlways++; return []; } // check if the file exists! const paths = (0, built_in_source_1.findSource)(data.analyzer.flowrConfig.solver.resolveSource, matchingRead.value, { referenceChain: element.node.info.file ? [element.node.info.file] : [], ctx: data.analyzer.inspectContext() }); if (paths && paths.length) { metadata.totalValid++; return []; } return [{ involvedId: matchingRead.nodeId, loc, filePath: matchingRead.value, certainty: writesBefore && writesBefore.length && writesBefore.every(w => w === logic_1.Ternary.Maybe) ? linter_format_1.LintingResultCertainty.Uncertain : linter_format_1.LintingResultCertainty.Certain }]; }), '.meta': metadata }; }, info: { name: 'File Path Validity', description: 'Checks whether file paths used in read and write operations are valid and point to existing files.', // checks all found paths for whether they're valid to ensure correctness, but doesn't handle non-constant paths so not all will be returned certainty: linter_format_1.LintingRuleCertainty.BestEffort, tags: [linter_tags_1.LintingRuleTag.Robustness, linter_tags_1.LintingRuleTag.Reproducibility, linter_tags_1.LintingRuleTag.Bug], defaultConfig: { additionalReadFunctions: [], additionalWriteFunctions: [], includeUnknown: false } }, prettyPrint: { [linter_format_1.LintingPrettyPrintContext.Query]: result => `Path \`${result.filePath}\` at ${range_1.SourceLocation.format(result.loc)}`, [linter_format_1.LintingPrettyPrintContext.Full]: result => `Path \`${result.filePath}\` at ${range_1.SourceLocation.format(result.loc)} does not point to a valid file` } }; function samePath(a, b, ignoreCapitalization) { if (ignoreCapitalization === true) { a = a.toLowerCase(); b = b.toLowerCase(); } return a === b; } //# sourceMappingURL=file-path-validity.js.map