{ // Place your python workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. // Placeholders with the same ids are connected. // Example: // "Print to console": { // "scope": "javascript,typescript", // "prefix": "log", // "body": [ // "console.log('$1');", // "$2" // ], // "description": "Log output to console" // } "Has relative path": { "scope": "ql", "prefix": "has relative path", "body": [ "exists($1.getLocation().getFile().getRelativePath())" ], "description": "has relative path", }, "Exists": { "scope": "ql", "prefix": "exists", "body": [ "exists(${1:DataFlow::Node node} |", " $2", ")" ], "description": "Exists clause", }, "Predicate": { "scope": "ql", "prefix": "predicate", "body": [ "predicate ${1:isFoo}(${2:DataFlow::Node node}) {", " ${3:any()}", "}" ], "description": "Predicate", }, "Class": { "scope": "ql", "prefix": "class", "body": [ "class ${1:MyClass} extends ${2:DataFlow::MethodCallNode} {", " $1() { ${3:getMethodName() = \"foo\"} }", "", " DataFlow::Node ${4:getThing}() { result = ${5:getArgument(0)} }", "}" ], "description": "Class", }, "Abstract class": { "scope": "ql", "prefix": "abstract class", "body": [ "abstract class ${1:AdditionalThing} extends ${2:DataFlow::Node} {", " abstract ${3:DataFlow::Node} ${4:getThing}($5);", "}" ], "description": "Class", }, "Class::Range": { "scope": "ql", "prefix": "range class", "body": [ "class ${1:MyClass} extends ${2:DataFlow::Node} {", " $1::Range range;", "", " $1() { this = range }", "", " ${3:DataFlow::Node} ${4:getThing}() { result = range.$4() }", "}", "", "module $1 {", " abstract class Range extends $2 {", " abstract $3 $4();", " }", "}", ], "description": "Class with ::Range pattern", }, "Class::Range delegate": { "scope": "ql", "prefix": "range delegate", "body": [ "${1:DataFlow::Node} ${2:getThing}() { result = range.$2() }" ], "description": "Predicate that delegates to range class", }, "Type tracking predicate": { "scope": "ql", "prefix": "type tracking", "body": [ "/** Gets a reference to a ${3:thing}. */", "private DataFlow::Node ${1:myType}(DataFlow::TypeTracker t) {", " t.start() and", " result = ${2:value}", " or", " exists(DataFlow::TypeTracker t2 |", " result = $1(t2).track(t2, t)", " )", "}", "", "/** Gets a reference to a ${3:thing}. */", "DataFlow::Node $1() {", " result = $1(DataFlow::TypeTracker::end())", "}" ], "description": "Type tracking predicate", }, "Type tracking module": { "scope": "ql", "prefix": "type tracking module", "body": [ "// ---------------------------------------------------------------------------", "// ${1:modulename}", "// ---------------------------------------------------------------------------", "/** Gets a reference to the `$1` module. */", "private DataFlow::Node $1(DataFlow::TypeTracker t) {", " t.start() and", " result = DataFlow::importNode(\"$1\")", " or", " exists(DataFlow::TypeTracker t2 | result = $1(t2).track(t2, t))", "}", "", "/** Gets a reference to the `$1` module. */", "DataFlow::Node $1() { result = $1(DataFlow::TypeTracker::end()) }", "", "/**", " * Gets a reference to the attribute `attr_name` of the `$1` module.", " * WARNING: Only holds for a few predefined attributes.", " */", "private DataFlow::Node $1_attr(DataFlow::TypeTracker t, string attr_name) {", " attr_name in [\"${2:name}\"] and", " (", " t.start() and", " result = DataFlow::importNode(\"$1\" + \".\" + attr_name)", " or", " t.startInAttr(attr_name) and", " result = $1()", " )", " or", " // Due to bad performance when using normal setup with `$1_attr(t2, attr_name).track(t2, t)`", " // we have inlined that code and forced a join", " exists(DataFlow::TypeTracker t2 |", " exists(DataFlow::StepSummary summary |", " $1_attr_first_join(t2, attr_name, result, summary) and", " t = t2.append(summary)", " )", " )", "}", "", "pragma[nomagic]", "private predicate $1_attr_first_join(", " DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res, DataFlow::StepSummary summary", ") {", " DataFlow::StepSummary::step($1_attr(t2, attr_name), res, summary)", "}", "", "/**", " * Gets a reference to the attribute `attr_name` of the `$1` module.", " * WARNING: Only holds for a few predefined attributes.", " */", "private DataFlow::Node $1_attr(string attr_name) {", " result = $1_attr(DataFlow::TypeTracker::end(), attr_name)", "}", "", "/** Provides models for the `$1` module. */", "module $1 {", "", "}", ], "description": "Type tracking module", }, "Type tracking module member": { "scope": "ql", "prefix": "type tracking module member", "body": [ "/** Gets a reference to the `${1:module}.${2:member}` ${3:object/class}. */", "private DataFlow::Node ${4:$2}(DataFlow::TypeTracker t) {", " t.start() and", " result = DataFlow::importNode(\"$1.$2\")", " or", " t.startInAttr(\"$2\") and", " result = $1()", " or", " exists(DataFlow::TypeTracker t2 | result = $4(t2).track(t2, t))", "}", " ", "/** Gets a reference to the `$1.$2` $3. */", "DataFlow::Node $4() { result = $4(DataFlow::TypeTracker::end()) }", ], "description": "Type tracking module member", }, "Taint tracking configuration": { "scope": "ql", "prefix": "taint tracking", "body": [ "/** @kind path-problem */", "import python", "import experimental.dataflow.DataFlow", "import experimental.dataflow.TaintTracking", "import experimental.semmle.python.Concepts", "import experimental.dataflow.RemoteFlowSources", "import DataFlow::PathGraph", "class ${1:Config} extends TaintTracking::Configuration {", " $1() { this = \"$1\" } ", "", " override predicate isSource(DataFlow::Node node) {", " ${2:none()}", " }", "", " override predicate isSink(DataFlow::Node node) {", " ${3:none()}", " }", "}", "", "from $1 cfg, DataFlow::PathNode source, DataFlow::PathNode sink", "where cfg.hasFlowPath(source, sink)", "select sink, source, sink, \"taint from $@\", source.getNode(), \"here\"" ] }, "Type tracking submodule": { "scope": "ql", "prefix": "type tracking submodule", "body": [ " // -------------------------------------------------------------------------", " // ${1:parent}.${2:submodule}", " // -------------------------------------------------------------------------", " /** Gets a reference to the `$1.$2` module. */", " DataFlow::Node $2() { result = $1_attr(\"$2\") }", "", " /** Provides models for the `$1.$2` module */", " module $2 {", " /**", " * Gets a reference to the attribute `attr_name` of the `$1.$2` module.", " * WARNING: Only holds for a few predefined attributes.", " */", " private DataFlow::Node $2_attr(DataFlow::TypeTracker t, string attr_name) {", " attr_name in [\"$3\"] and", " (", " t.start() and", " result = DataFlow::importNode(\"$1.$2\" + \".\" + attr_name)", " or", " t.startInAttr(attr_name) and", " result = $2()", " )", " or", " // Due to bad performance when using normal setup with `$2_attr(t2, attr_name).track(t2, t)`", " // we have inlined that code and forced a join", " exists(DataFlow::TypeTracker t2 |", " exists(DataFlow::StepSummary summary |", " $2_attr_first_join(t2, attr_name, result, summary) and", " t = t2.append(summary)", " )", " )", " }", "", " pragma[nomagic]", " private predicate $2_attr_first_join(", " DataFlow::TypeTracker t2, string attr_name, DataFlow::Node res,", " DataFlow::StepSummary summary", " ) {", " DataFlow::StepSummary::step($2_attr(t2, attr_name), res, summary)", " }", "", " /**", " * Gets a reference to the attribute `attr_name` of the `$1.$2` module.", " * WARNING: Only holds for a few predefined attributes.", " */", " private DataFlow::Node $2_attr(string attr_name) {", " result = $2_attr(DataFlow::TypeTracker::end(), attr_name)", " }", " }", ], "description": "Type tracking submodule", }, "Type tracking class": { "scope": "ql", "prefix": "type tracking class", "body": [ " /**", " * Provides models for the `${1:module}.${2:classname}` class", " *", " * See ${6:apiref}.", " */", " module $2 {", " /** Gets a reference to the `$1.$2` class. */", " private DataFlow::Node classRef(DataFlow::TypeTracker t) {", " t.start() and", " result = ${4:module}_attr(\"$2\")", " or", " // TODO: remove/expand this part of the template as needed", " // Handle `${5:toplevel}.$2` alias", " t.start() and", " result = $5_attr(\"$2\")", " or", " exists(DataFlow::TypeTracker t2 | result = classRef(t2).track(t2, t))", " }", "", " /** Gets a reference to the `$1.$2` class. */", " DataFlow::Node classRef() { result = classRef(DataFlow::TypeTracker::end()) }", "", " /**", " * A source of an instance of `$1.$2`.", " *", " * This can include instantiation of the class, return value from function", " * calls, or a special parameter that will be set when functions are call by external", " * library.", " *", " * Use `$2::instance()` predicate to get references to instances of `$1.$2`.", " */", " abstract class InstanceSource extends DataFlow::Node { }", "", " /** A direct instantiation of `$1.$2`. */", " private class ClassInstantiation extends InstanceSource, DataFlow::CfgNode {", " override CallNode node;", "", " ClassInstantiation() { node.getFunction() = classRef().asCfgNode() }", " }", "", " /** Gets a reference to an instance of `$1.$2`. */", " private DataFlow::Node instance(DataFlow::TypeTracker t) {", " t.start() and", " result instanceof InstanceSource", " or", " exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))", " }", "", " /** Gets a reference to an instance of `$1.$2`. */", " DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) }", " }", ], "description": "Type tracking class", }, }