Merge branch 'main' into redsun82/rust-canonical-enum

This commit is contained in:
Paolo Tranquilli
2024-11-27 15:01:47 +01:00
103 changed files with 3379 additions and 667 deletions

87
.vscode/tasks.json vendored
View File

@@ -38,6 +38,93 @@
"command": "${config:python.pythonPath}",
},
"problemMatcher": []
},
{
"label": "Create query change note",
"type": "process",
"command": "python3",
"args": [
"misc/scripts/create-change-note.py",
"${input:language}",
"src",
"${input:name}",
"${input:categoryQuery}"
],
"presentation": {
"reveal": "never",
"close": true
},
"problemMatcher": []
},
{
"label": "Create library change note",
"type": "process",
"command": "python3",
"args": [
"misc/scripts/create-change-note.py",
"${input:language}",
"lib",
"${input:name}",
"${input:categoryLibrary}"
],
"presentation": {
"reveal": "never",
"close": true
},
"problemMatcher": []
}
],
"inputs": [
{
"type": "pickString",
"id": "language",
"description": "Language",
"options":
[
"go",
"java",
"javascript",
"cpp",
"csharp",
"python",
"ruby",
"rust",
"swift",
]
},
{
"type": "promptString",
"id": "name",
"description": "Short name (kebab-case)"
},
{
"type": "pickString",
"id": "categoryQuery",
"description": "Category (query change)",
"options":
[
"breaking",
"deprecated",
"newQuery",
"queryMetadata",
"majorAnalysis",
"minorAnalysis",
"fix",
]
},
{
"type": "pickString",
"id": "categoryLibrary",
"description": "Category (library change)",
"options":
[
"breaking",
"deprecated",
"feature",
"majorAnalysis",
"minorAnalysis",
"fix",
]
}
]
}

View File

@@ -793,28 +793,27 @@ private Element interpretElement0(
) {
(
// Non-member functions
elementSpec(namespace, type, subtypes, name, signature, _) and
funcHasQualifiedName(result, namespace, name) and
subtypes = false and
type = "" and
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
or
signature = "" and
elementSpec(namespace, type, subtypes, name, "", _) and
funcHasQualifiedName(result, namespace, name)
elementSpec(namespace, type, subtypes, name, signature, _)
)
or
// Member functions
exists(Class namedClass, Class classWithMethod |
hasClassAndName(classWithMethod, result, name) and
classHasQualifiedName(namedClass, namespace, type)
|
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature) and
hasClassAndName(classWithMethod, result, name)
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
or
signature = "" and
elementSpec(namespace, type, subtypes, name, "", _) and
hasClassAndName(classWithMethod, result, name)
elementSpec(namespace, type, subtypes, name, "", _)
) and
classHasQualifiedName(namedClass, namespace, type) and
(
// member declared in the named type or a subtype of it
subtypes = true and

View File

@@ -164,4 +164,10 @@ void test_format() {
auto s2 = std::format(string::source());
sink(s2); // $ ir MISSING: ast
}
void test(std::format_string s) {
int x = source();
int y = std::same_signature_as_format_but_different_name(s, x);
sink(y); // clean
}

View File

@@ -451,6 +451,9 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| format.cpp:162:24:162:27 | {} | format.cpp:162:24:162:27 | call to basic_format_string | TAINT |
| format.cpp:165:13:165:23 | call to format | format.cpp:166:8:166:9 | s2 | |
| format.cpp:165:25:165:38 | call to source | format.cpp:165:25:165:40 | call to basic_format_string | TAINT |
| format.cpp:169:30:169:30 | s | format.cpp:171:60:171:60 | s | |
| format.cpp:170:11:170:16 | call to source | format.cpp:171:63:171:63 | x | |
| format.cpp:171:11:171:58 | call to same_signature_as_format_but_different_name | format.cpp:172:8:172:8 | y | |
| map.cpp:21:28:21:28 | call to pair | map.cpp:23:2:23:2 | a | |
| map.cpp:21:28:21:28 | call to pair | map.cpp:24:7:24:7 | a | |
| map.cpp:21:28:21:28 | call to pair | map.cpp:25:7:25:7 | a | |

View File

@@ -676,4 +676,9 @@ namespace std {
using format_string = basic_format_string<char>; // simplified from `char, std::type_identity_t<Args>...`
template<class... Args> string format( format_string fmt, Args&&... args );
// This function has the same signature as `format`, but a different name. It should NOT be able to use
// the model for `format`.
template <typename... Args>
int same_signature_as_format_but_different_name(format_string, Args &&...args);
}

View File

@@ -265,6 +265,8 @@ signatureMatches
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 0 |
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 1 |
| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | (format_string,Args &&) | | format<Args> | 0 |
| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | (format_string,Args &&) | | format<Args> | 1 |
getSignatureParameterName
| (InputIt,InputIt) | deque | assign<InputIt> | 0 | func:0 |
| (InputIt,InputIt) | deque | assign<InputIt> | 1 | func:0 |
@@ -729,6 +731,8 @@ getParameterTypeName
| stl.h:678:33:678:38 | format | 0 | format_string |
| stl.h:678:33:678:38 | format | 1 | func:0 && |
| stl.h:678:33:678:38 | format | 1 | func:0 && |
| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | 0 | format_string |
| stl.h:683:6:683:48 | same_signature_as_format_but_different_name | 1 | func:0 && |
| stringstream.cpp:18:6:18:9 | sink | 0 | const basic_ostream> & |
| stringstream.cpp:21:6:21:9 | sink | 0 | const basic_istream> & |
| stringstream.cpp:24:6:24:9 | sink | 0 | const basic_iostream> & |

View File

@@ -130,6 +130,7 @@ os,29,11,6,3,,,,,26,,,,,,,,,,,7,3,,1,6,
path,,,18,,,,,,,,,,,,,,,,,,,,,18,
reflect,,,37,,,,,,,,,,,,,,,,,,,,,37,
regexp,10,,20,,,,,,,3,3,4,,,,,,,,,,,,20,
slices,,,17,,,,,,,,,,,,,,,,,,,,,,17
sort,,,1,,,,,,,,,,,,,,,,,,,,,1,
strconv,,,9,,,,,,,,,,,,,,,,,,,,,9,
strings,,,34,,,,,,,,,,,,,,,,,,,,,34,
1 package sink source summary sink:command-injection sink:credentials-key sink:jwt sink:log-injection sink:nosql-injection sink:path-injection sink:regex-use[0] sink:regex-use[1] sink:regex-use[c] sink:request-forgery sink:request-forgery[TCP Addr + Port] sink:sql-injection sink:url-redirection sink:url-redirection[0] sink:url-redirection[receiver] sink:xpath-injection source:environment source:file source:remote source:stdin summary:taint summary:value
130 path 18 18
131 reflect 37 37
132 regexp 10 20 3 3 4 20
133 slices 17 17
134 sort 1 1
135 strconv 9 9
136 strings 34 34

View File

@@ -26,7 +26,7 @@ Go framework & library support
`Macaron <https://gopkg.in/macaron.v1>`_,``gopkg.in/macaron*``,12,1,1
`Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4
`SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1,
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",33,587,104
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",33,604,104
`XPath <https://github.com/antchfx/xpath>`_,``github.com/antchfx/xpath*``,,,4
`appleboy/gin-jwt <https://github.com/appleboy/gin-jwt>`_,``github.com/appleboy/gin-jwt*``,,,1
`beego <https://beego.me/>`_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",63,63,213
@@ -61,5 +61,5 @@ Go framework & library support
`yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9,
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,33
Others,"``github.com/Masterminds/squirrel``, ``github.com/caarlos0/env``, ``github.com/go-gorm/gorm``, ``github.com/go-xorm/xorm``, ``github.com/gobuffalo/envy``, ``github.com/gogf/gf/database/gdb``, ``github.com/hashicorp/go-envparse``, ``github.com/jinzhu/gorm``, ``github.com/jmoiron/sqlx``, ``github.com/joho/godotenv``, ``github.com/kelseyhightower/envconfig``, ``github.com/lann/squirrel``, ``github.com/raindog308/gorqlite``, ``github.com/rqlite/gorqlite``, ``github.com/uptrace/bun``, ``go.mongodb.org/mongo-driver/mongo``, ``gopkg.in/Masterminds/squirrel``, ``gorm.io/gorm``, ``xorm.io/xorm``",23,2,391
Totals,,307,911,1532
Totals,,307,928,1532

View File

@@ -0,0 +1,31 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: summaryModel
data:
# All should be modeled when we have a way to model iterators
# AppendSec should be modeled when we have a way to model iterators
# Backward should be modeled when we have a way to model iterators
# Chunk should be modeled when we have a way to model iterators
- ["slices", "", False, "Clip", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Clone", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
# Collect should be modeled when we have a way to model iterators
- ["slices", "", False, "Compact", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "CompactFunc", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Concat", "", "", "Argument[0].ArrayElement.ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Delete", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "DeleteFunc", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Grow", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Insert", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Insert", "", "", "Argument[2].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Max", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
- ["slices", "", False, "MaxFunc", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
- ["slices", "", False, "Min", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
- ["slices", "", False, "MinFunc", "", "", "Argument[0].ArrayElement", "ReturnValue", "value", "manual"]
- ["slices", "", False, "Repeat", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Replace", "", "", "Argument[0].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
- ["slices", "", False, "Replace", "", "", "Argument[3].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"]
# Sorted should be modeled when we have a way to model iterators
# SortedFunc should be modeled when we have a way to model iterators
# SortedStableFunc should be modeled when we have a way to model iterators
# Values should be modeled when we have a way to model iterators

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added value flow models for functions in the `slices` package which do not involve the `iter` package.

View File

@@ -0,0 +1,193 @@
package main
import (
"cmp"
"slices"
"strings"
)
func TaintStepTest_SlicesClip(fromStringSlice []string) []string {
toStringSlice := slices.Clip(fromStringSlice)
return toStringSlice
}
func TaintStepTest_SlicesClone(fromStringSlice []string) []string {
toStringSlice := slices.Clone(fromStringSlice)
return toStringSlice
}
func TaintStepTest_SlicesCompact(fromStringSlice []string) []string {
toStringSlice := slices.Compact(fromStringSlice)
return toStringSlice
}
func TaintStepTest_SlicesCompactFunc(fromStringSlice []string) []string {
toStringSlice := slices.CompactFunc(fromStringSlice, strings.EqualFold)
return toStringSlice
}
func TaintStepTest_SlicesConcat0(fromStringSlice []string) []string {
toStringSlice := slices.Concat(fromStringSlice, []string{"a", "b", "c"})
return toStringSlice
}
func TaintStepTest_SlicesConcat1(fromStringSlice []string) []string {
toStringSlice := slices.Concat([]string{"a", "b", "c"}, fromStringSlice)
return toStringSlice
}
func TaintStepTest_SlicesDelete(fromStringSlice []string) []string {
toStringSlice := slices.Delete(fromStringSlice, 0, 1)
return toStringSlice
}
func TaintStepTest_SlicesDeleteFunc(fromStringSlice []string) []string {
deleteEmptyString := func(str string) bool {
return str == ""
}
toStringSlice := slices.DeleteFunc(fromStringSlice, deleteEmptyString)
return toStringSlice
}
func TaintStepTest_SlicesGrow(fromStringSlice []string) []string {
toStringSlice := slices.Grow(fromStringSlice, 1)
return toStringSlice
}
func TaintStepTest_SlicesInsert0(fromStringSlice []string) []string {
toStringSlice := slices.Insert(fromStringSlice, 1, "a", "b")
return toStringSlice
}
func TaintStepTest_SlicesInsert2(fromString string) []string {
toStringSlice := slices.Insert([]string{}, 0, fromString, "b")
return toStringSlice
}
func TaintStepTest_SlicesMax(fromStringSlice []string) string {
toString := slices.Max(fromStringSlice)
return toString
}
func TaintStepTest_SlicesMaxFunc(fromStringSlice []string) string {
toString := slices.MaxFunc(fromStringSlice, cmp.Compare)
return toString
}
func TaintStepTest_SlicesMin(fromStringSlice []string) string {
toString := slices.Min(fromStringSlice)
return toString
}
func TaintStepTest_SlicesMinFunc(fromStringSlice []string) string {
toString := slices.MinFunc(fromStringSlice, cmp.Compare)
return toString
}
func TaintStepTest_SlicesRepeat(fromStringSlice []string) []string {
toStringSlice := slices.Repeat(fromStringSlice, 2)
return toStringSlice
}
func TaintStepTest_SlicesReplace0(fromStringSlice []string) []string {
toStringSlice := slices.Replace(fromStringSlice, 1, 2, "a")
return toStringSlice
}
func TaintStepTest_SlicesReplace3(fromString string) []string {
toStringSlice := slices.Replace([]string{}, 1, 3, fromString, "b")
return toStringSlice
}
func RunAllTaints_Slices() {
{
source := []string{newSource(0).(string)}
out := TaintStepTest_SlicesClip(source)
sink(0, out[0])
}
{
source := []string{newSource(1).(string)}
out := TaintStepTest_SlicesClone(source)
sink(1, out[0])
}
{
source := []string{newSource(2).(string)}
out := TaintStepTest_SlicesCompact(source)
sink(2, out[0])
}
{
source := []string{newSource(3).(string)}
out := TaintStepTest_SlicesCompactFunc(source)
sink(3, out[0])
}
{
source := []string{newSource(4).(string)}
out := TaintStepTest_SlicesConcat0(source)
sink(4, out[0])
}
{
source := []string{newSource(5).(string)}
out := TaintStepTest_SlicesConcat1(source)
sink(5, out[0])
}
{
source := []string{newSource(6).(string)}
out := TaintStepTest_SlicesDelete(source)
sink(6, out[0])
}
{
source := []string{newSource(7).(string)}
out := TaintStepTest_SlicesDeleteFunc(source)
sink(7, out[0])
}
{
source := []string{newSource(8).(string)}
out := TaintStepTest_SlicesGrow(source)
sink(8, out[0])
}
{
source := []string{newSource(9).(string)}
out := TaintStepTest_SlicesInsert0(source)
sink(9, out[0])
}
{
source := newSource(10).(string)
out := TaintStepTest_SlicesInsert2(source)
sink(10, out[0])
}
{
source := []string{newSource(11).(string)}
out := TaintStepTest_SlicesMax(source)
sink(11, out)
}
{
source := []string{newSource(12).(string)}
out := TaintStepTest_SlicesMaxFunc(source)
sink(12, out)
}
{
source := []string{newSource(13).(string)}
out := TaintStepTest_SlicesMin(source)
sink(13, out)
}
{
source := []string{newSource(14).(string)}
out := TaintStepTest_SlicesMinFunc(source)
sink(14, out)
}
{
source := []string{newSource(15).(string)}
out := TaintStepTest_SlicesRepeat(source)
sink(15, out[0])
}
{
source := []string{newSource(16).(string)}
out := TaintStepTest_SlicesReplace0(source)
sink(16, out[0])
}
{
source := newSource(17).(string)
out := TaintStepTest_SlicesReplace3(source)
sink(17, out[0])
}
}

View File

@@ -1,6 +1,6 @@
module example.com/m
go 1.20
go 1.23
require (
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb

View File

@@ -1,3 +1,3 @@
# golang.org/x/net v0.0.0-20201010224723-4f7140c49acb
## explicit
golang.org/x/net
## explicit; go 1.11
golang.org/x/net/context

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Calling `coll.contains(x)` is now a taint sanitizer (for any query) for the value `x`, where `coll` is a collection of constants.

View File

@@ -28,6 +28,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.ThreadLocal
private import semmle.code.java.frameworks.ratpack.RatpackExec
private import semmle.code.java.frameworks.stapler.Stapler
private import semmle.code.java.security.ListOfConstantsSanitizer
}
/**
@@ -189,3 +190,8 @@ private class NumberTaintPreservingCallable extends TaintPreservingCallable {
* map-key and map-value content, so that e.g. a tainted `Map` is assumed to have tainted keys and values.
*/
abstract class TaintInheritingContent extends DataFlow::Content { }
/**
* A sanitizer in all global taint flow configurations but not in local taint.
*/
abstract class DefaultTaintSanitizer extends DataFlow::Node { }

View File

@@ -13,24 +13,27 @@ private import semmle.code.java.dispatch.VirtualDispatch
private import semmle.code.java.dataflow.internal.BaseSSA
private import semmle.code.java.controlflow.Guards
private import codeql.typeflow.TypeFlow
private import codeql.typeflow.UniversalFlow as UniversalFlow
private module Input implements TypeFlowInput<Location> {
private newtype TTypeFlowNode =
/** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */
private RefType boxIfNeeded(J::Type t) {
t.(PrimitiveType).getBoxedType() = result or
result = t
}
/** Provides the input types and predicates for instantiation of `UniversalFlow`. */
module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
private newtype TFlowNode =
TField(Field f) { not f.getType() instanceof PrimitiveType } or
TSsa(BaseSsaVariable ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or
TExpr(Expr e) or
TMethod(Method m) { not m.getReturnType() instanceof PrimitiveType }
/** Gets `t` if it is a `RefType` or the boxed type if `t` is a primitive type. */
private RefType boxIfNeeded(J::Type t) {
t.(PrimitiveType).getBoxedType() = result or
result = t
}
/**
* A `Field`, `BaseSsaVariable`, `Expr`, or `Method`.
*/
class TypeFlowNode extends TTypeFlowNode {
class FlowNode extends TFlowNode {
/** Gets a textual representation of this element. */
string toString() {
result = this.asField().toString() or
result = this.asSsa().toString() or
@@ -38,6 +41,7 @@ private module Input implements TypeFlowInput<Location> {
result = this.asMethod().toString()
}
/** Gets the source location for this element. */
Location getLocation() {
result = this.asField().getLocation() or
result = this.asSsa().getLocation() or
@@ -45,14 +49,19 @@ private module Input implements TypeFlowInput<Location> {
result = this.asMethod().getLocation()
}
/** Gets the field corresponding to this node, if any. */
Field asField() { this = TField(result) }
/** Gets the SSA variable corresponding to this node, if any. */
BaseSsaVariable asSsa() { this = TSsa(result) }
/** Gets the expression corresponding to this node, if any. */
Expr asExpr() { this = TExpr(result) }
/** Gets the method corresponding to this node, if any. */
Method asMethod() { this = TMethod(result) }
/** Gets the type of this node. */
RefType getType() {
result = this.asField().getType() or
result = this.asSsa().getSourceVariable().getType() or
@@ -61,8 +70,6 @@ private module Input implements TypeFlowInput<Location> {
}
}
class Type = RefType;
private SrcCallable viableCallable_v1(Call c) {
result = viableImpl_v1(c)
or
@@ -88,7 +95,7 @@ private module Input implements TypeFlowInput<Location> {
*
* For a given `n2`, this predicate must include all possible `n1` that can flow to `n2`.
*/
predicate step(TypeFlowNode n1, TypeFlowNode n2) {
predicate step(FlowNode n1, FlowNode n2) {
n2.asExpr().(ChooseExpr).getAResultExpr() = n1.asExpr()
or
exists(Field f, Expr e |
@@ -134,7 +141,7 @@ private module Input implements TypeFlowInput<Location> {
/**
* Holds if `null` is the only value that flows to `n`.
*/
predicate isNullValue(TypeFlowNode n) {
predicate isNullValue(FlowNode n) {
n.asExpr() instanceof NullLiteral
or
exists(LocalVariableDeclExpr decl |
@@ -144,11 +151,21 @@ private module Input implements TypeFlowInput<Location> {
)
}
predicate isExcludedFromNullAnalysis(TypeFlowNode n) {
predicate isExcludedFromNullAnalysis(FlowNode n) {
// Fields that are never assigned a non-null value are probably set by
// reflection and are thus not always null.
exists(n.asField())
}
}
private module Input implements TypeFlowInput<Location> {
import FlowStepsInput
class TypeFlowNode = FlowNode;
predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1;
class Type = RefType;
predicate exactTypeBase(TypeFlowNode n, RefType t) {
exists(ClassInstanceExpr e |

View File

@@ -38,6 +38,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable {
/** Gets the `Callable` in which this `BaseSsaSourceVariable` is defined. */
Callable getEnclosingCallable() { this = TLocalVar(result, _) }
/** Gets a textual representation of this element. */
string toString() {
exists(LocalScopeVariable v, Callable c | this = TLocalVar(c, v) |
if c = v.getCallable()
@@ -46,6 +47,7 @@ class BaseSsaSourceVariable extends TBaseSsaSourceVariable {
)
}
/** Gets the source location for this element. */
Location getLocation() {
exists(LocalScopeVariable v | this = TLocalVar(_, v) and result = v.getLocation())
}
@@ -482,8 +484,10 @@ class BaseSsaVariable extends TBaseSsaVariable {
this = TSsaEntryDef(_, result)
}
/** Gets a textual representation of this element. */
string toString() { none() }
/** Gets the source location for this element. */
Location getLocation() { result = this.getCfgNode().getLocation() }
/** Gets the `BasicBlock` in which this SSA variable is defined. */

View File

@@ -161,6 +161,7 @@ private module Cached {
*/
cached
predicate defaultTaintSanitizer(DataFlow::Node node) {
node instanceof DefaultTaintSanitizer or
// Ignore paths through test code.
node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass or
node.asExpr() instanceof ValidatedVariableAccess

View File

@@ -246,7 +246,7 @@ string getInsecureAlgorithmRegex() {
string getASecureAlgorithmName() {
result =
[
"RSA", "SHA-?256", "SHA-?512", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))",
"RSA", "SHA-?(256|384|512)", "CCM", "GCM", "AES(?![^a-zA-Z](ECB|CBC/PKCS[57]Padding))",
"Blowfish", "ECIES", "SHA3-(256|384|512)"
]
}

View File

@@ -0,0 +1,263 @@
/**
* Provides a default taint sanitizer identifying comparisons against lists of
* compile-time constants.
*/
import java
private import codeql.typeflow.UniversalFlow as UniversalFlow
private import semmle.code.java.Collections
private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dataflow.internal.BaseSSA
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.dispatch.VirtualDispatch
private class FlowNode = FlowStepsInput::FlowNode;
/**
* Holds if `n2` is an unmodifiable collection constructed from input `n1`,
* which is either another collection or a number of elements.
*/
private predicate unmodifiableCollectionStep(FlowNode n1, FlowNode n2) {
exists(Call c, Callable tgt |
n2.asExpr() = c and
n1.asExpr() = c.getAnArgument() and
c.getCallee().getSourceDeclaration() = tgt
|
tgt.hasQualifiedName("java.util", "Collections",
["unmodifiableCollection", "unmodifiableList", "unmodifiableSet"])
or
tgt.hasQualifiedName("java.util", ["List", "Set"], ["copyOf", "of"])
or
tgt.hasQualifiedName("com.google.common.collect", ["ImmutableList", "ImmutableSet"],
["copyOf", "of"])
)
}
/**
* Holds if `n2` is a collection or array constructed from input `n1`, which is
* either a collection, an array, or a number of elements.
*/
private predicate collectionStep(FlowNode n1, FlowNode n2) {
n2.asExpr().(ArrayInit).getAnInit() = n1.asExpr()
or
n2.asExpr().(ArrayCreationExpr).getInit() = n1.asExpr()
or
unmodifiableCollectionStep(n1, n2)
or
exists(Call c, Callable tgt |
n2.asExpr() = c and
n1.asExpr() = c.getAnArgument() and
c.getCallee().getSourceDeclaration() = tgt
|
tgt.hasQualifiedName("java.util", "Arrays", "asList")
or
tgt.isStatic() and
tgt.hasName(["copyOf", "of"]) and
tgt.getDeclaringType().getASourceSupertype+().hasQualifiedName("java.util", "Collection")
or
tgt instanceof Constructor and
tgt.getNumberOfParameters() = 1 and
tgt.getParameterType(0) instanceof CollectionType and
tgt.getDeclaringType() instanceof CollectionType
)
}
private module BaseUniversalFlow = UniversalFlow::Make<Location, FlowStepsInput>;
private module UnmodifiableProp implements BaseUniversalFlow::NullaryPropertySig {
predicate hasPropertyBase(FlowNode n) { unmodifiableCollectionStep(_, n) }
}
/** Holds if the given node is an unmodifiable collection. */
private predicate unmodifiableCollection =
BaseUniversalFlow::FlowNullary<UnmodifiableProp>::hasProperty/1;
/**
* Holds if `v` is a collection or array with an access, `coll`, at which the
* element `e` gets added.
*/
private predicate collectionAddition(Variable v, VarAccess coll, Expr e) {
exists(MethodCall mc, Method m, int arg |
mc.getMethod().getSourceDeclaration().overridesOrInstantiates*(m) and
mc.getQualifier() = coll and
v.getAnAccess() = coll and
mc.getArgument(arg) = e
|
m.hasQualifiedName("java.util", "Collection", ["add", "addAll"]) and
m.getNumberOfParameters() = 1 and
arg = 0
or
m.hasQualifiedName("java.util", "List", ["add", "addAll"]) and
m.getNumberOfParameters() = 2 and
arg = 1
or
m.hasQualifiedName("java.util", "SequencedCollection", ["addFirst", "addLast"]) and
m.getNumberOfParameters() = 1 and
arg = 0
)
or
v.getAnAccess() = coll and
exists(Assignment assign | assign.getSource() = e |
coll = assign.getDest().(ArrayAccess).getArray()
)
}
/**
* Holds if `n` represents a definition of `v` and `v` is a collection or
* array that has additions occurring as side-effects after its definition.
*/
private predicate nodeWithAddition(FlowNode n, Variable v) {
collectionAddition(v, _, _) and
(
n.asField() = v
or
n.asSsa().getSourceVariable().getVariable() = v and
(n.asSsa() instanceof BaseSsaUpdate or n.asSsa().(BaseSsaImplicitInit).isParameterDefinition(_))
)
}
/** Holds if `c` does not add elements to the given collection. */
private predicate safeCallable(Callable c) {
c instanceof CollectionQueryMethod
or
c instanceof CollectionMethod and
c.hasName(["clear", "remove", "removeAll", "stream", "iterator", "toArray"])
or
c.hasQualifiedName("org.apache.commons.lang3", "StringUtils", "join")
}
/**
* Holds if `n` might be mutated in ways that adds elements that are not
* tracked by the `collectionAddition` predicate.
*/
private predicate collectionWithPossibleMutation(FlowNode n) {
not unmodifiableCollection(n) and
(
exists(Expr e |
n.asExpr() = e and
(e.getType() instanceof CollectionType or e.getType() instanceof Array) and
not collectionAddition(_, e, _) and
not collectionStep(n, _)
|
exists(ArrayAccess aa | e = aa.getArray())
or
exists(Call c, Callable tgt | c.getAnArgument() = e or c.getQualifier() = e |
tgt = c.getCallee().getSourceDeclaration() and
not safeCallable(tgt)
)
)
or
exists(FlowNode mid |
FlowStepsInput::step(n, mid) and
collectionWithPossibleMutation(mid)
)
)
}
/**
* A collection constructor that constructs an empty mutable collection.
*/
private class EmptyCollectionConstructor extends Constructor {
EmptyCollectionConstructor() {
this.getDeclaringType() instanceof CollectionType and
forall(Type t | t = this.getAParamType() | t instanceof PrimitiveType)
}
}
private module CollectionFlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
import FlowStepsInput
/**
* Holds if `n2` is a collection/array/constant whose value(s) are
* determined completely from the range of `n1` nodes.
*/
predicate step(FlowNode n1, FlowNode n2) {
// Exclude the regular input constraints for those nodes that are covered
// completely by `collectionStep`.
FlowStepsInput::step(n1, n2) and
not collectionStep(_, n2)
or
// For collections with side-effects in the form of additions, we add the
// sources of those additions as additional input that need to originate
// from constants.
exists(Variable v |
nodeWithAddition(n2, v) and
collectionAddition(v, _, n1.asExpr())
)
or
// Include various forms of collection transformation.
collectionStep(n1, n2)
}
predicate isExcludedFromNullAnalysis = FlowStepsInput::isExcludedFromNullAnalysis/1;
}
private module CollectionUniversalFlow = UniversalFlow::Make<Location, CollectionFlowStepsInput>;
private module ConstantCollectionProp implements CollectionUniversalFlow::NullaryPropertySig {
/**
* Holds if `n` forms the base case for finding collections of constants.
* These are individual constants and empty collections.
*/
predicate hasPropertyBase(FlowNode n) {
n.asExpr().isCompileTimeConstant() or
n.asExpr().(ConstructorCall).getConstructor() instanceof EmptyCollectionConstructor
}
predicate barrier = collectionWithPossibleMutation/1;
}
/**
* Holds if the given node is either a constant or a collection/array of
* constants.
*/
private predicate constantCollection =
CollectionUniversalFlow::FlowNullary<ConstantCollectionProp>::hasProperty/1;
/** Gets the result of a case normalization call of `arg`. */
private MethodCall normalizeCaseCall(Expr arg) {
exists(Method changecase | result.getMethod() = changecase |
changecase.hasName(["toUpperCase", "toLowerCase"]) and
changecase.getDeclaringType() instanceof TypeString and
arg = result.getQualifier()
or
changecase
.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "StringUtils",
["lowerCase", "upperCase"]) and
arg = result.getArgument(0)
or
changecase
.hasQualifiedName("org.apache.hadoop.util", "StringUtils", ["toLowerCase", "toUpperCase"]) and
arg = result.getArgument(0)
)
}
/**
* Holds if the guard `g` ensures that the expression `e` is one of a set of
* known constants upon evaluating to `branch`.
*/
private predicate constantCollectionContainsCheck(Guard g, Expr e, boolean branch) {
exists(MethodCall mc, Method m, FlowNode n, Expr checked |
g = mc and
mc.getMethod().getSourceDeclaration().overridesOrInstantiates*(m) and
m.hasQualifiedName("java.util", "Collection", "contains") and
n.asExpr() = mc.getQualifier() and
constantCollection(n) and
checked = mc.getAnArgument() and
branch = true
|
checked = e or
checked = normalizeCaseCall(e)
)
}
/**
* A comparison against a list of compile-time constants, sanitizing taint by
* restricting to a set of known values.
*/
private class ListOfConstantsComparisonSanitizerGuard extends TaintTracking::DefaultTaintSanitizer {
ListOfConstantsComparisonSanitizerGuard() {
this = DataFlow::BarrierGuard<constantCollectionContainsCheck/3>::getABarrierNode()
}
}

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added SHA-384 to the list of secure hashing algorithms. As a result the `java/potentially-weak-cryptographic-algorithm` query should no longer flag up uses of SHA-384.

View File

@@ -0,0 +1,158 @@
public class B {
// Use this method to mark non-integer bounds
// that should also be annotated.
static void bound(int b) { }
public int forLoop() {
int result = 0;
for (int i = 0;
i < 10; // $ bound="i in [0..10]"
i++) { // $ bound="i in [0..9]"
result = i; // $ bound="i in [0..9]"
}
return result; // $ bound="result in [0..9]"
}
public int forLoopExit() {
int result = 0;
for (; result < 10;) { // $ bound="result in [0..10]"
result += 1; // $ bound="result in [0..9]"
}
return result; // $ bound="result = 10"
}
public int forLoopExitStep() {
int result = 0;
for (; result < 10;) { // $ bound="result in [0..12]"
result += 3; // $ bound="result in [0..9]"
}
return result; // $ bound="result = 12"
}
public int forLoopExitUpd() {
int result = 0;
for (; result < 10; // $ bound="result in [0..10]"
result++) { // $ bound="result in [0..9]"
}
return result; // $ bound="result = 10"
}
public int forLoopExitNested() {
int result = 0;
for (; result < 10;) {
int i = 0;
for (; i < 3;) { // $ bound="i in [0..3]"
i += 1; // $ bound="i in [0..2]"
}
result += i; // $ bound="result in [0..9]" bound="i = 3"
}
return result; // $ MISSING:bound="result = 12"
}
public int emptyForLoop() {
int result = 0;
for (int i = 0; i < 0; // $ bound="i = 0"
i++) { // $ bound="i in [0..-1]"
result = i; // $ bound="i in [0..-1]"
}
return result; // $ bound="result = 0"
}
public int noLoop() {
int result = 0;
result += 1; // $ bound="result = 0"
return result; // $ bound="result = 1"
}
public int foreachLoop() {
int result = 0;
for (int i : new int[] {1, 2, 3, 4, 5}) {
result = i;
}
return result;
}
public int emptyForeachLoop() {
int result = 0;
for (int i : new int[] {}) {
result = i;
}
return result;
}
public int whileLoop() {
int result = 100;
while (result > 5) { // $ bound="result in [4..100]"
result = result - 2; // $ bound="result in [6..100]"
}
return result; // $ bound="result = 4"
}
public int oddWhileLoop() {
int result = 101;
while (result > 5) { // $ bound="result in [5..101]"
result = result - 2; // $ bound="result in [7..101]"
}
return result; // $ bound="result = 5"
}
static void arrayLength(int[] arr) {
bound(arr.length);
for (int i = 0;
i < arr.length;
i++) { // $ bound="i <= arr.length - 1"
arr[i]++; // $ bound="i <= arr.length - 1"
}
}
static int varBound(int b) {
bound(b);
int result = 0;
for (int i = 0;
i < b;
i++) { // $ bound="i <= b - 1"
result = i; // $ bound="i <= b - 1"
}
return result; // We cannot conclude anything here, since we do not know that b > 0
}
static int varBoundPositiveGuard(int b) {
bound(b);
if (b > 0) {
int result = 0;
for (int i = 0;
i < b;
i++) { // $ bound="i <= b - 1"
result = i; // $ bound="i <= b - 1"
}
return result; // $ MISSING: bound="result <= b - 1"
} else {
return 0;
}
}
static int varBoundPositiveGuardEarlyReturn(int b) {
bound(b);
if (b <= 0) return 0;
int result = 0;
for (int i = 0;
i < b;
i++) { // $ bound="i <= b - 1"
result = i; // $ bound="i <= b - 1"
}
return result; // $ MISSING: bound="result <= b - 1"
}
static int varBoundPositiveAssert(int b) {
bound(b);
assert b > 0;
int result = 0;
for (int i = 0;
i < b;
i++) { // $ bound="i <= b - 1"
result = i; // $ bound="i <= b - 1"
}
return result; // $ MISSING: bound="result <= b - 1"
}
}

View File

@@ -0,0 +1,71 @@
/**
* Inline range analysis tests for Java.
* See `shared/util/codeql/dataflow/test/InlineFlowTest.qll`
*/
import java
import semmle.code.java.dataflow.RangeAnalysis
private import TestUtilities.InlineExpectationsTest as IET
module RangeTest implements IET::TestSig {
string getARelevantTag() { result = "bound" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "bound" and
(
// simple integer bounds (`ZeroBound`s)
exists(Expr e, int lower, int upper |
constrained(e, lower, upper) and
e instanceof VarRead and
e.getCompilationUnit().fromSource()
|
location = e.getLocation() and
element = e.toString() and
if lower = upper
then value = "\"" + e.toString() + " = " + lower.toString() + "\""
else
value = "\"" + e.toString() + " in [" + lower.toString() + ".." + upper.toString() + "]\""
)
or
// advanced bounds
exists(Expr e, int delta, string deltaStr, boolean upper, string cmp, Expr boundExpr |
annotatedBound(e, _, boundExpr, delta, upper) and
e instanceof VarRead and
e.getCompilationUnit().fromSource() and
(
if delta = 0
then deltaStr = ""
else
if delta > 0
then deltaStr = " + " + delta.toString()
else deltaStr = " - " + delta.abs().toString()
) and
if upper = true then cmp = "<=" else cmp = ">="
|
location = e.getLocation() and
element = e.toString() and
value = "\"" + e.toString() + " " + cmp + " " + boundExpr.toString() + deltaStr + "\""
)
)
}
private predicate constrained(Expr e, int lower, int upper) {
bounded(e, any(ZeroBound z), lower, false, _) and
bounded(e, any(ZeroBound z), upper, true, _)
}
private predicate annotatedBound(Expr e, Bound b, Expr boundExpr, int delta, boolean upper) {
bounded(e, b, delta, upper, _) and
// the expression for the bound is explicitly requested as being annotated
// via a call such as
// ```java
// bound(expr);
// ```
boundExpr = b.getExpr() and
exists(Call c | c.getCallee().getName() = "bound" and c.getArgument(0) = boundExpr) and
// non-trivial bound
not e = b.getExpr()
}
}
import IET::MakeTest<RangeTest>

View File

@@ -0,0 +1,35 @@
import java.util.*;
public class A {
private static final Set<String> SEPARATORS =
Collections.unmodifiableSet(
new HashSet<>(Arrays.asList("\t", "\n", ";")));
public static void sink(String s) { }
private void checkSeparator(String separator) {
if (SEPARATORS.contains(separator)) {
sink(separator);
}
}
public static final String URI1 = "yarn.io/gpu";
public static final String URI2 = "yarn.io/fpga";
public static final Set<String> SCHEMAS = Set.of(URI1, URI2, "s3a", "wasb");
private void checkSchema(String schema) {
if (SCHEMAS.contains(schema)) {
sink(schema);
}
}
private void testAdd(String inp) {
Set<String> s = new HashSet<>();
s.add("AA");
s.add("BB");
if (s.contains(inp.toUpperCase())) {
sink(inp);
}
}
}

View File

@@ -0,0 +1 @@
| Type A uses out-of-scope type variable E. Note the Java extractor is known to sometimes do this; the Kotlin extractor should not. |

View File

@@ -0,0 +1,3 @@
| A.java:12:12:12:20 | separator |
| A.java:23:12:23:17 | schema |
| A.java:32:12:32:14 | inp |

View File

@@ -0,0 +1,5 @@
import java
import semmle.code.java.dataflow.FlowSteps
from DefaultTaintSanitizer e
select e

View File

@@ -0,0 +1,306 @@
// Test cases for CWE-089 (SQL injection and Java Persistence query injection)
// http://cwe.mitre.org/data/definitions/89.html
package test.cwe089.semmle.tests;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
class AllowListSanitizerWithJavaUtilList {
public static Connection connection;
public static final List<String> goodAllowList1 = List.of("allowed1", "allowed2", "allowed3");
public static final List<String> goodAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1"));
public static final List<String> goodAllowList3;
public static final List<String> goodAllowList4;
public static final List<String> goodAllowList5;
public static final List<String> badAllowList1 = List.of("allowed1", "allowed2", getNonConstantString());
public static final List<String> badAllowList2 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString()));
public static final List<String> badAllowList3;
public static final List<String> badAllowList4;
public static List<String> badAllowList6 = List.of("allowed1", "allowed2", "allowed3");
public final List<String> goodAllowList7 = List.of("allowed1", "allowed2", "allowed3");
static {
goodAllowList3 = List.of("allowed1", "allowed2", "allowed3");
goodAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2"));
badAllowList3 = List.of(getNonConstantString(), "allowed2", "allowed3");
badAllowList4 = Collections.unmodifiableList(Arrays.asList("allowed1", getNonConstantString()));
goodAllowList5 = new ArrayList<String>();
goodAllowList5.add("allowed1");
goodAllowList5.add("allowed2");
goodAllowList5.add("allowed3");
}
public static String getNonConstantString() {
return String.valueOf(System.currentTimeMillis());
}
public static void main(String[] args) throws IOException, SQLException {
badAllowList6 = List.of("allowed1", getNonConstantString(), "allowed3");
testStaticFields(args);
testLocal(args);
var x = new AllowListSanitizerWithJavaUtilList();
x.testNonStaticFields(args);
testMultipleSources(args);
testEscape(args);
}
private static void testStaticFields(String[] args) throws IOException, SQLException {
String tainted = args[1];
// GOOD: an allowlist is used with constant strings
if(goodAllowList1.contains(tainted.toLowerCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList2.contains(tainted.toUpperCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList3.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList4.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList1.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList2.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList3.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList4.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList5.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: the allowlist is in a non-final field
if(badAllowList6.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
private void testNonStaticFields(String[] args) throws IOException, SQLException {
String tainted = args[0];
// GOOD: the allowlist is in a non-static field
if(goodAllowList7.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
private static void testLocal(String[] args) throws IOException, SQLException {
String tainted = args[1];
// GOOD: an allowlist is used with constant strings
{
List<String> allowlist = List.of("allowed1", "allowed2", "allowed3");
if(allowlist.contains(tainted.toLowerCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
List<String> allowlist = List.of("allowed1", "allowed2", args[2]);
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant strings
{
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
List<String> allowlist = List.of(allowedArray);
if(allowlist.contains(tainted.toUpperCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
String[] allowedArray = {"allowed1", "allowed2", args[2]};
List<String> allowlist = List.of(allowedArray);
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant strings
{
List<String> allowlist = Collections.unmodifiableList(Arrays.asList("allowed1"));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
List<String> allowlist = Collections.unmodifiableList(Arrays.asList("allowed1", "allowed2", args[2]));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant strings
{
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
List<String> allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
String[] allowedArray = {"allowed1", "allowed2", args[2]};
List<String> allowlist = Collections.unmodifiableList(Arrays.asList(allowedArray));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant string
{
List<String> allowlist = new ArrayList<String>();
allowlist.add("allowed1");
allowlist.add("allowed2");
allowlist.add("allowed3");
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
List<String> allowlist = new ArrayList<String>();
allowlist.add("allowed1");
allowlist.add(getNonConstantString());
allowlist.add("allowed3");
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but it contains a non-compile-time constant element
{
List<String> allowlist = new ArrayList<String>();
allowlist.add("allowed1");
addNonConstantStringDirectly(allowlist);
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
}
private static void testMultipleSources(String[] args) throws IOException, SQLException {
String tainted = args[1];
boolean b = args[2] == "True";
{
// BAD: an allowlist is used which might contain constant strings
List<String> allowlist = new ArrayList<String>();
allowlist.add("allowed1");
if (b) {
allowlist.add(getNonConstantString());
}
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
{
// BAD: an allowlist is used which might contain constant strings
List<String> allowlist = b ? goodAllowList1 : badAllowList1;
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
{
// BAD: an allowlist is used which might contain constant strings
List<String> allowlist = b ? goodAllowList1 : List.of("allowed1", "allowed2", args[2]);;
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
}
private static void testEscape(String[] args) throws IOException, SQLException {
String tainted = args[1];
boolean b = args[2] == "True";
{
// BAD: an allowlist is used which contains constant strings
List<String> allowlist = new ArrayList<String>();
addNonConstantStringViaLambda(e -> allowlist.add(e));
if(allowlist.contains(tainted)){ // missing result
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
}
private static void addNonConstantStringDirectly(List<String> list) {
list.add(getNonConstantString());
}
private static void addNonConstantStringViaLambda(Consumer<String> adder) {
adder.accept(getNonConstantString());
}
}

View File

@@ -0,0 +1,305 @@
// Test cases for CWE-089 (SQL injection and Java Persistence query injection)
// http://cwe.mitre.org/data/definitions/89.html
package test.cwe089.semmle.tests;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.function.Consumer;
class AllowListSanitizerWithJavaUtilSet {
public static Connection connection;
public static final Set<String> goodAllowList1 = Set.of("allowed1", "allowed2", "allowed3");
public static final Set<String> goodAllowList2 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1","allowed2")));
public static final Set<String> goodAllowList3;
public static final Set<String> goodAllowList4;
public static final Set<String> goodAllowList5;
public static final Set<String> badAllowList1 = Set.of("allowed1", "allowed2", getNonConstantString());
public static final Set<String> badAllowList2 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1", getNonConstantString())));
public static final Set<String> badAllowList3;
public static final Set<String> badAllowList4;
public static Set<String> badAllowList6 = Set.of("allowed1", "allowed2", "allowed3");
public final Set<String> goodAllowList7 = Set.of("allowed1", "allowed2", "allowed3");
static {
goodAllowList3 = Set.of("allowed1", "allowed2", "allowed3");
goodAllowList4 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1", "allowed2")));
badAllowList3 = Set.of(getNonConstantString(), "allowed2", "allowed3");
badAllowList4 = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("allowed1", getNonConstantString())));
goodAllowList5 = new HashSet<String>();
goodAllowList5.add("allowed1");
goodAllowList5.add("allowed2");
goodAllowList5.add("allowed3");
}
public static String getNonConstantString() {
return String.valueOf(System.currentTimeMillis());
}
public static void main(String[] args) throws IOException, SQLException {
badAllowList6 = Set.of("allowed1", getNonConstantString(), "allowed3");
testStaticFields(args);
testLocal(args);
var x = new AllowListSanitizerWithJavaUtilSet();
x.testNonStaticFields(args);
testMultipleSources(args);
testEscape(args);
}
private static void testStaticFields(String[] args) throws IOException, SQLException {
String tainted = args[1];
// GOOD: an allowlist is used with constant strings
if(goodAllowList1.contains(tainted.toLowerCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList2.contains(tainted.toUpperCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList3.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList4.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList1.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList2.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList3.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: an allowlist is used with constant strings
if(badAllowList4.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// GOOD: an allowlist is used with constant strings
if(goodAllowList5.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
// BAD: the allowlist is in a non-final field
if(badAllowList6.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
private void testNonStaticFields(String[] args) throws IOException, SQLException {
String tainted = args[1];
// GOOD: the allowlist is in a non-static field
if(goodAllowList7.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
private static void testLocal(String[] args) throws IOException, SQLException {
String tainted = args[1];
// GOOD: an allowlist is used with constant strings
{
Set<String> allowlist = Set.of("allowed1", "allowed2", "allowed3");
if(allowlist.contains(tainted.toLowerCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
Set<String> allowlist = Set.of("allowed1", "allowed2", args[2]);
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant strings
{
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
Set<String> allowlist = Set.of(allowedArray);
if(allowlist.contains(tainted.toUpperCase())){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
String[] allowedArray = {"allowed1", "allowed2", args[2]};
Set<String> allowlist = Set.of(allowedArray);
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant strings
{
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1")));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("allowed1", "allowed2", args[2])));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant strings
{
String[] allowedArray = {"allowed1", "allowed2", "allowed3"};
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray)));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
String[] allowedArray = {"allowed1", "allowed2", args[2]};
Set<String> allowlist = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(allowedArray)));
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// GOOD: an allowlist is used with constant string
{
Set<String> allowlist = new HashSet<String>();
allowlist.add("allowed1");
allowlist.add("allowed2");
allowlist.add("allowed3");
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but one of the entries is not a compile-time constant
{
Set<String> allowlist = new HashSet<String>();
allowlist.add("allowed1");
allowlist.add(getNonConstantString());
allowlist.add("allowed3");
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
// BAD: an allowlist is used but it contains a non-compile-time constant element
{
Set<String> allowlist = new HashSet<String>();
allowlist.add("allowed1");
addNonConstantStringDirectly(allowlist);
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
}
private static void testMultipleSources(String[] args) throws IOException, SQLException {
String tainted = args[1];
boolean b = args[2] == "True";
{
// BAD: an allowlist is used which might contain constant strings
Set<String> allowlist = new HashSet<String>();
allowlist.add("allowed1");
if (b) {
allowlist.add(getNonConstantString());
}
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
{
// BAD: an allowlist is used which might contain constant strings
Set<String> allowlist = b ? goodAllowList1 : badAllowList1;
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
{
// BAD: an allowlist is used which might contain constant strings
Set<String> allowlist = b ? goodAllowList1 : Set.of("allowed1", "allowed2", args[2]);;
if(allowlist.contains(tainted)){
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
}
private static void testEscape(String[] args) throws IOException, SQLException {
String tainted = args[1];
boolean b = args[2] == "True";
{
// BAD: an allowlist is used which contains constant strings
Set<String> allowlist = new HashSet<String>();
addNonConstantStringViaLambda(e -> allowlist.add(e));
if(allowlist.contains(tainted)){ // missing result
String query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='"
+ tainted + "' ORDER BY PRICE";
ResultSet results = connection.createStatement().executeQuery(query);
}
}
}
private static void addNonConstantStringDirectly(Set<String> set) {
set.add(getNonConstantString());
}
private static void addNonConstantStringViaLambda(Consumer<String> adder) {
adder.accept(getNonConstantString());
}
}

View File

@@ -0,0 +1 @@
| Type AllowListSanitizerWithJavaUtilSet uses out-of-scope type variable E. Note the Java extractor is known to sometimes do this; the Kotlin extractor should not. |

View File

@@ -1,3 +1,55 @@
| AllowListSanitizerWithJavaUtilList.java:64:66:64:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:63:8:63:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:70:66:70:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:69:8:69:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:76:66:76:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:75:8:75:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:82:66:82:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:81:8:81:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:87:8:87:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:93:8:93:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:99:8:99:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:105:8:105:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:112:66:112:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:111:8:111:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:117:8:117:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:128:66:128:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:127:8:127:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:140:67:140:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:139:9:139:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:148:9:148:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:159:67:159:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:158:9:158:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:168:9:168:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:178:67:178:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:177:9:177:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:186:9:186:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:197:67:197:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:196:9:196:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:206:9:206:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:219:67:219:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:218:9:218:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:230:9:230:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:241:9:241:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:259:9:259:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:268:9:268:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:277:9:277:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilList.java:292:9:292:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:63:66:63:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:62:8:62:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:69:66:69:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:68:8:68:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:75:66:75:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:74:8:74:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:81:66:81:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:80:8:80:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:86:8:86:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:92:8:92:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:98:8:98:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:104:8:104:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:111:66:111:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:110:8:110:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:116:8:116:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:127:66:127:70 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:126:8:126:14 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:139:67:139:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:138:9:138:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:147:9:147:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:158:67:158:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:157:9:157:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:167:9:167:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:177:67:177:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:176:9:176:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:185:9:185:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:196:67:196:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:195:9:195:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:205:9:205:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:218:67:218:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:217:9:217:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:229:9:229:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:240:9:240:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:258:9:258:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:267:9:267:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:276:9:276:15 | tainted | this expression |
| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | Query built by concatenation with $@, which may be untrusted. | AllowListSanitizerWithJavaUtilSet.java:291:9:291:15 | tainted | this expression |
| Test.java:36:47:36:52 | query1 | Query built by concatenation with $@, which may be untrusted. | Test.java:35:8:35:15 | category | this expression |
| Test.java:42:57:42:62 | query2 | Query built by concatenation with $@, which may be untrusted. | Test.java:41:51:41:52 | id | this expression |
| Test.java:50:62:50:67 | query3 | Query built by concatenation with $@, which may be untrusted. | Test.java:49:8:49:15 | category | this expression |

View File

@@ -1,4 +1,34 @@
#select
| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | This query depends on a $@. | AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args | user-provided value |
| Mongo.java:17:45:17:67 | parse(...) | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:45:17:67 | parse(...) | This query depends on a $@. | Mongo.java:10:29:10:41 | args | user-provided value |
| Mongo.java:21:49:21:52 | json | Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | This query depends on a $@. | Mongo.java:10:29:10:41 | args | user-provided value |
| Test.java:36:47:36:52 | query1 | Test.java:227:26:227:38 | args : String[] | Test.java:36:47:36:52 | query1 | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value |
@@ -10,6 +40,52 @@
| Test.java:209:47:209:68 | queryWithUserTableName | Test.java:227:26:227:38 | args : String[] | Test.java:209:47:209:68 | queryWithUserTableName | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value |
| Test.java:221:81:221:111 | ... + ... | Test.java:227:26:227:38 | args : String[] | Test.java:221:81:221:111 | ... + ... | This query depends on a $@. | Test.java:227:26:227:38 | args | user-provided value |
edges
| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | provenance | |
| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | provenance | Sink:MaD:4 |
| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | provenance | Sink:MaD:4 |
| Mongo.java:10:29:10:41 | args : String[] | Mongo.java:17:56:17:66 | stringQuery : String | provenance | |
| Mongo.java:10:29:10:41 | args : String[] | Mongo.java:21:49:21:52 | json | provenance | |
| Mongo.java:17:56:17:66 | stringQuery : String | Mongo.java:17:45:17:67 | parse(...) | provenance | Config |
@@ -40,6 +116,54 @@ models
| 6 | Summary: java.lang; AbstractStringBuilder; true; append; ; ; Argument[0]; Argument[this]; taint; manual |
| 7 | Summary: java.lang; CharSequence; true; toString; ; ; Argument[this]; ReturnValue; taint; manual |
nodes
| AllowListSanitizerWithJavaUtilList.java:48:26:48:38 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:50:20:50:23 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:51:13:51:16 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:54:23:54:26 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:55:14:55:17 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:58:39:58:51 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:88:66:88:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:94:66:94:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:100:66:100:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:106:66:106:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:118:66:118:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:132:32:132:44 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:149:67:149:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:169:67:169:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:187:67:187:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:207:67:207:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:231:67:231:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:242:67:242:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:247:42:247:54 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:260:67:260:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:269:67:269:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:278:67:278:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilList.java:283:33:283:45 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilList.java:293:67:293:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:47:26:47:38 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:49:20:49:23 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:50:13:50:16 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:53:23:53:26 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:54:14:54:17 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:57:39:57:51 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:87:66:87:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:93:66:93:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:99:66:99:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:105:66:105:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:117:66:117:70 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:131:32:131:44 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:148:67:148:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:168:67:168:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:186:67:186:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:206:67:206:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:230:67:230:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:241:67:241:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:246:42:246:54 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:259:67:259:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:268:67:268:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:277:67:277:71 | query | semmle.label | query |
| AllowListSanitizerWithJavaUtilSet.java:282:33:282:45 | args : String[] | semmle.label | args : String[] |
| AllowListSanitizerWithJavaUtilSet.java:292:67:292:71 | query | semmle.label | query |
| Mongo.java:10:29:10:41 | args : String[] | semmle.label | args : String[] |
| Mongo.java:17:45:17:67 | parse(...) | semmle.label | parse(...) |
| Mongo.java:17:56:17:66 | stringQuery : String | semmle.label | stringQuery : String |

View File

@@ -19,7 +19,7 @@ public class WeakHashing {
// BAD: Using a strong hashing algorithm but with a weak default
MessageDigest bad3 = MessageDigest.getInstance(props.getProperty("hashAlg2", "MD5"));
// GOOD: Using a strong hashing algorithm
MessageDigest ok = MessageDigest.getInstance(props.getProperty("hashAlg2"));
@@ -28,5 +28,8 @@ public class WeakHashing {
// GOOD: Using a strong hashing algorithm
MessageDigest ok3 = MessageDigest.getInstance("SHA3-512");
// GOOD: Using a strong hashing algorithm
MessageDigest ok4 = MessageDigest.getInstance("SHA384");
}
}

View File

@@ -0,0 +1,55 @@
#!/usr/bin/env python3
# Creates a change note and opens it in VSCode for editing.
# Expects to receive the following arguments:
# - What language the change note is for
# - Whether it's a query or library change (the string `src` or `lib`)
# - The name of the change note (in kebab-case)
# - The category of the change.
# The change note will be created in the `{language}/ql/{subdir}/change-notes` directory, where `subdir` is either `src` or `lib`.
# The format of the change note filename is `{current_date}-{change_note_name}.md` with the date in
# the format `YYYY-MM-DD`.
import sys
import os
# Read the given arguments
language = sys.argv[1]
subdir = sys.argv[2]
change_note_name = sys.argv[3]
change_category = sys.argv[4]
# Find the root of the repository. The current script should be located in `misc/scripts`.
root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Go to the repo root
os.chdir(root)
output_dir = f"{language}/ql/{subdir}/change-notes"
# Abort if the output directory doesn't exist
if not os.path.exists(output_dir):
print(f"Output directory {output_dir} does not exist")
sys.exit(1)
# Get the current date
import datetime
current_date = datetime.datetime.now().strftime("%Y-%m-%d")
# Create the change note file
change_note_file = f"{output_dir}/{current_date}-{change_note_name}.md"
change_note = f"""
---
category: {change_category}
---
* """.lstrip()
with open(change_note_file, "w") as f:
f.write(change_note)
# Open the change note file in VSCode, reusing the existing window if possible
os.system(f"code -r {change_note_file}")

View File

@@ -14,24 +14,29 @@ fn project_root() -> PathBuf {
PathBuf::from(dir).parent().unwrap().to_owned()
}
fn class_name(type_name: &String) -> String {
match type_name.as_str() {
"BinExpr" => "BinaryExpr".to_owned(),
"ElseBranch" => "Expr".to_owned(),
"Fn" => "Function".to_owned(),
"Literal" => "LiteralExpr".to_owned(),
"Type" => "TypeRef".to_owned(),
_ => type_name.to_owned(),
}
fn class_name(type_name: &str) -> String {
let name = match type_name {
"BinExpr" => "BinaryExpr",
"ElseBranch" => "Expr",
"Fn" => "Function",
"Literal" => "LiteralExpr",
"Type" => "TypeRef",
_ => type_name,
};
name.to_owned()
}
fn property_name(type_name: &String, field_name: &String) -> String {
match (type_name.as_str(), field_name.as_str()) {
("Path", "segment") => "part".to_owned(),
(_, "then_branch") => "then".to_owned(),
(_, "else_branch") => "else_".to_owned(),
_ => field_name.to_owned(),
}
fn property_name(type_name: &str, field_name: &str) -> String {
let name = match (type_name, field_name) {
("CallExpr", "expr") => "function",
("LetExpr", "expr") => "scrutinee",
("MatchExpr", "expr") => "scrutinee",
("Path", "segment") => "part",
(_, "then_branch") => "then",
(_, "else_branch") => "else_",
_ => field_name,
};
name.to_owned()
}
fn to_lower_snake_case(s: &str) -> String {
@@ -61,7 +66,7 @@ fn write_schema(
for node in &grammar.enums {
let super_classses = if let Some(cls) = super_types.get(&node.name) {
let super_classes: Vec<String> = cls.iter().map(class_name).collect();
let super_classes: Vec<String> = cls.iter().map(|s| class_name(s)).collect();
super_classes.join(",")
} else {
"AstNode".to_owned()
@@ -76,7 +81,7 @@ fn write_schema(
}
for node in &grammar.nodes {
let super_classses = if let Some(cls) = super_types.get(&node.name) {
let super_classes: Vec<String> = cls.iter().map(class_name).collect();
let super_classes: Vec<String> = cls.iter().map(|s| class_name(s)).collect();
super_classes.join(",")
} else {
"AstNode".to_owned()

View File

@@ -1,2 +1,2 @@
mod.rs 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7 4bcb9def847469aae9d8649461546b7c21ec97cf6e63d3cf394e339915ce65d7
top.rs bc12e91ac724df9ca0c5d438067762d7e540bc20bde01c053af048b2a8391e2e bc12e91ac724df9ca0c5d438067762d7e540bc20bde01c053af048b2a8391e2e
top.rs 272ecf2f56f35211d2449dbf55b1907d8414a8e4cceded03fd12f6f599852c73 272ecf2f56f35211d2449dbf55b1907d8414a8e4cceded03fd12f6f599852c73

View File

@@ -4942,7 +4942,7 @@ impl From<trap::Label<LabelableExpr>> for trap::Label<Locatable> {
pub struct LetExpr {
pub id: trap::TrapId<LetExpr>,
pub attrs: Vec<trap::Label<Attr>>,
pub expr: Option<trap::Label<Expr>>,
pub scrutinee: Option<trap::Label<Expr>>,
pub pat: Option<trap::Label<Pat>>,
}
@@ -4956,8 +4956,8 @@ impl trap::TrapEntry for LetExpr {
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("let_expr_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.expr {
out.add_tuple("let_expr_exprs", vec![id.into(), v.into()]);
if let Some(v) = self.scrutinee {
out.add_tuple("let_expr_scrutinees", vec![id.into(), v.into()]);
}
if let Some(v) = self.pat {
out.add_tuple("let_expr_pats", vec![id.into(), v.into()]);
@@ -5509,7 +5509,7 @@ impl From<trap::Label<MacroType>> for trap::Label<TypeRef> {
pub struct MatchExpr {
pub id: trap::TrapId<MatchExpr>,
pub attrs: Vec<trap::Label<Attr>>,
pub expr: Option<trap::Label<Expr>>,
pub scrutinee: Option<trap::Label<Expr>>,
pub match_arm_list: Option<trap::Label<MatchArmList>>,
}
@@ -5523,8 +5523,8 @@ impl trap::TrapEntry for MatchExpr {
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("match_expr_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.expr {
out.add_tuple("match_expr_exprs", vec![id.into(), v.into()]);
if let Some(v) = self.scrutinee {
out.add_tuple("match_expr_scrutinees", vec![id.into(), v.into()]);
}
if let Some(v) = self.match_arm_list {
out.add_tuple("match_expr_match_arm_lists", vec![id.into(), v.into()]);
@@ -8120,7 +8120,7 @@ pub struct CallExpr {
pub id: trap::TrapId<CallExpr>,
pub arg_list: Option<trap::Label<ArgList>>,
pub attrs: Vec<trap::Label<Attr>>,
pub expr: Option<trap::Label<Expr>>,
pub function: Option<trap::Label<Expr>>,
}
impl trap::TrapEntry for CallExpr {
@@ -8136,8 +8136,8 @@ impl trap::TrapEntry for CallExpr {
for (i, v) in self.attrs.into_iter().enumerate() {
out.add_tuple("call_expr_base_attrs", vec![id.into(), i.into(), v.into()]);
}
if let Some(v) = self.expr {
out.add_tuple("call_expr_exprs", vec![id.into(), v.into()]);
if let Some(v) = self.function {
out.add_tuple("call_expr_functions", vec![id.into(), v.into()]);
}
}
}

View File

@@ -397,12 +397,12 @@ impl Translator<'_> {
pub(crate) fn emit_call_expr(&mut self, node: ast::CallExpr) -> Label<generated::CallExpr> {
let arg_list = node.arg_list().map(|x| self.emit_arg_list(x));
let attrs = node.attrs().map(|x| self.emit_attr(x)).collect();
let expr = node.expr().map(|x| self.emit_expr(x));
let function = node.expr().map(|x| self.emit_expr(x));
let label = self.trap.emit(generated::CallExpr {
id: TrapId::Star,
arg_list,
attrs,
expr,
function,
});
self.emit_location(label, &node);
emit_detached!(CallExpr, self, node, label);
@@ -958,12 +958,12 @@ impl Translator<'_> {
pub(crate) fn emit_let_expr(&mut self, node: ast::LetExpr) -> Label<generated::LetExpr> {
let attrs = node.attrs().map(|x| self.emit_attr(x)).collect();
let expr = node.expr().map(|x| self.emit_expr(x));
let scrutinee = node.expr().map(|x| self.emit_expr(x));
let pat = node.pat().map(|x| self.emit_pat(x));
let label = self.trap.emit(generated::LetExpr {
id: TrapId::Star,
attrs,
expr,
scrutinee,
pat,
});
self.emit_location(label, &node);
@@ -1224,12 +1224,12 @@ impl Translator<'_> {
pub(crate) fn emit_match_expr(&mut self, node: ast::MatchExpr) -> Label<generated::MatchExpr> {
let attrs = node.attrs().map(|x| self.emit_attr(x)).collect();
let expr = node.expr().map(|x| self.emit_expr(x));
let scrutinee = node.expr().map(|x| self.emit_expr(x));
let match_arm_list = node.match_arm_list().map(|x| self.emit_match_arm_list(x));
let label = self.trap.emit(generated::MatchExpr {
id: TrapId::Star,
attrs,
expr,
scrutinee,
match_arm_list,
});
self.emit_location(label, &node);

View File

@@ -1,4 +1,4 @@
lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll 5e6ce2581b312d74ac8ffde44941b77f643025a7ff2c47799b3834596a513fa4 24dc5d28eb4754f968cf850294ac32057a2a97cf5156a3e90e0924c28e50e810
lib/codeql/rust/controlflow/internal/generated/CfgNodes.qll a8e083c7d8c4dea6459c5e128e2123f5cf8fd14c076f2256ebda508c13d553cd 16fcc0d34097b0b37a0041281515ca028d2702eec6d9c1d03c39a1158883bdef
lib/codeql/rust/elements/Abi.qll 4c973d28b6d628f5959d1f1cc793704572fd0acaae9a97dfce82ff9d73f73476 250f68350180af080f904cd34cb2af481c5c688dc93edf7365fd0ae99855e893
lib/codeql/rust/elements/Addressable.qll 13011bfd2e1556694c3d440cc34af8527da4df49ad92b62f2939d3699ff2cea5 ddb25935f7553a1a384b1abe2e4b4fa90ab50b952dadec32fd867afcb054f4be
lib/codeql/rust/elements/ArgList.qll 661f5100f5d3ef8351452d9058b663a2a5c720eea8cf11bedd628969741486a2 28e424aac01a90fb58cd6f9f83c7e4cf379eea39e636bc0ba07efc818be71c71
@@ -298,7 +298,6 @@ lib/codeql/rust/elements/internal/OrPatConstructor.qll 4ef583e07298487c0c4c6d7c7
lib/codeql/rust/elements/internal/ParamBaseImpl.qll fe11999c728c443c46c992e9bed7a2b3e23afa16ae99592e70054bc57ae371b8 df86fdb23266bdfb9ed8a8f02558a760b67f173943b9d075b081229eb5844f66
lib/codeql/rust/elements/internal/ParamConstructor.qll b98a2d8969f289fdcc8c0fb11cbd19a3b0c71be038c4a74f5988295a2bae52f0 77d81b31064167945b79b19d9697b57ca24462c3a7cc19e462c4693ce87db532
lib/codeql/rust/elements/internal/ParamListConstructor.qll 3123142ab3cab46fb53d7f3eff6ba2d3ff7a45b78839a53dc1979a9c6a54920e 165f3d777ea257cfcf142cc4ba9a0ebcd1902eb99842b8a6657c87087f3df6fe
lib/codeql/rust/elements/internal/ParamListImpl.qll 0ed6e9affe1dc0144641502292c2ddd51958fe3d503419caf15198176e3a4174 92d053cc5fdf40a2d98acb665083b5da15403d7da205779a97a4ee66fac0add4
lib/codeql/rust/elements/internal/ParenExprConstructor.qll 104b67dc3fd53ab52e2a42ffde37f3a3a50647aa7bf35df9ba9528e9670da210 d1f5937756e87a477710c61698d141cdad0ccce8b07ecb51bab00330a1ca9835
lib/codeql/rust/elements/internal/ParenPatConstructor.qll 9aea3c3b677755177d85c63e20234c234f530a16db20ab699de05ca3f1b59787 29f24aed0d880629a53b30550467ade09a0a778dbf88891769c1e11b0b239f98
lib/codeql/rust/elements/internal/ParenTypeConstructor.qll d62e656a4a3c8ffd4eb87d49585a7a3bfb5dbe3826fbcbd11cb87b46f34c19ae febf6535965afa0f6eac4d2b08730f5a07bbb36a7434abe0a7663d7264961a3f
@@ -431,7 +430,7 @@ lib/codeql/rust/elements/internal/generated/BinaryExpr.qll 64e9bd9c571edd6e5f3e7
lib/codeql/rust/elements/internal/generated/BlockExpr.qll 5a5ddbe34bc478a7bd9b0d07d3b6f017c2d1f20581d859251a963314e6514d1f 9804c30b8b279038b864c52557535f854bd012bacdfe8e5840f1f777c74e52df
lib/codeql/rust/elements/internal/generated/BoxPat.qll ec946a3e671ab7417e04b0207967adad004df512c570c4f0780ca5816d12d75f b0e64860855c4e85914042b1a51034899ff7cd1b2c6857188de89310a2726ea3
lib/codeql/rust/elements/internal/generated/BreakExpr.qll 0f428a8b2f4209b134c2ffc3e1c93c30bc6b0e9c9172f140cefa88c1f77d8690 957b39f38ff6befe9061f55bc0b403c2f1c366dd0cf63b874bae6f8216576d76
lib/codeql/rust/elements/internal/generated/CallExpr.qll 23ee64e3bf643cd5e6ff705181d2bb31e1aeaffecb5bdce73836172dbf15f12f 34b280139b1f8f70d78e1432392f03c971be392e8cb68d014eb325d0c101bddd
lib/codeql/rust/elements/internal/generated/CallExpr.qll f1b8dae487077cc9d1dccf8c3cd61fd17afe860585f17ce8b860be4859be7ca4 6034fc03778e38802cdf3a6e460364b74e92912622581b31e6179951022bbbd6
lib/codeql/rust/elements/internal/generated/CallExprBase.qll cce796e36847249f416629bacf3ea146313084de3374587412e66c10d2917b83 c219aa2174321c161a4a742ca0605521687ca9a5ca32db453a5c62db6f7784cc
lib/codeql/rust/elements/internal/generated/Callable.qll b0502b5263b7bcd18e740f284f992c0e600e37d68556e3e0ba54a2ac42b94934 bda3e1eea11cacf5a9b932cd72efc2de6105103e8c575880fcd0cd89daadf068
lib/codeql/rust/elements/internal/generated/CastExpr.qll d6fbf02e9e202254666082a9116634d0eb933177866ac4c0a57b5e9c4bb4b383 477f67773492e3b82695461d56327c9db05a7d1a67e8d192406265f2ce369670
@@ -478,7 +477,7 @@ lib/codeql/rust/elements/internal/generated/ItemList.qll 73c8398a96d4caa47a2dc11
lib/codeql/rust/elements/internal/generated/Label.qll 6630fe16e9d2de6c759ff2684f5b9950bc8566a1525c835c131ebb26f3eea63e 671143775e811fd88ec90961837a6c0ee4db96e54f42efd80c5ae2571661f108
lib/codeql/rust/elements/internal/generated/LabelableExpr.qll 896fd165b438b60d7169e8f30fa2a94946490c4d284e1bbadfec4253b909ee6c 5c6b029ea0b22cf096df2b15fe6f9384ad3e65b50b253cae7f19a2e5ffb04a58
lib/codeql/rust/elements/internal/generated/LetElse.qll 7ca556118b5446bfc85abba8f0edd4970e029b30d414ea824a1b5f568310a76c a403540881336f9d0269cbcdb4b87107a17ab234a985247dc52a380f150a1641
lib/codeql/rust/elements/internal/generated/LetExpr.qll 9af0f89b294c8a0a751317e7074fe370339563d36c1df4911d1ea082a4df77fd 68272593d1feb88990bfbd0b8c222776f085e49694894384fc6d96e9464ba734
lib/codeql/rust/elements/internal/generated/LetExpr.qll 6f831be1d0f76258d5f74c847636e070a819dee5aa090be0c52a971f261eaff3 e85a48e7492862f738e184f5f1512c2d18d33a0cfb516e269334acf7448b508a
lib/codeql/rust/elements/internal/generated/LetStmt.qll aa1852db86ec29f857a90677f0c6b4a07f0fd965fc193d4141be95ce15862fca 40f32a37c0cc161b099fe0b4c7d713da928781d3e2c3de90db991df1d9062647
lib/codeql/rust/elements/internal/generated/Lifetime.qll 90d01c76188ce0c053122c62b41e47f27c4c7717ca5a4999a76797360043da0d 7b9feb202da5a06cd17f7770bb66742fd9e7cff0d410fefc7ffaafe710ac16d6
lib/codeql/rust/elements/internal/generated/LifetimeArg.qll 7c1a44e3d480e75142b171eb51382c9492d393043833c0ab4a4036eba19043b8 7d8273b62794268dab6938ba1e3a3560a80a2c49cd9a9717345785dacd311059
@@ -515,7 +514,7 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b
lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60
lib/codeql/rust/elements/internal/generated/ParenPat.qll ce24b8f8ecbf0f204af200317405724063887257460c80cf250c39b2fdf37185 e7c87d37e1a0ca7ea03840017e1aa9ddb7f927f1f3b6396c0305b46aeee33db6
lib/codeql/rust/elements/internal/generated/ParenType.qll 9cc954d73f8330dcac7b475f97748b63af5c8766dee9d2f2872c0a7e4c903537 c07534c8a9c683c4a9b11d490095647e420de0a0bfc23273eaf6f31b00244273
lib/codeql/rust/elements/internal/generated/ParentChild.qll 0ef5a17cc0d38e942e8a3dbe26b34befdea3ba23bc18cc2450e0ce0bd55e145d 0aa61484a16cf47dc3802a77f46b055394d38bf3736f0197115e3ff004115635
lib/codeql/rust/elements/internal/generated/ParentChild.qll db7a782f11a14305acc666c865118475e2d324d2bf5d4110b157e1d488b62b75 3b5d31528d0baa0ceee139097e93461d18503797a1507288dc43428f378500e2
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
lib/codeql/rust/elements/internal/generated/Path.qll 4c1c8e840ed57880e574142b081b11d7a7428a009f10e3aa8f4645e211f6b2e0 989668cf0f1bdee7557e2f97c01e41d2a56848227fed41477833f5fc1e1d35f6
lib/codeql/rust/elements/internal/generated/PathExpr.qll 2096e3c1db22ee488a761690adabfc9cfdea501c99f7c5d96c0019cb113fc506 54245ce0449c4e263173213df01e079d5168a758503a5dbd61b25ad35a311140
@@ -528,7 +527,7 @@ lib/codeql/rust/elements/internal/generated/PtrType.qll 40099c5a4041314b66932dfd
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590 ea294a3ba33fd1bc632046c4fedbcb84dcb961a8e4599969d65893b19d90e590
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
lib/codeql/rust/elements/internal/generated/RangePat.qll efd93730de217cf50dcba5875595263a5eadf9f7e4e1272401342a094d158614 229b251b3d118932e31e78ac4dfb75f48b766f240f20d436062785606d44467b
lib/codeql/rust/elements/internal/generated/Raw.qll 631450d9014ad3eb191007e2b0054162ca86aaccf9d5275be831ba762ee966a5 bc302f73decc7ceafbe285c32d74b5911830d2b3c95c7033507512de857feabb
lib/codeql/rust/elements/internal/generated/Raw.qll 7de290d66bd594f4c5b5a296502792e803e9f1084bb2616d9774196e33b16c87 28150fdd3cff3bb49b407f0c2119602be13e78cbb1f8fd749edd31f5d9772f7a
lib/codeql/rust/elements/internal/generated/RecordExpr.qll eb6cb662e463f9260efae1a6ce874fa781172063b916ef1963f861e9942d308d 1a21cbccc8f3799ff13281e822818ebfb21d81591720a427cac3625512cb9d40
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
@@ -635,10 +634,10 @@ test/extractor-tests/generated/BreakExpr/BreakExpr.ql cdde2855d98f658187c60b9edc
test/extractor-tests/generated/BreakExpr/BreakExpr_getAttr.ql c7690a9aab1923bf3c2fb06f0a1d441d480b3c91ee1df3a868bbbd96c4042053 c592dd077fb6e22b2d6ddcaec37da2c5a26ba92d84f5d1ae4c78a615b9013765
test/extractor-tests/generated/BreakExpr/BreakExpr_getExpr.ql 0358f4fe6a66da56177703cf0e991042729c5e34ae8b6dccbb827f95fe936c72 1cb2dd778c50e19fe04c5fdf3a08a502635ea8303e71ff38d03aa7dc53213986
test/extractor-tests/generated/BreakExpr/BreakExpr_getLifetime.ql ad83cc0db3c0f959fef6bb7ce0938d241a877e8cf84d15fb63879be2fe47238c 240b2fe2156b763d3a82fc64159615872db65b65ffb9ba2f3fd5d1ebd6c60f34
test/extractor-tests/generated/CallExpr/CallExpr.ql 69d88b3c799f6e81fe53fe04724ed6c1cbfbfcc21023dd62aed3a3f852c6a2aa 0caa94802919d30bf2749d8a1c58545163e2b1cad5490f19158b5e5063806443
test/extractor-tests/generated/CallExpr/CallExpr.ql ffb0cf1cb359a6dcbdf792a570c281e2d300779dca2dbc0f324990652adb972f 978a9e6c82758f9e8b334a682a02d6b893a6bf1db3cd85e9535839a9696b09b4
test/extractor-tests/generated/CallExpr/CallExpr_getArgList.ql b022e7b6b6db9932e787e37b7760c6a09c91140a0368940374a2c919688e0488 c20849c96b53c96f6f717efff5e8b4c0e900c0ef5d715cfbaf7101c7056ad8f4
test/extractor-tests/generated/CallExpr/CallExpr_getAttr.ql 1ace458070875b9ff2c671c2ee18392ea7bf6e51b68ee98d412c8606e8eb8d33 4c35da8255d2975cef4adee15623662441bb8f2e1d73582e4c193d1bc11cc1b5
test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql f680f04423ece282c459d5908e5aa0bc43ca072ff0e605587dfa94210da1d06d f8a709015b8317b8e2dcf3b3ee9370e2c3a655ef7e3c6034b1b90f4d75ebdda2
test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql 060a6c8b5b85c839b14fe96f9e50291a7a0e5662a945f4f337070f782ec76715 e9a1e44433936146d87be939aa160848b9a7d7333c36da601fb7d1a66d71eb59
test/extractor-tests/generated/CastExpr/CastExpr.ql 2ffb22ebc6e47953a49162488b3605d36b9d89330b1e71187066e7bbc40a22ad 7621a39d49f573b9862b9a4e1021d53205670ee59b49e4d81128637926f76485
test/extractor-tests/generated/CastExpr/CastExpr_getAttr.ql 5d5d98172e495cdb8b5cea9d6588c4c245107b441464e3ffd6c27668af11ab4e 5820bf083aaa4c3275004a2cd9eeecc4b45ab96916cbc0655a1b42611c540715
test/extractor-tests/generated/CastExpr/CastExpr_getExpr.ql c37186b8f3e3dab8ae28c0da7263ff7272c40501beb16736ec0fb8990d285e22 59d50d7349234afcf84986b7570db9dcd342e16812f7c46199d4736cdfa5462d
@@ -780,10 +779,10 @@ test/extractor-tests/generated/Label/Label.ql 6a92a27d615dd9c380cb9d889eecf827fc
test/extractor-tests/generated/Label/Label_getLifetime.ql 3d6ddc3b44182e6432e938d5c1c95e0281575e320d517e431f6bad7748efb93e 56d07e485cb5e4263443eb5a0d62d7d4456bb0c2748331b371e519bfe14d3b81
test/extractor-tests/generated/LetElse/LetElse.ql bdf2b17d5efe6b9cb5bb4fcfe854a5fcd72443d39ae1e7981d2a0459c481e394 a14a611d0783ae38d631600c2bde7409f4e739ba2f284314b90ec9a21c23ab3a
test/extractor-tests/generated/LetElse/LetElse_getBlockExpr.ql 32c21ad843884944738a735f01e272032a347d1860fa6d27d17652c549f941b0 2bfd8a5e3d42eb1c73eb679ada847dd29f2f0657a0ad8ef15da126e54fff5ef5
test/extractor-tests/generated/LetExpr/LetExpr.ql a25072a00cfe1242dc846b38199c000ed7217d33fdd50d2763237fdfda7b9449 8c9367af79d9fbc98ed2fe62450929fa876512f1c999615b5c1ecff082fdc7bc
test/extractor-tests/generated/LetExpr/LetExpr.ql c76a0c4aaa73f4064207dacc8d2c649d3a5f8046c0f6e1aae985d2402a342e73 c5abe3845d4975d05c98ee6496732da384cdaca60ed49235776338e6dbe80b3d
test/extractor-tests/generated/LetExpr/LetExpr_getAttr.ql 911b143afebaa0a487b13d533f089c5b0eaf336a44a4cab42147c284338484ba 625c91fb6d8c2e3a9f13e5679cc0cd29329c6c2b213d2e1191e23db2b65841dd
test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql ccabfaa15cfc8685e86cb950cb62b7f2fec278f28906ab34deb97b308f160cc4 e0574537d47a77f1be85090970f3e1263858174479002fd4de3f85b777ee4336
test/extractor-tests/generated/LetExpr/LetExpr_getPat.ql bc0363f77bc2ba583619ab7d309293ace0ed6a851bfb9b886f75729f96eb40a8 bc0cd9233b7904d8cc7f9021377120f5f4bcc5c7aa28b1b55f17bc738c434d78
test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql ee33d3bbaf0ee7cdf9bd7b800e9684b5ac7ce8cf1939378cd460cb0c5ea11742 5d69e727b3e9d1ab4ce9eef702a7b1911515469625056bce87fac1d27ba863e6
test/extractor-tests/generated/LetStmt/LetStmt.ql 02db64303bfe87a11a85663e4c79bdabd9ca13693f146c7923b47c4c92850fcc 9ec1326b8bc58b270b178a4c02621b1650d107de7c02a9408d97c59f0d8a6178
test/extractor-tests/generated/LetStmt/LetStmt_getAttr.ql 68f69c4c054514140c0f0833a170e9f3facf950bd7af663ac9019f6c88ba0ea7 ca54d25cc052289458c7e34e40f0304bca2c412cecfb407f31279262bd74c15a
test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.ql 6a5f0eed3ce3e8cbc57be6ec2b4eed732f00e084108d21a61d9ab28b65e494ca a48b426b97a6c347ad04fe2e592cd25b5c66b2a6a299cbf8c0da03e14304fd70

5
rust/ql/.gitattributes generated vendored
View File

@@ -300,7 +300,6 @@
/lib/codeql/rust/elements/internal/ParamBaseImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/ParamConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ParamListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ParamListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/ParenExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ParenPatConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ParenTypeConstructor.qll linguist-generated
@@ -640,7 +639,7 @@
/test/extractor-tests/generated/CallExpr/CallExpr.ql linguist-generated
/test/extractor-tests/generated/CallExpr/CallExpr_getArgList.ql linguist-generated
/test/extractor-tests/generated/CallExpr/CallExpr_getAttr.ql linguist-generated
/test/extractor-tests/generated/CallExpr/CallExpr_getExpr.ql linguist-generated
/test/extractor-tests/generated/CallExpr/CallExpr_getFunction.ql linguist-generated
/test/extractor-tests/generated/CastExpr/CastExpr.ql linguist-generated
/test/extractor-tests/generated/CastExpr/CastExpr_getAttr.ql linguist-generated
/test/extractor-tests/generated/CastExpr/CastExpr_getExpr.ql linguist-generated
@@ -784,8 +783,8 @@
/test/extractor-tests/generated/LetElse/LetElse_getBlockExpr.ql linguist-generated
/test/extractor-tests/generated/LetExpr/LetExpr.ql linguist-generated
/test/extractor-tests/generated/LetExpr/LetExpr_getAttr.ql linguist-generated
/test/extractor-tests/generated/LetExpr/LetExpr_getExpr.ql linguist-generated
/test/extractor-tests/generated/LetExpr/LetExpr_getPat.ql linguist-generated
/test/extractor-tests/generated/LetExpr/LetExpr_getScrutinee.ql linguist-generated
/test/extractor-tests/generated/LetStmt/LetStmt.ql linguist-generated
/test/extractor-tests/generated/LetStmt/LetStmt_getAttr.ql linguist-generated
/test/extractor-tests/generated/LetStmt/LetStmt_getInitializer.ql linguist-generated

View File

@@ -6,6 +6,7 @@
private import codeql.rust.dataflow.DataFlow
private import codeql.threatmodels.ThreatModels
private import codeql.rust.Frameworks
/**
* A data flow source for a specific threat-model.
@@ -46,6 +47,63 @@ class ActiveThreatModelSource extends ThreatModelSource {
ActiveThreatModelSource() { currentThreatModel(this.getThreatModel()) }
}
/**
* A data flow source corresponding to the program's command line arguments or path.
*/
final class CommandLineArgsSource = CommandLineArgsSource::Range;
/**
* Provides a class for modeling new sources for the program's command line arguments or path.
*/
module CommandLineArgsSource {
/**
* A data flow source corresponding to the program's command line arguments or path.
*/
abstract class Range extends ThreatModelSource::Range {
override string getThreatModel() { result = "commandargs" }
override string getSourceType() { result = "CommandLineArgs" }
}
}
/**
* A data flow source corresponding to the program's environment.
*/
final class EnvironmentSource = EnvironmentSource::Range;
/**
* Provides a class for modeling new sources for the program's environment.
*/
module EnvironmentSource {
/**
* A data flow source corresponding to the program's environment.
*/
abstract class Range extends ThreatModelSource::Range {
override string getThreatModel() { result = "environment" }
override string getSourceType() { result = "EnvironmentSource" }
}
}
/**
* A data flow source for remote (network) data.
*/
final class RemoteSource = RemoteSource::Range;
/**
* Provides a class for modeling new sources of remote (network) data.
*/
module RemoteSource {
/**
* A data flow source for remote (network) data.
*/
abstract class Range extends ThreatModelSource::Range {
override string getThreatModel() { result = "remote" }
override string getSourceType() { result = "RemoteSource" }
}
}
/**
* A data-flow node that constructs a SQL statement.
*

View File

@@ -0,0 +1,6 @@
/**
* This file imports all models of frameworks and libraries.
*/
private import codeql.rust.frameworks.Reqwest
private import codeql.rust.frameworks.stdlib.Env

View File

@@ -187,9 +187,37 @@ final class RecordExprCfgNode extends Nodes::RecordExprCfgNode {
RecordExprCfgNode() { node = this.getRecordExpr() }
/** Gets the `i`th record expression. */
ExprCfgNode getExpr(int i) {
any(ChildMapping mapping)
.hasCfgChild(node, node.getRecordExprFieldList().getField(i).getExpr(), this, result)
/** Gets the record expression for the field `field`. */
pragma[nomagic]
ExprCfgNode getFieldExpr(string field) {
exists(RecordExprField ref |
ref = node.getRecordExprFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result) and
field = ref.getNameRef().getText()
)
}
}
/**
* A record pattern. For example:
* ```rust
* match x {
* Foo { a: 1, b: 2 } => "ok",
* Foo { .. } => "fail",
* }
* ```
*/
final class RecordPatCfgNode extends Nodes::RecordPatCfgNode {
private RecordPatChildMapping node;
RecordPatCfgNode() { node = this.getRecordPat() }
/** Gets the record pattern for the field `field`. */
PatCfgNode getFieldPat(string field) {
exists(RecordPatField rpf |
rpf = node.getRecordPatFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, rpf.getPat(), this, result) and
field = rpf.getNameRef().getText()
)
}
}

View File

@@ -68,6 +68,12 @@ class RecordExprChildMapping extends ParentAstNode, RecordExpr {
}
}
class RecordPatChildMapping extends ParentAstNode, RecordPat {
override predicate relevantChild(AstNode child) {
child = this.getRecordPatFieldList().getAField().getPat()
}
}
class FormatArgsExprChildMapping extends ParentAstNode, CfgImpl::ExprTrees::FormatArgsExprTree {
override predicate relevantChild(AstNode child) { child = this.getChildNode(_) }
}

View File

@@ -313,7 +313,7 @@ module ExprTrees {
class CallExprTree extends StandardPostOrderTree instanceof CallExpr {
override AstNode getChildNode(int i) {
i = 0 and result = super.getExpr()
i = 0 and result = super.getFunction()
or
result = super.getArgList().getArg(i - 1)
}
@@ -410,7 +410,7 @@ module ExprTrees {
class LetExprTree extends StandardPreOrderTree, LetExpr {
override AstNode getChildNode(int i) {
i = 0 and
result = this.getExpr()
result = this.getScrutinee()
or
i = 1 and
result = this.getPat()

View File

@@ -570,7 +570,7 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
override predicate relevantChild(AstNode child) {
none()
or
child = this.getExpr()
child = this.getFunction()
}
}
@@ -592,16 +592,16 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
CallExpr getCallExpr() { result = node }
/**
* Gets the expression of this call expression, if it exists.
* Gets the function of this call expression, if it exists.
*/
ExprCfgNode getExpr() {
any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result)
ExprCfgNode getFunction() {
any(ChildMapping mapping).hasCfgChild(node, node.getFunction(), this, result)
}
/**
* Holds if `getExpr()` exists.
* Holds if `getFunction()` exists.
*/
predicate hasExpr() { exists(this.getExpr()) }
predicate hasFunction() { exists(this.getFunction()) }
}
final private class ParentCallExprBase extends ParentAstNode, CallExprBase {
@@ -1245,7 +1245,7 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
override predicate relevantChild(AstNode child) {
none()
or
child = this.getExpr()
child = this.getScrutinee()
or
child = this.getPat()
}
@@ -1283,16 +1283,16 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
/**
* Gets the expression of this let expression, if it exists.
* Gets the scrutinee of this let expression, if it exists.
*/
ExprCfgNode getExpr() {
any(ChildMapping mapping).hasCfgChild(node, node.getExpr(), this, result)
ExprCfgNode getScrutinee() {
any(ChildMapping mapping).hasCfgChild(node, node.getScrutinee(), this, result)
}
/**
* Holds if `getExpr()` exists.
* Holds if `getScrutinee()` exists.
*/
predicate hasExpr() { exists(this.getExpr()) }
predicate hasScrutinee() { exists(this.getScrutinee()) }
/**
* Gets the pat of this let expression, if it exists.
@@ -3211,14 +3211,14 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
cfgNode
)
or
pred = "getExpr" and
pred = "getFunction" and
parent =
any(Nodes::CallExprCfgNode cfgNode, CallExpr astNode |
astNode = cfgNode.getCallExpr() and
child = getDesugared(astNode.getExpr()) and
child = getDesugared(astNode.getFunction()) and
i = -1 and
hasCfgNode(child) and
not child = cfgNode.getExpr().getAstNode()
not child = cfgNode.getFunction().getAstNode()
|
cfgNode
)
@@ -3355,14 +3355,14 @@ module MakeCfgNodes<LocationSig Loc, InputSig<Loc> Input> {
cfgNode
)
or
pred = "getExpr" and
pred = "getScrutinee" and
parent =
any(Nodes::LetExprCfgNode cfgNode, LetExpr astNode |
astNode = cfgNode.getLetExpr() and
child = getDesugared(astNode.getExpr()) and
child = getDesugared(astNode.getScrutinee()) and
i = -1 and
hasCfgNode(child) and
not child = cfgNode.getExpr().getAstNode()
not child = cfgNode.getScrutinee().getAstNode()
|
cfgNode
)

View File

@@ -19,6 +19,12 @@ module DataFlow {
final class PostUpdateNode = Node::PostUpdateNode;
final class Content = DataFlowImpl::Content;
final class VariantContent = DataFlowImpl::VariantContent;
final class ContentSet = DataFlowImpl::ContentSet;
/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.

View File

@@ -115,6 +115,11 @@ module Node {
*/
ExprCfgNode asExpr() { none() }
/**
* Gets the pattern that corresponds to this node, if any.
*/
PatCfgNode asPat() { none() }
/** Gets the enclosing callable. */
DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) }
@@ -177,8 +182,7 @@ module Node {
PatNode() { this = TPatNode(n) }
/** Gets the `PatCfgNode` in the CFG that this node corresponds to. */
PatCfgNode getPat() { result = n }
override PatCfgNode asPat() { result = n }
}
/**
@@ -322,8 +326,7 @@ module LocalFlow {
nodeFrom.(Node::AstCfgFlowNode).getCfgNode() =
nodeTo.(Node::SsaNode).getDefinitionExt().(Ssa::WriteDefinition).getControlFlowNode()
or
nodeFrom.(Node::ParameterNode).getParameter().(ParamCfgNode).getPat() =
nodeTo.(Node::PatNode).getPat()
nodeFrom.(Node::ParameterNode).getParameter().(ParamCfgNode).getPat() = nodeTo.asPat()
or
SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _)
or
@@ -331,18 +334,165 @@ module LocalFlow {
a.getRhs() = nodeFrom.getCfgNode() and
a.getLhs() = nodeTo.getCfgNode()
)
or
exists(MatchExprCfgNode match |
nodeFrom.asExpr() = match.getScrutinee() and
nodeTo.asPat() = match.getArmPat(_)
)
or
nodeFrom.asPat().(OrPatCfgNode).getAPat() = nodeTo.asPat()
}
}
private class DataFlowCallableAlias = DataFlowCallable;
private import codeql.util.Option
private class ReturnKindAlias = ReturnKind;
private class CrateOrigin extends string {
CrateOrigin() {
this = [any(Item i).getCrateOrigin(), any(Resolvable r).getResolvedCrateOrigin()]
}
}
private class DataFlowCallAlias = DataFlowCall;
private class CrateOriginOption = Option<CrateOrigin>::Option;
private class ParameterPositionAlias = ParameterPosition;
pragma[nomagic]
private predicate hasExtendedCanonicalPath(Item i, CrateOriginOption crate, string path) {
path = i.getExtendedCanonicalPath() and
(
crate.asSome() = i.getCrateOrigin()
or
crate.isNone() and
not i.hasCrateOrigin()
)
}
pragma[nomagic]
private predicate variantHasExtendedCanonicalPath(
Enum e, Variant v, CrateOriginOption crate, string path, string name
) {
hasExtendedCanonicalPath(e, crate, path) and
v = e.getVariantList().getAVariant() and
name = v.getName().getText()
}
pragma[nomagic]
private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption crate, string path) {
path = r.getResolvedPath() and
(
crate.asSome() = r.getResolvedCrateOrigin()
or
crate.isNone() and
not r.hasResolvedCrateOrigin()
)
}
/**
* A path to a value contained in an object. For example a field name of a struct.
*/
abstract class Content extends TContent {
/** Gets a textual representation of this content. */
abstract string toString();
}
/** A canonical path pointing to an enum variant. */
private class VariantCanonicalPath extends MkVariantCanonicalPath {
CrateOriginOption crate;
string path;
string name;
VariantCanonicalPath() { this = MkVariantCanonicalPath(crate, path, name) }
/** Gets the underlying variant. */
Variant getVariant() { variantHasExtendedCanonicalPath(_, result, crate, path, name) }
string toString() { result = name }
Location getLocation() { result = this.getVariant().getLocation() }
}
/**
* A variant of an `enum`. In addition to the variant itself, this also includes the
* position (for tuple variants) or the field name (for record variants).
*/
abstract class VariantContent extends Content { }
/** A tuple variant. */
private class VariantPositionContent extends VariantContent, TVariantPositionContent {
private VariantCanonicalPath v;
private int pos_;
VariantPositionContent() { this = TVariantPositionContent(v, pos_) }
VariantCanonicalPath getVariantCanonicalPath(int pos) { result = v and pos = pos_ }
final override string toString() {
// only print indices when the arity is > 1
if exists(TVariantPositionContent(v, 1))
then result = v.toString() + "(" + pos_ + ")"
else result = v.toString()
}
}
/** A record variant. */
private class VariantFieldContent extends VariantContent, TVariantFieldContent {
private VariantCanonicalPath v;
private string field_;
VariantFieldContent() { this = TVariantFieldContent(v, field_) }
VariantCanonicalPath getVariantCanonicalPath(string field) { result = v and field = field_ }
final override string toString() {
// only print field when the arity is > 1
if strictcount(string f | exists(TVariantFieldContent(v, f))) > 1
then result = v.toString() + "{" + field_ + "}"
else result = v.toString()
}
}
/** A value that represents a set of `Content`s. */
abstract class ContentSet extends TContentSet {
/** Gets a textual representation of this element. */
abstract string toString();
/** Gets a content that may be stored into when storing into this set. */
abstract Content getAStoreContent();
/** Gets a content that may be read from when reading from this set. */
abstract Content getAReadContent();
}
final private class SingletonContentSet extends ContentSet, TSingletonContentSet {
private Content c;
SingletonContentSet() { this = TSingletonContentSet(c) }
Content getContent() { result = c }
override string toString() { result = c.toString() }
override Content getAStoreContent() { result = c }
override Content getAReadContent() { result = c }
}
// Defines a set of aliases needed for the `RustDataFlow` module
private module Aliases {
class DataFlowCallableAlias = DataFlowCallable;
class ReturnKindAlias = ReturnKind;
class DataFlowCallAlias = DataFlowCall;
class ParameterPositionAlias = ParameterPosition;
class ContentAlias = Content;
class ContentSetAlias = ContentSet;
}
module RustDataFlow implements InputSig<Location> {
private import Aliases
/**
* An element, viewed as a node in a data flow graph. Either an expression
* (`ExprNode`) or a parameter (`ParameterNode`).
@@ -388,55 +538,19 @@ module RustDataFlow implements InputSig<Location> {
final class ReturnKind = ReturnKindAlias;
private import codeql.util.Option
private class CrateOrigin extends string {
CrateOrigin() {
this = [any(Item i).getCrateOrigin(), any(Resolvable r).getResolvedCrateOrigin()]
}
}
private class CrateOriginOption = Option<CrateOrigin>::Option;
pragma[nomagic]
private predicate hasExtendedCanonicalPath(
DataFlowCallable c, CrateOriginOption crate, string path
) {
exists(Item i |
i = c.asCfgScope() and
path = i.getExtendedCanonicalPath()
|
crate.asSome() = i.getCrateOrigin()
or
crate.isNone() and
not i.hasCrateOrigin()
)
}
pragma[nomagic]
private predicate resolvesExtendedCanonicalPath(
DataFlowCall c, CrateOriginOption crate, string path
) {
exists(Resolvable r |
path = r.getResolvedPath() and
(
r = c.asMethodCallExprCfgNode().getExpr()
or
r = c.asCallExprCfgNode().getExpr().(PathExprCfgNode).getPath()
)
|
crate.asSome() = r.getResolvedCrateOrigin()
or
crate.isNone() and
not r.hasResolvedCrateOrigin()
)
private Resolvable getCallResolvable(CallExprBase call) {
result = call.(MethodCallExpr)
or
result = call.(CallExpr).getFunction().(PathExpr).getPath()
}
/** Gets a viable implementation of the target of the given `Call`. */
DataFlowCallable viableCallable(DataFlowCall call) {
exists(string path, CrateOriginOption crate |
hasExtendedCanonicalPath(result, crate, path) and
resolvesExtendedCanonicalPath(call, crate, path)
exists(Resolvable r, string path, CrateOriginOption crate |
hasExtendedCanonicalPath(result.asCfgScope(), crate, path) and
r = getCallResolvable(call.asCallBaseExprCfgNode().getExpr()) and
resolveExtendedCanonicalPath(r, crate, path)
)
}
@@ -450,30 +564,23 @@ module RustDataFlow implements InputSig<Location> {
// NOTE: For now we use the type `Unit` and do not benefit from type
// information in the data flow analysis.
final class DataFlowType = Unit;
final class DataFlowType extends Unit {
string toString() { result = "" }
}
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() }
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
final class Content = Void;
class Content = ContentAlias;
class ContentSet = ContentSetAlias;
predicate forceHighPrecision(Content c) { none() }
class ContentSet extends TContentSet {
/** Gets a textual representation of this element. */
string toString() { result = "ContentSet" }
final class ContentApprox = Content; // TODO: Implement if needed
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent() { none() }
/** Gets a content that may be read from when reading from this set. */
Content getAReadContent() { none() }
}
final class ContentApprox = Void;
ContentApprox getContentApprox(Content c) { any() }
ContentApprox getContentApprox(Content c) { result = c }
class ParameterPosition = ParameterPositionAlias;
@@ -501,19 +608,95 @@ module RustDataFlow implements InputSig<Location> {
*/
predicate jumpStep(Node node1, Node node2) { none() }
/** Holds if path `p` resolves to variant `v`. */
private predicate pathResolveToVariantCanonicalPath(Path p, VariantCanonicalPath v) {
exists(CrateOriginOption crate, string path |
resolveExtendedCanonicalPath(p.getQualifier(), crate, path) and
v = MkVariantCanonicalPath(crate, path, p.getPart().getNameRef().getText())
)
or
// TODO: Remove once library types are extracted
not p.hasQualifier() and
v = MkVariantCanonicalPath(_, "crate::std::option::Option", p.getPart().getNameRef().getText())
or
// TODO: Remove once library types are extracted
not p.hasQualifier() and
v = MkVariantCanonicalPath(_, "crate::std::result::Result", p.getPart().getNameRef().getText())
}
/** Holds if `p` destructs an enum variant `v`. */
pragma[nomagic]
private predicate tupleVariantDestruction(TupleStructPat p, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(p.getPath(), v)
}
/** Holds if `p` destructs an enum variant `v`. */
pragma[nomagic]
private predicate recordVariantDestruction(RecordPat p, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(p.getPath(), v)
}
/**
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
* `node1` references an object with a content `c.getAReadContent()` whose
* value ends up in `node2`.
*/
predicate readStep(Node node1, ContentSet c, Node node2) { none() }
predicate readStep(Node node1, ContentSet cs, Node node2) {
exists(Content c | c = cs.(SingletonContentSet).getContent() |
exists(TupleStructPatCfgNode pat, int pos |
pat = node1.asPat() and
tupleVariantDestruction(pat.getPat(),
c.(VariantPositionContent).getVariantCanonicalPath(pos)) and
node2.asPat() = pat.getField(pos)
)
or
exists(RecordPatCfgNode pat, string field |
pat = node1.asPat() and
recordVariantDestruction(pat.getPat(),
c.(VariantFieldContent).getVariantCanonicalPath(field)) and
node2.asPat() = pat.getFieldPat(field)
)
)
}
/** Holds if `ce` constructs an enum value of type `v`. */
pragma[nomagic]
private predicate tupleVariantConstruction(CallExpr ce, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(ce.getFunction().(PathExpr).getPath(), v)
}
/** Holds if `re` constructs an enum value of type `v`. */
pragma[nomagic]
private predicate recordVariantConstruction(RecordExpr re, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(re.getPath(), v)
}
/**
* Holds if data can flow from `node1` to `node2` via a store into `c`. Thus,
* `node2` references an object with a content `c.getAStoreContent()` that
* contains the value of `node1`.
*/
predicate storeStep(Node node1, ContentSet c, Node node2) { none() }
predicate storeStep(Node node1, ContentSet cs, Node node2) {
exists(Content c | c = cs.(SingletonContentSet).getContent() |
node2.asExpr() =
any(CallExprCfgNode call, int pos |
tupleVariantConstruction(call.getCallExpr(),
c.(VariantPositionContent).getVariantCanonicalPath(pos)) and
node1.asExpr() = call.getArgument(pos)
|
call
)
or
node2.asExpr() =
any(RecordExprCfgNode re, string field |
recordVariantConstruction(re.getRecordExpr(),
c.(VariantFieldContent).getVariantCanonicalPath(field)) and
node1.asExpr() = re.getFieldExpr(field)
|
re
)
)
}
/**
* Holds if values stored inside content `c` are cleared at node `n`. For example,
@@ -580,8 +763,6 @@ module RustDataFlow implements InputSig<Location> {
class DataFlowSecondLevelScope = Void;
}
final class ContentSet = RustDataFlow::ContentSet;
import MakeImpl<Location, RustDataFlow>
/** A collection of cached types and predicates to be evaluated in the same stage. */
@@ -598,14 +779,6 @@ private module Cached {
cached
newtype TDataFlowCall = TCall(CallExprBaseCfgNode c)
cached
newtype TOptionalContentSet =
TAnyElementContent() or
TAnyContent()
cached
class TContentSet = TAnyElementContent or TAnyContent;
cached
newtype TDataFlowCallable = TCfgScope(CfgScope scope)
@@ -621,6 +794,42 @@ private module Cached {
i in [0 .. max([any(ParamList l).getNumberOfParams(), any(ArgList l).getNumberOfArgs()]) - 1]
} or
TSelfParameterPosition()
cached
newtype TVariantCanonicalPath =
MkVariantCanonicalPath(CrateOriginOption crate, string path, string name) {
variantHasExtendedCanonicalPath(_, _, crate, path, name)
or
// TODO: Remove once library types are extracted
crate.isNone() and
path = "crate::std::option::Option" and
name = "Some"
or
// TODO: Remove once library types are extracted
crate.isNone() and
path = "crate::std::result::Result" and
name = ["Ok", "Err"]
}
cached
newtype TContent =
TVariantPositionContent(VariantCanonicalPath v, int pos) {
pos in [0 .. v.getVariant().getFieldList().(TupleFieldList).getNumberOfFields() - 1]
or
// TODO: Remove once library types are extracted
v = MkVariantCanonicalPath(_, "crate::std::option::Option", "Some") and
pos = 0
or
// TODO: Remove once library types are extracted
v = MkVariantCanonicalPath(_, "crate::std::result::Result", ["Ok", "Err"]) and
pos = 0
} or
TVariantFieldContent(VariantCanonicalPath v, string field) {
field = v.getVariant().getFieldList().(RecordFieldList).getAField().getName().getText()
}
cached
newtype TContentSet = TSingletonContentSet(Content c)
}
import Cached

View File

@@ -24,6 +24,8 @@ predicate variableWrite(AstNode write, Variable v) {
not isUnitializedLet(pat, v)
)
or
exists(SelfParam self | self = write and self = v.getSelfParam())
or
exists(VariableAccess access |
access = write and
access.getVariable() = v
@@ -477,7 +479,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
none() // handled in `DataFlowImpl.qll` instead
}
class Parameter = CfgNodes::ParamCfgNode;
class Parameter = CfgNodes::ParamBaseCfgNode;
/** Holds if SSA definition `def` initializes parameter `p` at function entry. */
predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) {

View File

@@ -23,6 +23,6 @@ module Impl {
* ```
*/
class CallExpr extends Generated::CallExpr {
override string toString() { result = this.getExpr().toAbbreviatedString() + "(...)" }
override string toString() { result = this.getFunction().toAbbreviatedString() + "(...)" }
}
}

View File

@@ -28,7 +28,7 @@ module Impl {
or
index = 1 and result = this.getPat().toAbbreviatedString()
or
index = 2 and result = "= " + this.getExpr().toAbbreviatedString()
index = 2 and result = "= " + this.getScrutinee().toAbbreviatedString()
}
}
}

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `ParamList`.
*
@@ -12,11 +11,17 @@ private import codeql.rust.elements.internal.generated.ParamList
* be referenced directly.
*/
module Impl {
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A ParamList. For example:
* ```rust
* todo!()
* ```
*/
class ParamList extends Generated::ParamList { }
class ParamList extends Generated::ParamList {
/**
* Gets any of the parameters of this parameter list.
*/
final ParamBase getAParamBase() { result = this.getParam(_) or result = this.getSelfParam() }
}
}

View File

@@ -73,24 +73,35 @@ module Impl {
* where `definingNode` is the entire `Either::Left(x) | Either::Right(x)`
* pattern.
*/
private predicate variableDecl(AstNode definingNode, IdentPat p, string name) {
(
definingNode = getOutermostEnclosingOrPat(p)
or
not exists(getOutermostEnclosingOrPat(p)) and
definingNode = p.getName()
) and
name = p.getName().getText() and
// exclude for now anything starting with an uppercase character, which may be a reference to
// an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
// which we don't appear to recognize yet anyway. This also assumes programmers follow the
// naming guidelines, which they generally do, but they're not enforced.
not name.charAt(0).isUppercase() and
// exclude parameters from functions without a body as these are trait method declarations
// without implementations
not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = p) and
// exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
not exists(FnPtrType fp | fp.getParamList().getParam(_).getPat() = p)
private predicate variableDecl(AstNode definingNode, AstNode p, string name) {
p =
any(SelfParam sp |
definingNode = sp.getName() and
name = sp.getName().getText() and
// exclude self parameters from functions without a body as these are
// trait method declarations without implementations
not exists(Function f | not f.hasBody() and f.getParamList().getSelfParam() = sp)
)
or
p =
any(IdentPat pat |
(
definingNode = getOutermostEnclosingOrPat(pat)
or
not exists(getOutermostEnclosingOrPat(pat)) and definingNode = pat.getName()
) and
name = pat.getName().getText() and
// exclude for now anything starting with an uppercase character, which may be a reference to
// an enum constant (e.g. `None`). This excludes static and constant variables (UPPERCASE),
// which we don't appear to recognize yet anyway. This also assumes programmers follow the
// naming guidelines, which they generally do, but they're not enforced.
not name.charAt(0).isUppercase() and
// exclude parameters from functions without a body as these are trait method declarations
// without implementations
not exists(Function f | not f.hasBody() and f.getParamList().getAParam().getPat() = pat) and
// exclude parameters from function pointer types (e.g. `x` in `fn(x: i32) -> i32`)
not exists(FnPtrType fp | fp.getParamList().getParam(_).getPat() = pat)
)
}
/** A variable. */
@@ -112,8 +123,11 @@ module Impl {
/** Gets an access to this variable. */
VariableAccess getAnAccess() { result.getVariable() = this }
/** Gets the `self` parameter that declares this variable, if one exists. */
SelfParam getSelfParam() { variableDecl(definingNode, result, name) }
/**
* Gets the pattern that declares this variable.
* Gets the pattern that declares this variable, if any.
*
* Normally, the pattern is unique, except when introduced in an or pattern:
*
@@ -135,7 +149,9 @@ module Impl {
predicate isCaptured() { this.getAnAccess().isCapture() }
/** Gets the parameter that introduces this variable, if any. */
Param getParameter() { parameterDeclInScope(result, this, _) }
ParamBase getParameter() {
result = this.getSelfParam() or result.(Param).getPat() = getAVariablePatAncestor(this)
}
/** Hold is this variable is mutable. */
predicate isMutable() { this.getPat().isMut() }
@@ -144,7 +160,11 @@ module Impl {
predicate isImmutable() { not this.isMutable() }
}
/** A path expression that may access a local variable. */
/**
* A path expression that may access a local variable. These are paths that
* only consists of a simple name (i.e., without generic arguments,
* qualifiers, etc.).
*/
private class VariableAccessCand extends PathExprBase {
string name_;
@@ -190,10 +210,7 @@ module Impl {
private VariableScope getEnclosingScope(AstNode n) { result = getAnAncestorInVariableScope(n) }
private Pat getAVariablePatAncestor(Variable v) {
exists(AstNode definingNode, string name |
v = MkVariable(definingNode, name) and
variableDecl(definingNode, result, name)
)
result = v.getPat()
or
exists(Pat mid |
mid = getAVariablePatAncestor(v) and
@@ -202,23 +219,12 @@ module Impl {
}
/**
* Holds if parameter `p` introduces the variable `v` inside variable scope
* `scope`.
* Holds if a parameter declares the variable `v` inside variable scope `scope`.
*/
private predicate parameterDeclInScope(Param p, Variable v, VariableScope scope) {
exists(Pat pat |
pat = getAVariablePatAncestor(v) and
p.getPat() = pat
|
exists(Function f |
f.getParamList().getAParam() = p and
scope = f.getBody()
)
or
exists(ClosureExpr ce |
ce.getParamList().getAParam() = p and
scope = ce.getBody()
)
private predicate parameterDeclInScope(Variable v, VariableScope scope) {
exists(Callable f |
v.getParameter() = f.getParamList().getAParamBase() and
scope = [f.(Function).getBody(), f.(ClosureExpr).getBody()]
)
}
@@ -231,7 +237,7 @@ module Impl {
) {
name = v.getName() and
(
parameterDeclInScope(_, v, scope) and
parameterDeclInScope(v, scope) and
scope.getLocation().hasLocationFileInfo(_, line, column, _, _)
or
exists(Pat pat | pat = getAVariablePatAncestor(v) |

View File

@@ -29,16 +29,16 @@ module Generated {
override string getAPrimaryQlClass() { result = "CallExpr" }
/**
* Gets the expression of this call expression, if it exists.
* Gets the function of this call expression, if it exists.
*/
Expr getExpr() {
Expr getFunction() {
result =
Synth::convertExprFromRaw(Synth::convertCallExprToRaw(this).(Raw::CallExpr).getExpr())
Synth::convertExprFromRaw(Synth::convertCallExprToRaw(this).(Raw::CallExpr).getFunction())
}
/**
* Holds if `getExpr()` exists.
* Holds if `getFunction()` exists.
*/
final predicate hasExpr() { exists(this.getExpr()) }
final predicate hasFunction() { exists(this.getFunction()) }
}
}

View File

@@ -48,16 +48,17 @@ module Generated {
final int getNumberOfAttrs() { result = count(int i | exists(this.getAttr(i))) }
/**
* Gets the expression of this let expression, if it exists.
* Gets the scrutinee of this let expression, if it exists.
*/
Expr getExpr() {
result = Synth::convertExprFromRaw(Synth::convertLetExprToRaw(this).(Raw::LetExpr).getExpr())
Expr getScrutinee() {
result =
Synth::convertExprFromRaw(Synth::convertLetExprToRaw(this).(Raw::LetExpr).getScrutinee())
}
/**
* Holds if `getExpr()` exists.
* Holds if `getScrutinee()` exists.
*/
final predicate hasExpr() { exists(this.getExpr()) }
final predicate hasScrutinee() { exists(this.getScrutinee()) }
/**
* Gets the pat of this let expression, if it exists.

View File

@@ -1836,13 +1836,13 @@ private module Impl {
}
private Element getImmediateChildOfLetExpr(LetExpr e, int index, string partialPredicateCall) {
exists(int b, int bExpr, int n, int nAttr, int nExpr, int nPat |
exists(int b, int bExpr, int n, int nAttr, int nScrutinee, int nPat |
b = 0 and
bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and
n = bExpr and
nAttr = n + 1 + max(int i | i = -1 or exists(e.getAttr(i)) | i) and
nExpr = nAttr + 1 and
nPat = nExpr + 1 and
nScrutinee = nAttr + 1 and
nPat = nScrutinee + 1 and
(
none()
or
@@ -1851,9 +1851,9 @@ private module Impl {
result = e.getAttr(index - n) and
partialPredicateCall = "Attr(" + (index - n).toString() + ")"
or
index = nAttr and result = e.getExpr() and partialPredicateCall = "Expr()"
index = nAttr and result = e.getScrutinee() and partialPredicateCall = "Scrutinee()"
or
index = nExpr and result = e.getPat() and partialPredicateCall = "Pat()"
index = nScrutinee and result = e.getPat() and partialPredicateCall = "Pat()"
)
)
}
@@ -2807,18 +2807,18 @@ private module Impl {
}
private Element getImmediateChildOfCallExpr(CallExpr e, int index, string partialPredicateCall) {
exists(int b, int bCallExprBase, int n, int nExpr |
exists(int b, int bCallExprBase, int n, int nFunction |
b = 0 and
bCallExprBase =
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallExprBase(e, i, _)) | i) and
n = bCallExprBase and
nExpr = n + 1 and
nFunction = n + 1 and
(
none()
or
result = getImmediateChildOfCallExprBase(e, index - b, partialPredicateCall)
or
index = n and result = e.getExpr() and partialPredicateCall = "Expr()"
index = n and result = e.getFunction() and partialPredicateCall = "Function()"
)
)
}

View File

@@ -1927,9 +1927,9 @@ module Raw {
Attr getAttr(int index) { let_expr_attrs(this, index, result) }
/**
* Gets the expression of this let expression, if it exists.
* Gets the scrutinee of this let expression, if it exists.
*/
Expr getExpr() { let_expr_exprs(this, result) }
Expr getScrutinee() { let_expr_scrutinees(this, result) }
/**
* Gets the pat of this let expression, if it exists.
@@ -2144,7 +2144,7 @@ module Raw {
/**
* Gets the scrutinee (the expression being matched) of this match expression, if it exists.
*/
Expr getScrutinee() { match_expr_exprs(this, result) }
Expr getScrutinee() { match_expr_scrutinees(this, result) }
/**
* Gets the match arm list of this match expression, if it exists.
@@ -3072,9 +3072,9 @@ module Raw {
override string toString() { result = "CallExpr" }
/**
* Gets the expression of this call expression, if it exists.
* Gets the function of this call expression, if it exists.
*/
Expr getExpr() { call_expr_exprs(this, result) }
Expr getFunction() { call_expr_functions(this, result) }
}
/**

View File

@@ -0,0 +1,20 @@
/**
* Provides modeling for the `reqwest` library.
*/
private import rust
private import codeql.rust.Concepts
/**
* A call to `reqwest::get` or `reqwest::blocking::get`.
*/
private class ReqwestGet extends RemoteSource::Range {
ReqwestGet() {
exists(CallExpr ce |
this.asExpr().getExpr() = ce and
ce.getFunction().(PathExpr).getPath().getResolvedCrateOrigin().matches("%reqwest") and
ce.getFunction().(PathExpr).getPath().getResolvedPath() =
["crate::get", "crate::blocking::get"]
)
}
}

View File

@@ -0,0 +1,36 @@
/**
* Provides modeling for the `std::env` library.
*/
private import rust
private import codeql.rust.Concepts
/**
* A call to `std::env::args` or `std::env::args_os`.
*/
private class StdEnvArgs extends CommandLineArgsSource::Range {
StdEnvArgs() {
this.asExpr().getExpr().(CallExpr).getFunction().(PathExpr).getPath().getResolvedPath() =
["crate::env::args", "crate::env::args_os"]
}
}
/**
* A call to `std::env::current_dir`, `std::env::current_exe` or `std::env::home_dir`.
*/
private class StdEnvDir extends CommandLineArgsSource::Range {
StdEnvDir() {
this.asExpr().getExpr().(CallExpr).getFunction().(PathExpr).getPath().getResolvedPath() =
["crate::env::current_dir", "crate::env::current_exe", "crate::env::home_dir"]
}
}
/**
* A call to `std::env::var`, `std::env::var_os`, `std::env::vars` or `std::env::vars_os`.
*/
private class StdEnvVar extends EnvironmentSource::Range {
StdEnvVar() {
this.asExpr().getExpr().(CallExpr).getFunction().(PathExpr).getPath().getResolvedPath() =
["crate::env::var", "crate::env::var_os", "crate::env::vars", "crate::env::vars_os"]
}
}

View File

@@ -95,7 +95,7 @@ module Stages {
or
exists(AstCfgNode n)
or
exists(CallExprCfgNode n | exists(n.getExpr()))
exists(CallExprCfgNode n | exists(n.getFunction()))
}
}
}

View File

@@ -1718,9 +1718,9 @@ let_expr_attrs(
);
#keyset[id]
let_expr_exprs(
let_expr_scrutinees(
int id: @let_expr ref,
int expr: @expr ref
int scrutinee: @expr ref
);
#keyset[id]
@@ -1866,9 +1866,9 @@ match_expr_attrs(
);
#keyset[id]
match_expr_exprs(
match_expr_scrutinees(
int id: @match_expr ref,
int expr: @expr ref
int scrutinee: @expr ref
);
#keyset[id]
@@ -2538,9 +2538,9 @@ call_exprs(
);
#keyset[id]
call_expr_exprs(
call_expr_functions(
int id: @call_expr ref,
int expr: @expr ref
int function: @expr ref
);
consts(

View File

@@ -1,6 +1,7 @@
/**
* @name Unextracted Elements
* @description List all elements that weren't extracted due to unimplemented features or parse errors.
* @kind diagnostic
* @id rust/diagnostics/unextracted-elements
*/

View File

@@ -0,0 +1,12 @@
/**
* @name Unresolved Macro Calls
* @description List all macro calls that were not resolved to a target.
* @kind diagnostic
* @id rust/diagnostics/unresolved-macro-calls
*/
import rust
from MacroCall mc
where not mc.hasExpanded()
select mc, "Macro call was not resolved to a target."

View File

@@ -7,6 +7,7 @@
*/
import rust
import codeql.rust.Concepts
import codeql.rust.Diagnostics
import Stats
@@ -37,4 +38,14 @@ where
key = "Inconsistencies - CFG" and value = getTotalCfgInconsistencies()
or
key = "Inconsistencies - data flow" and value = getTotalDataFlowInconsistencies()
select key, value
or
key = "Macro calls - total" and value = count(MacroCall mc)
or
key = "Macro calls - resolved" and value = count(MacroCall mc | mc.hasExpanded())
or
key = "Macro calls - unresolved" and value = count(MacroCall mc | not mc.hasExpanded())
or
key = "Taint sources - total" and value = count(ThreatModelSource s)
or
key = "Taint sources - active" and value = count(ActiveThreatModelSource s)
select key, value order by key

View File

@@ -0,0 +1,18 @@
/**
* @name Taint Sources
* @description List all sources of untrusted input that have been idenfitied
* in the database.
* @kind problem
* @problem.severity info
* @id rust/summary/taint-sources
* @tags summary
*/
import rust
import codeql.rust.Concepts
from ThreatModelSource s, string defaultString
where
if s instanceof ActiveThreatModelSource then defaultString = " (DEFAULT)" else defaultString = ""
select s,
"Flow source '" + s.getSourceType() + "' of type " + s.getThreatModel() + defaultString + "."

View File

@@ -1,4 +1,4 @@
| gen_call_expr.rs:5:5:5:11 | foo(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes |
| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes |
| gen_call_expr.rs:7:5:7:14 | ...(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes |
| gen_call_expr.rs:8:5:8:10 | foo(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasExpr: | yes |
| gen_call_expr.rs:5:5:5:11 | foo(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes |
| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes |
| gen_call_expr.rs:7:5:7:14 | ...(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes |
| gen_call_expr.rs:8:5:8:10 | foo(...) | hasArgList: | yes | getNumberOfAttrs: | 0 | hasFunction: | yes |

View File

@@ -2,11 +2,12 @@
import codeql.rust.elements
import TestUtils
from CallExpr x, string hasArgList, int getNumberOfAttrs, string hasExpr
from CallExpr x, string hasArgList, int getNumberOfAttrs, string hasFunction
where
toBeTested(x) and
not x.isUnknown() and
(if x.hasArgList() then hasArgList = "yes" else hasArgList = "no") and
getNumberOfAttrs = x.getNumberOfAttrs() and
if x.hasExpr() then hasExpr = "yes" else hasExpr = "no"
select x, "hasArgList:", hasArgList, "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr
if x.hasFunction() then hasFunction = "yes" else hasFunction = "no"
select x, "hasArgList:", hasArgList, "getNumberOfAttrs:", getNumberOfAttrs, "hasFunction:",
hasFunction

View File

@@ -0,0 +1,4 @@
| gen_call_expr.rs:5:5:5:11 | foo(...) | gen_call_expr.rs:5:5:5:7 | foo |
| gen_call_expr.rs:6:5:6:23 | foo::<...>(...) | gen_call_expr.rs:6:5:6:19 | foo::<...> |
| gen_call_expr.rs:7:5:7:14 | ...(...) | gen_call_expr.rs:7:5:7:10 | foo[0] |
| gen_call_expr.rs:8:5:8:10 | foo(...) | gen_call_expr.rs:8:5:8:7 | foo |

View File

@@ -4,4 +4,4 @@ import TestUtils
from CallExpr x
where toBeTested(x) and not x.isUnknown()
select x, x.getExpr()
select x, x.getFunction()

View File

@@ -1 +1 @@
| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | getNumberOfAttrs: | 0 | hasExpr: | yes | hasPat: | yes |
| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | getNumberOfAttrs: | 0 | hasScrutinee: | yes | hasPat: | yes |

View File

@@ -2,11 +2,11 @@
import codeql.rust.elements
import TestUtils
from LetExpr x, int getNumberOfAttrs, string hasExpr, string hasPat
from LetExpr x, int getNumberOfAttrs, string hasScrutinee, string hasPat
where
toBeTested(x) and
not x.isUnknown() and
getNumberOfAttrs = x.getNumberOfAttrs() and
(if x.hasExpr() then hasExpr = "yes" else hasExpr = "no") and
(if x.hasScrutinee() then hasScrutinee = "yes" else hasScrutinee = "no") and
if x.hasPat() then hasPat = "yes" else hasPat = "no"
select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasExpr:", hasExpr, "hasPat:", hasPat
select x, "getNumberOfAttrs:", getNumberOfAttrs, "hasScrutinee:", hasScrutinee, "hasPat:", hasPat

View File

@@ -0,0 +1 @@
| gen_let_expr.rs:5:8:5:31 | let ... = maybe_some | gen_let_expr.rs:5:22:5:31 | maybe_some |

View File

@@ -4,4 +4,4 @@ import TestUtils
from LetExpr x
where toBeTested(x) and not x.isUnknown()
select x, x.getExpr()
select x, x.getScrutinee()

View File

@@ -1,29 +1,29 @@
models
edges
| main.rs:9:13:9:19 | ...: ... : unit | main.rs:9:30:14:1 | { ... } : unit | provenance | |
| main.rs:21:13:21:21 | source(...) : unit | main.rs:22:10:22:10 | s | provenance | |
| main.rs:26:13:26:21 | source(...) : unit | main.rs:27:22:27:22 | s : unit | provenance | |
| main.rs:27:13:27:23 | sanitize(...) : unit | main.rs:28:10:28:10 | s | provenance | |
| main.rs:27:22:27:22 | s : unit | main.rs:9:13:9:19 | ...: ... : unit | provenance | |
| main.rs:27:22:27:22 | s : unit | main.rs:27:13:27:23 | sanitize(...) : unit | provenance | |
| main.rs:32:13:32:21 | source(...) : unit | main.rs:33:10:33:10 | s | provenance | |
| main.rs:9:13:9:19 | ...: ... | main.rs:9:30:14:1 | { ... } | provenance | |
| main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | provenance | |
| main.rs:26:13:26:21 | source(...) | main.rs:27:22:27:22 | s | provenance | |
| main.rs:27:13:27:23 | sanitize(...) | main.rs:28:10:28:10 | s | provenance | |
| main.rs:27:22:27:22 | s | main.rs:9:13:9:19 | ...: ... | provenance | |
| main.rs:27:22:27:22 | s | main.rs:27:13:27:23 | sanitize(...) | provenance | |
| main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | provenance | |
nodes
| main.rs:9:13:9:19 | ...: ... : unit | semmle.label | ...: ... : unit |
| main.rs:9:30:14:1 | { ... } : unit | semmle.label | { ... } : unit |
| main.rs:9:13:9:19 | ...: ... | semmle.label | ...: ... |
| main.rs:9:30:14:1 | { ... } | semmle.label | { ... } |
| main.rs:17:10:17:18 | source(...) | semmle.label | source(...) |
| main.rs:21:13:21:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:21:13:21:21 | source(...) | semmle.label | source(...) |
| main.rs:22:10:22:10 | s | semmle.label | s |
| main.rs:26:13:26:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:27:13:27:23 | sanitize(...) : unit | semmle.label | sanitize(...) : unit |
| main.rs:27:22:27:22 | s : unit | semmle.label | s : unit |
| main.rs:26:13:26:21 | source(...) | semmle.label | source(...) |
| main.rs:27:13:27:23 | sanitize(...) | semmle.label | sanitize(...) |
| main.rs:27:22:27:22 | s | semmle.label | s |
| main.rs:28:10:28:10 | s | semmle.label | s |
| main.rs:32:13:32:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:32:13:32:21 | source(...) | semmle.label | source(...) |
| main.rs:33:10:33:10 | s | semmle.label | s |
subpaths
| main.rs:27:22:27:22 | s : unit | main.rs:9:13:9:19 | ...: ... : unit | main.rs:9:30:14:1 | { ... } : unit | main.rs:27:13:27:23 | sanitize(...) : unit |
| main.rs:27:22:27:22 | s | main.rs:9:13:9:19 | ...: ... | main.rs:9:30:14:1 | { ... } | main.rs:27:13:27:23 | sanitize(...) |
testFailures
#select
| main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | $@ | main.rs:17:10:17:18 | source(...) | source(...) |
| main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) : unit | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) : unit | source(...) : unit |
| main.rs:28:10:28:10 | s | main.rs:26:13:26:21 | source(...) : unit | main.rs:28:10:28:10 | s | $@ | main.rs:26:13:26:21 | source(...) : unit | source(...) : unit |
| main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) : unit | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) : unit | source(...) : unit |
| main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) | source(...) |
| main.rs:28:10:28:10 | s | main.rs:26:13:26:21 | source(...) | main.rs:28:10:28:10 | s | $@ | main.rs:26:13:26:21 | source(...) | source(...) |
| main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) | source(...) |

View File

@@ -1,74 +1,74 @@
models
edges
| main.rs:12:28:14:1 | { ... } : unit | main.rs:17:13:17:23 | get_data(...) : unit | provenance | |
| main.rs:13:5:13:13 | source(...) : unit | main.rs:12:28:14:1 | { ... } : unit | provenance | |
| main.rs:17:13:17:23 | get_data(...) : unit | main.rs:18:10:18:10 | a | provenance | |
| main.rs:21:12:21:17 | ...: i64 : unit | main.rs:22:10:22:10 | n | provenance | |
| main.rs:26:13:26:21 | source(...) : unit | main.rs:27:13:27:13 | a : unit | provenance | |
| main.rs:27:13:27:13 | a : unit | main.rs:21:12:21:17 | ...: i64 : unit | provenance | |
| main.rs:30:17:30:22 | ...: i64 : unit | main.rs:30:32:32:1 | { ... } : unit | provenance | |
| main.rs:35:13:35:21 | source(...) : unit | main.rs:36:26:36:26 | a : unit | provenance | |
| main.rs:36:13:36:27 | pass_through(...) : unit | main.rs:37:10:37:10 | b | provenance | |
| main.rs:36:26:36:26 | a : unit | main.rs:30:17:30:22 | ...: i64 : unit | provenance | |
| main.rs:36:26:36:26 | a : unit | main.rs:36:13:36:27 | pass_through(...) : unit | provenance | |
| main.rs:41:13:44:6 | pass_through(...) : unit | main.rs:45:10:45:10 | a | provenance | |
| main.rs:41:26:44:5 | { ... } : unit | main.rs:30:17:30:22 | ...: i64 : unit | provenance | |
| main.rs:41:26:44:5 | { ... } : unit | main.rs:41:13:44:6 | pass_through(...) : unit | provenance | |
| main.rs:43:9:43:18 | source(...) : unit | main.rs:41:26:44:5 | { ... } : unit | provenance | |
| main.rs:56:23:56:28 | ...: i64 : unit | main.rs:57:14:57:14 | n | provenance | |
| main.rs:59:31:65:5 | { ... } : unit | main.rs:77:13:77:25 | ... .get_data(...) : unit | provenance | |
| main.rs:63:13:63:21 | source(...) : unit | main.rs:59:31:65:5 | { ... } : unit | provenance | |
| main.rs:66:28:66:33 | ...: i64 : unit | main.rs:66:43:72:5 | { ... } : unit | provenance | |
| main.rs:77:13:77:25 | ... .get_data(...) : unit | main.rs:78:10:78:10 | a | provenance | |
| main.rs:83:13:83:21 | source(...) : unit | main.rs:84:16:84:16 | a : unit | provenance | |
| main.rs:84:16:84:16 | a : unit | main.rs:56:23:56:28 | ...: i64 : unit | provenance | |
| main.rs:89:13:89:21 | source(...) : unit | main.rs:90:29:90:29 | a : unit | provenance | |
| main.rs:90:13:90:30 | ... .data_through(...) : unit | main.rs:91:10:91:10 | b | provenance | |
| main.rs:90:29:90:29 | a : unit | main.rs:66:28:66:33 | ...: i64 : unit | provenance | |
| main.rs:90:29:90:29 | a : unit | main.rs:90:13:90:30 | ... .data_through(...) : unit | provenance | |
| main.rs:12:28:14:1 | { ... } | main.rs:17:13:17:23 | get_data(...) | provenance | |
| main.rs:13:5:13:13 | source(...) | main.rs:12:28:14:1 | { ... } | provenance | |
| main.rs:17:13:17:23 | get_data(...) | main.rs:18:10:18:10 | a | provenance | |
| main.rs:21:12:21:17 | ...: i64 | main.rs:22:10:22:10 | n | provenance | |
| main.rs:26:13:26:21 | source(...) | main.rs:27:13:27:13 | a | provenance | |
| main.rs:27:13:27:13 | a | main.rs:21:12:21:17 | ...: i64 | provenance | |
| main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | provenance | |
| main.rs:35:13:35:21 | source(...) | main.rs:36:26:36:26 | a | provenance | |
| main.rs:36:13:36:27 | pass_through(...) | main.rs:37:10:37:10 | b | provenance | |
| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | provenance | |
| main.rs:36:26:36:26 | a | main.rs:36:13:36:27 | pass_through(...) | provenance | |
| main.rs:41:13:44:6 | pass_through(...) | main.rs:45:10:45:10 | a | provenance | |
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | provenance | |
| main.rs:41:26:44:5 | { ... } | main.rs:41:13:44:6 | pass_through(...) | provenance | |
| main.rs:43:9:43:18 | source(...) | main.rs:41:26:44:5 | { ... } | provenance | |
| main.rs:56:23:56:28 | ...: i64 | main.rs:57:14:57:14 | n | provenance | |
| main.rs:59:31:65:5 | { ... } | main.rs:77:13:77:25 | ... .get_data(...) | provenance | |
| main.rs:63:13:63:21 | source(...) | main.rs:59:31:65:5 | { ... } | provenance | |
| main.rs:66:28:66:33 | ...: i64 | main.rs:66:43:72:5 | { ... } | provenance | |
| main.rs:77:13:77:25 | ... .get_data(...) | main.rs:78:10:78:10 | a | provenance | |
| main.rs:83:13:83:21 | source(...) | main.rs:84:16:84:16 | a | provenance | |
| main.rs:84:16:84:16 | a | main.rs:56:23:56:28 | ...: i64 | provenance | |
| main.rs:89:13:89:21 | source(...) | main.rs:90:29:90:29 | a | provenance | |
| main.rs:90:13:90:30 | ... .data_through(...) | main.rs:91:10:91:10 | b | provenance | |
| main.rs:90:29:90:29 | a | main.rs:66:28:66:33 | ...: i64 | provenance | |
| main.rs:90:29:90:29 | a | main.rs:90:13:90:30 | ... .data_through(...) | provenance | |
nodes
| main.rs:12:28:14:1 | { ... } : unit | semmle.label | { ... } : unit |
| main.rs:13:5:13:13 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:17:13:17:23 | get_data(...) : unit | semmle.label | get_data(...) : unit |
| main.rs:12:28:14:1 | { ... } | semmle.label | { ... } |
| main.rs:13:5:13:13 | source(...) | semmle.label | source(...) |
| main.rs:17:13:17:23 | get_data(...) | semmle.label | get_data(...) |
| main.rs:18:10:18:10 | a | semmle.label | a |
| main.rs:21:12:21:17 | ...: i64 : unit | semmle.label | ...: i64 : unit |
| main.rs:21:12:21:17 | ...: i64 | semmle.label | ...: i64 |
| main.rs:22:10:22:10 | n | semmle.label | n |
| main.rs:26:13:26:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:27:13:27:13 | a : unit | semmle.label | a : unit |
| main.rs:30:17:30:22 | ...: i64 : unit | semmle.label | ...: i64 : unit |
| main.rs:30:32:32:1 | { ... } : unit | semmle.label | { ... } : unit |
| main.rs:35:13:35:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:36:13:36:27 | pass_through(...) : unit | semmle.label | pass_through(...) : unit |
| main.rs:36:26:36:26 | a : unit | semmle.label | a : unit |
| main.rs:26:13:26:21 | source(...) | semmle.label | source(...) |
| main.rs:27:13:27:13 | a | semmle.label | a |
| main.rs:30:17:30:22 | ...: i64 | semmle.label | ...: i64 |
| main.rs:30:32:32:1 | { ... } | semmle.label | { ... } |
| main.rs:35:13:35:21 | source(...) | semmle.label | source(...) |
| main.rs:36:13:36:27 | pass_through(...) | semmle.label | pass_through(...) |
| main.rs:36:26:36:26 | a | semmle.label | a |
| main.rs:37:10:37:10 | b | semmle.label | b |
| main.rs:41:13:44:6 | pass_through(...) : unit | semmle.label | pass_through(...) : unit |
| main.rs:41:26:44:5 | { ... } : unit | semmle.label | { ... } : unit |
| main.rs:43:9:43:18 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:41:13:44:6 | pass_through(...) | semmle.label | pass_through(...) |
| main.rs:41:26:44:5 | { ... } | semmle.label | { ... } |
| main.rs:43:9:43:18 | source(...) | semmle.label | source(...) |
| main.rs:45:10:45:10 | a | semmle.label | a |
| main.rs:56:23:56:28 | ...: i64 : unit | semmle.label | ...: i64 : unit |
| main.rs:56:23:56:28 | ...: i64 | semmle.label | ...: i64 |
| main.rs:57:14:57:14 | n | semmle.label | n |
| main.rs:59:31:65:5 | { ... } : unit | semmle.label | { ... } : unit |
| main.rs:63:13:63:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:66:28:66:33 | ...: i64 : unit | semmle.label | ...: i64 : unit |
| main.rs:66:43:72:5 | { ... } : unit | semmle.label | { ... } : unit |
| main.rs:77:13:77:25 | ... .get_data(...) : unit | semmle.label | ... .get_data(...) : unit |
| main.rs:59:31:65:5 | { ... } | semmle.label | { ... } |
| main.rs:63:13:63:21 | source(...) | semmle.label | source(...) |
| main.rs:66:28:66:33 | ...: i64 | semmle.label | ...: i64 |
| main.rs:66:43:72:5 | { ... } | semmle.label | { ... } |
| main.rs:77:13:77:25 | ... .get_data(...) | semmle.label | ... .get_data(...) |
| main.rs:78:10:78:10 | a | semmle.label | a |
| main.rs:83:13:83:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:84:16:84:16 | a : unit | semmle.label | a : unit |
| main.rs:89:13:89:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:90:13:90:30 | ... .data_through(...) : unit | semmle.label | ... .data_through(...) : unit |
| main.rs:90:29:90:29 | a : unit | semmle.label | a : unit |
| main.rs:83:13:83:21 | source(...) | semmle.label | source(...) |
| main.rs:84:16:84:16 | a | semmle.label | a |
| main.rs:89:13:89:21 | source(...) | semmle.label | source(...) |
| main.rs:90:13:90:30 | ... .data_through(...) | semmle.label | ... .data_through(...) |
| main.rs:90:29:90:29 | a | semmle.label | a |
| main.rs:91:10:91:10 | b | semmle.label | b |
subpaths
| main.rs:36:26:36:26 | a : unit | main.rs:30:17:30:22 | ...: i64 : unit | main.rs:30:32:32:1 | { ... } : unit | main.rs:36:13:36:27 | pass_through(...) : unit |
| main.rs:41:26:44:5 | { ... } : unit | main.rs:30:17:30:22 | ...: i64 : unit | main.rs:30:32:32:1 | { ... } : unit | main.rs:41:13:44:6 | pass_through(...) : unit |
| main.rs:90:29:90:29 | a : unit | main.rs:66:28:66:33 | ...: i64 : unit | main.rs:66:43:72:5 | { ... } : unit | main.rs:90:13:90:30 | ... .data_through(...) : unit |
| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:36:13:36:27 | pass_through(...) |
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:41:13:44:6 | pass_through(...) |
| main.rs:90:29:90:29 | a | main.rs:66:28:66:33 | ...: i64 | main.rs:66:43:72:5 | { ... } | main.rs:90:13:90:30 | ... .data_through(...) |
testFailures
#select
| main.rs:18:10:18:10 | a | main.rs:13:5:13:13 | source(...) : unit | main.rs:18:10:18:10 | a | $@ | main.rs:13:5:13:13 | source(...) : unit | source(...) : unit |
| main.rs:22:10:22:10 | n | main.rs:26:13:26:21 | source(...) : unit | main.rs:22:10:22:10 | n | $@ | main.rs:26:13:26:21 | source(...) : unit | source(...) : unit |
| main.rs:37:10:37:10 | b | main.rs:35:13:35:21 | source(...) : unit | main.rs:37:10:37:10 | b | $@ | main.rs:35:13:35:21 | source(...) : unit | source(...) : unit |
| main.rs:45:10:45:10 | a | main.rs:43:9:43:18 | source(...) : unit | main.rs:45:10:45:10 | a | $@ | main.rs:43:9:43:18 | source(...) : unit | source(...) : unit |
| main.rs:57:14:57:14 | n | main.rs:83:13:83:21 | source(...) : unit | main.rs:57:14:57:14 | n | $@ | main.rs:83:13:83:21 | source(...) : unit | source(...) : unit |
| main.rs:78:10:78:10 | a | main.rs:63:13:63:21 | source(...) : unit | main.rs:78:10:78:10 | a | $@ | main.rs:63:13:63:21 | source(...) : unit | source(...) : unit |
| main.rs:91:10:91:10 | b | main.rs:89:13:89:21 | source(...) : unit | main.rs:91:10:91:10 | b | $@ | main.rs:89:13:89:21 | source(...) : unit | source(...) : unit |
| main.rs:18:10:18:10 | a | main.rs:13:5:13:13 | source(...) | main.rs:18:10:18:10 | a | $@ | main.rs:13:5:13:13 | source(...) | source(...) |
| main.rs:22:10:22:10 | n | main.rs:26:13:26:21 | source(...) | main.rs:22:10:22:10 | n | $@ | main.rs:26:13:26:21 | source(...) | source(...) |
| main.rs:37:10:37:10 | b | main.rs:35:13:35:21 | source(...) | main.rs:37:10:37:10 | b | $@ | main.rs:35:13:35:21 | source(...) | source(...) |
| main.rs:45:10:45:10 | a | main.rs:43:9:43:18 | source(...) | main.rs:45:10:45:10 | a | $@ | main.rs:43:9:43:18 | source(...) | source(...) |
| main.rs:57:14:57:14 | n | main.rs:83:13:83:21 | source(...) | main.rs:57:14:57:14 | n | $@ | main.rs:83:13:83:21 | source(...) | source(...) |
| main.rs:78:10:78:10 | a | main.rs:63:13:63:21 | source(...) | main.rs:78:10:78:10 | a | $@ | main.rs:63:13:63:21 | source(...) | source(...) |
| main.rs:91:10:91:10 | b | main.rs:89:13:89:21 | source(...) | main.rs:91:10:91:10 | b | $@ | main.rs:89:13:89:21 | source(...) | source(...) |

View File

@@ -1,3 +1,4 @@
localStep
| main.rs:3:11:3:11 | [SSA] i | main.rs:4:12:4:12 | i |
| main.rs:3:11:3:11 | i | main.rs:3:11:3:11 | [SSA] i |
| main.rs:3:11:3:16 | ...: i64 | main.rs:3:11:3:11 | i |
@@ -33,6 +34,8 @@
| main.rs:32:9:32:9 | [SSA] b | main.rs:36:10:36:10 | b |
| main.rs:32:9:32:9 | b | main.rs:32:9:32:9 | [SSA] b |
| main.rs:32:13:35:5 | match m { ... } | main.rs:32:9:32:9 | b |
| main.rs:32:19:32:19 | m | main.rs:33:9:33:15 | TupleStructPat |
| main.rs:32:19:32:19 | m | main.rs:34:9:34:12 | None |
| main.rs:33:20:33:20 | a | main.rs:32:13:35:5 | match m { ... } |
| main.rs:34:17:34:17 | 0 | main.rs:32:13:35:5 | match m { ... } |
| main.rs:40:9:40:9 | [SSA] a | main.rs:43:10:43:10 | a |
@@ -75,42 +78,229 @@
| main.rs:97:38:97:38 | p | main.rs:97:9:97:34 | Point {...} |
| main.rs:104:9:104:10 | [SSA] s1 | main.rs:106:11:106:12 | s1 |
| main.rs:104:9:104:10 | s1 | main.rs:104:9:104:10 | [SSA] s1 |
| main.rs:104:14:104:28 | Some(...) | main.rs:104:9:104:10 | s1 |
| main.rs:104:14:104:37 | ...::Some(...) | main.rs:104:9:104:10 | s1 |
| main.rs:105:9:105:10 | [SSA] s2 | main.rs:110:11:110:12 | s2 |
| main.rs:105:9:105:10 | s2 | main.rs:105:9:105:10 | [SSA] s2 |
| main.rs:105:14:105:20 | Some(...) | main.rs:105:9:105:10 | s2 |
| main.rs:107:14:107:14 | [SSA] n | main.rs:107:25:107:25 | n |
| main.rs:107:14:107:14 | n | main.rs:107:14:107:14 | [SSA] n |
| main.rs:107:20:107:26 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } |
| main.rs:108:17:108:23 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } |
| main.rs:110:5:113:5 | match s2 { ... } | main.rs:103:27:114:1 | { ... } |
| main.rs:111:14:111:14 | [SSA] n | main.rs:111:25:111:25 | n |
| main.rs:111:14:111:14 | n | main.rs:111:14:111:14 | [SSA] n |
| main.rs:111:20:111:26 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } |
| main.rs:112:17:112:23 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } |
| main.rs:117:9:117:9 | [SSA] a | main.rs:118:5:118:5 | a |
| main.rs:117:9:117:9 | a | main.rs:117:9:117:9 | [SSA] a |
| main.rs:117:13:117:17 | { ... } | main.rs:117:9:117:9 | a |
| main.rs:117:15:117:15 | 0 | main.rs:117:13:117:17 | { ... } |
| main.rs:118:5:118:5 | a | main.rs:116:31:119:1 | { ... } |
| main.rs:121:22:121:22 | [SSA] b | main.rs:123:12:123:12 | b |
| main.rs:121:22:121:22 | b | main.rs:121:22:121:22 | [SSA] b |
| main.rs:121:22:121:28 | ...: bool | main.rs:121:22:121:22 | b |
| main.rs:122:9:122:9 | [SSA] a | main.rs:128:5:128:5 | a |
| main.rs:122:9:122:9 | a | main.rs:122:9:122:9 | [SSA] a |
| main.rs:122:13:127:5 | 'block: { ... } | main.rs:122:9:122:9 | a |
| main.rs:124:13:124:26 | break ''block 1 | main.rs:122:13:127:5 | 'block: { ... } |
| main.rs:124:26:124:26 | 1 | main.rs:124:13:124:26 | break ''block 1 |
| main.rs:126:9:126:9 | 2 | main.rs:122:13:127:5 | 'block: { ... } |
| main.rs:128:5:128:5 | a | main.rs:121:38:129:1 | { ... } |
| main.rs:131:22:131:22 | [SSA] b | main.rs:133:12:133:12 | b |
| main.rs:131:22:131:22 | b | main.rs:131:22:131:22 | [SSA] b |
| main.rs:131:22:131:28 | ...: bool | main.rs:131:22:131:22 | b |
| main.rs:132:9:132:9 | [SSA] a | main.rs:138:5:138:5 | a |
| main.rs:132:9:132:9 | a | main.rs:132:9:132:9 | [SSA] a |
| main.rs:132:13:137:5 | 'block: { ... } | main.rs:132:9:132:9 | a |
| main.rs:134:13:134:26 | break ''block 1 | main.rs:132:13:137:5 | 'block: { ... } |
| main.rs:134:26:134:26 | 1 | main.rs:134:13:134:26 | break ''block 1 |
| main.rs:136:9:136:22 | break ''block 2 | main.rs:132:13:137:5 | 'block: { ... } |
| main.rs:136:22:136:22 | 2 | main.rs:136:9:136:22 | break ''block 2 |
| main.rs:138:5:138:5 | a | main.rs:131:38:139:1 | { ... } |
| main.rs:105:14:105:28 | ...::Some(...) | main.rs:105:9:105:10 | s2 |
| main.rs:106:11:106:12 | s1 | main.rs:107:9:107:23 | TupleStructPat |
| main.rs:106:11:106:12 | s1 | main.rs:108:9:108:20 | ...::None |
| main.rs:107:22:107:22 | [SSA] n | main.rs:107:33:107:33 | n |
| main.rs:107:22:107:22 | n | main.rs:107:22:107:22 | [SSA] n |
| main.rs:107:28:107:34 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } |
| main.rs:108:25:108:31 | sink(...) | main.rs:106:5:109:5 | match s1 { ... } |
| main.rs:110:5:113:5 | match s2 { ... } | main.rs:103:37:114:1 | { ... } |
| main.rs:110:11:110:12 | s2 | main.rs:111:9:111:23 | TupleStructPat |
| main.rs:110:11:110:12 | s2 | main.rs:112:9:112:20 | ...::None |
| main.rs:111:22:111:22 | [SSA] n | main.rs:111:33:111:33 | n |
| main.rs:111:22:111:22 | n | main.rs:111:22:111:22 | [SSA] n |
| main.rs:111:28:111:34 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } |
| main.rs:112:25:112:31 | sink(...) | main.rs:110:5:113:5 | match s2 { ... } |
| main.rs:117:9:117:10 | [SSA] s1 | main.rs:119:11:119:12 | s1 |
| main.rs:117:9:117:10 | s1 | main.rs:117:9:117:10 | [SSA] s1 |
| main.rs:117:14:117:29 | Some(...) | main.rs:117:9:117:10 | s1 |
| main.rs:118:9:118:10 | [SSA] s2 | main.rs:123:11:123:12 | s2 |
| main.rs:118:9:118:10 | s2 | main.rs:118:9:118:10 | [SSA] s2 |
| main.rs:118:14:118:20 | Some(...) | main.rs:118:9:118:10 | s2 |
| main.rs:119:11:119:12 | s1 | main.rs:120:9:120:15 | TupleStructPat |
| main.rs:119:11:119:12 | s1 | main.rs:121:9:121:12 | None |
| main.rs:120:14:120:14 | [SSA] n | main.rs:120:25:120:25 | n |
| main.rs:120:14:120:14 | n | main.rs:120:14:120:14 | [SSA] n |
| main.rs:120:20:120:26 | sink(...) | main.rs:119:5:122:5 | match s1 { ... } |
| main.rs:121:17:121:23 | sink(...) | main.rs:119:5:122:5 | match s1 { ... } |
| main.rs:123:5:126:5 | match s2 { ... } | main.rs:116:39:127:1 | { ... } |
| main.rs:123:11:123:12 | s2 | main.rs:124:9:124:15 | TupleStructPat |
| main.rs:123:11:123:12 | s2 | main.rs:125:9:125:12 | None |
| main.rs:124:14:124:14 | [SSA] n | main.rs:124:25:124:25 | n |
| main.rs:124:14:124:14 | n | main.rs:124:14:124:14 | [SSA] n |
| main.rs:124:20:124:26 | sink(...) | main.rs:123:5:126:5 | match s2 { ... } |
| main.rs:125:17:125:23 | sink(...) | main.rs:123:5:126:5 | match s2 { ... } |
| main.rs:135:9:135:10 | [SSA] s1 | main.rs:137:11:137:12 | s1 |
| main.rs:135:9:135:10 | s1 | main.rs:135:9:135:10 | [SSA] s1 |
| main.rs:135:14:135:39 | ...::A(...) | main.rs:135:9:135:10 | s1 |
| main.rs:136:9:136:10 | [SSA] s2 | main.rs:144:11:144:12 | s2 |
| main.rs:136:9:136:10 | s2 | main.rs:136:9:136:10 | [SSA] s2 |
| main.rs:136:14:136:30 | ...::B(...) | main.rs:136:9:136:10 | s2 |
| main.rs:137:11:137:12 | s1 | main.rs:138:9:138:25 | TupleStructPat |
| main.rs:137:11:137:12 | s1 | main.rs:139:9:139:25 | TupleStructPat |
| main.rs:137:11:137:12 | s1 | main.rs:141:11:141:12 | s1 |
| main.rs:138:24:138:24 | [SSA] n | main.rs:138:35:138:35 | n |
| main.rs:138:24:138:24 | n | main.rs:138:24:138:24 | [SSA] n |
| main.rs:138:30:138:36 | sink(...) | main.rs:137:5:140:5 | match s1 { ... } |
| main.rs:139:24:139:24 | [SSA] n | main.rs:139:35:139:35 | n |
| main.rs:139:24:139:24 | n | main.rs:139:24:139:24 | [SSA] n |
| main.rs:139:30:139:36 | sink(...) | main.rs:137:5:140:5 | match s1 { ... } |
| main.rs:141:11:141:12 | s1 | main.rs:142:10:142:46 | ... \| ... |
| main.rs:142:10:142:46 | ... \| ... | main.rs:142:10:142:26 | TupleStructPat |
| main.rs:142:10:142:46 | ... \| ... | main.rs:142:30:142:46 | TupleStructPat |
| main.rs:142:10:142:46 | [SSA] [match(true)] phi | main.rs:142:57:142:57 | n |
| main.rs:142:25:142:25 | [SSA] [input] [match(true)] phi | main.rs:142:10:142:46 | [SSA] [match(true)] phi |
| main.rs:142:25:142:25 | [SSA] n | main.rs:142:25:142:25 | [SSA] [input] [match(true)] phi |
| main.rs:142:25:142:25 | n | main.rs:142:25:142:25 | [SSA] n |
| main.rs:142:45:142:45 | [SSA] [input] [match(true)] phi | main.rs:142:10:142:46 | [SSA] [match(true)] phi |
| main.rs:142:45:142:45 | [SSA] n | main.rs:142:45:142:45 | [SSA] [input] [match(true)] phi |
| main.rs:142:45:142:45 | n | main.rs:142:45:142:45 | [SSA] n |
| main.rs:142:52:142:58 | sink(...) | main.rs:141:5:143:5 | match s1 { ... } |
| main.rs:144:5:147:5 | match s2 { ... } | main.rs:134:48:148:1 | { ... } |
| main.rs:144:11:144:12 | s2 | main.rs:145:9:145:25 | TupleStructPat |
| main.rs:144:11:144:12 | s2 | main.rs:146:9:146:25 | TupleStructPat |
| main.rs:145:24:145:24 | [SSA] n | main.rs:145:35:145:35 | n |
| main.rs:145:24:145:24 | n | main.rs:145:24:145:24 | [SSA] n |
| main.rs:145:30:145:36 | sink(...) | main.rs:144:5:147:5 | match s2 { ... } |
| main.rs:146:24:146:24 | [SSA] n | main.rs:146:35:146:35 | n |
| main.rs:146:24:146:24 | n | main.rs:146:24:146:24 | [SSA] n |
| main.rs:146:30:146:36 | sink(...) | main.rs:144:5:147:5 | match s2 { ... } |
| main.rs:153:9:153:10 | [SSA] s1 | main.rs:155:11:155:12 | s1 |
| main.rs:153:9:153:10 | s1 | main.rs:153:9:153:10 | [SSA] s1 |
| main.rs:153:14:153:26 | A(...) | main.rs:153:9:153:10 | s1 |
| main.rs:154:9:154:10 | [SSA] s2 | main.rs:162:11:162:12 | s2 |
| main.rs:154:9:154:10 | s2 | main.rs:154:9:154:10 | [SSA] s2 |
| main.rs:154:14:154:17 | B(...) | main.rs:154:9:154:10 | s2 |
| main.rs:155:11:155:12 | s1 | main.rs:156:9:156:12 | TupleStructPat |
| main.rs:155:11:155:12 | s1 | main.rs:157:9:157:12 | TupleStructPat |
| main.rs:155:11:155:12 | s1 | main.rs:159:11:159:12 | s1 |
| main.rs:156:11:156:11 | [SSA] n | main.rs:156:22:156:22 | n |
| main.rs:156:11:156:11 | n | main.rs:156:11:156:11 | [SSA] n |
| main.rs:156:17:156:23 | sink(...) | main.rs:155:5:158:5 | match s1 { ... } |
| main.rs:157:11:157:11 | [SSA] n | main.rs:157:22:157:22 | n |
| main.rs:157:11:157:11 | n | main.rs:157:11:157:11 | [SSA] n |
| main.rs:157:17:157:23 | sink(...) | main.rs:155:5:158:5 | match s1 { ... } |
| main.rs:159:11:159:12 | s1 | main.rs:160:10:160:20 | ... \| ... |
| main.rs:160:10:160:20 | ... \| ... | main.rs:160:10:160:13 | TupleStructPat |
| main.rs:160:10:160:20 | ... \| ... | main.rs:160:17:160:20 | TupleStructPat |
| main.rs:160:10:160:20 | [SSA] [match(true)] phi | main.rs:160:31:160:31 | n |
| main.rs:160:12:160:12 | [SSA] [input] [match(true)] phi | main.rs:160:10:160:20 | [SSA] [match(true)] phi |
| main.rs:160:12:160:12 | [SSA] n | main.rs:160:12:160:12 | [SSA] [input] [match(true)] phi |
| main.rs:160:12:160:12 | n | main.rs:160:12:160:12 | [SSA] n |
| main.rs:160:19:160:19 | [SSA] [input] [match(true)] phi | main.rs:160:10:160:20 | [SSA] [match(true)] phi |
| main.rs:160:19:160:19 | [SSA] n | main.rs:160:19:160:19 | [SSA] [input] [match(true)] phi |
| main.rs:160:19:160:19 | n | main.rs:160:19:160:19 | [SSA] n |
| main.rs:160:26:160:32 | sink(...) | main.rs:159:5:161:5 | match s1 { ... } |
| main.rs:162:5:165:5 | match s2 { ... } | main.rs:152:50:166:1 | { ... } |
| main.rs:162:11:162:12 | s2 | main.rs:163:9:163:12 | TupleStructPat |
| main.rs:162:11:162:12 | s2 | main.rs:164:9:164:12 | TupleStructPat |
| main.rs:163:11:163:11 | [SSA] n | main.rs:163:22:163:22 | n |
| main.rs:163:11:163:11 | n | main.rs:163:11:163:11 | [SSA] n |
| main.rs:163:17:163:23 | sink(...) | main.rs:162:5:165:5 | match s2 { ... } |
| main.rs:164:11:164:11 | [SSA] n | main.rs:164:22:164:22 | n |
| main.rs:164:11:164:11 | n | main.rs:164:11:164:11 | [SSA] n |
| main.rs:164:17:164:23 | sink(...) | main.rs:162:5:165:5 | match s2 { ... } |
| main.rs:174:9:174:10 | [SSA] s1 | main.rs:178:11:178:12 | s1 |
| main.rs:174:9:174:10 | s1 | main.rs:174:9:174:10 | [SSA] s1 |
| main.rs:174:14:176:5 | ...::C {...} | main.rs:174:9:174:10 | s1 |
| main.rs:177:9:177:10 | [SSA] s2 | main.rs:185:11:185:12 | s2 |
| main.rs:177:9:177:10 | s2 | main.rs:177:9:177:10 | [SSA] s2 |
| main.rs:177:14:177:43 | ...::D {...} | main.rs:177:9:177:10 | s2 |
| main.rs:178:11:178:12 | s1 | main.rs:179:9:179:38 | ...::C {...} |
| main.rs:178:11:178:12 | s1 | main.rs:180:9:180:38 | ...::D {...} |
| main.rs:178:11:178:12 | s1 | main.rs:182:11:182:12 | s1 |
| main.rs:179:36:179:36 | [SSA] n | main.rs:179:48:179:48 | n |
| main.rs:179:36:179:36 | n | main.rs:179:36:179:36 | [SSA] n |
| main.rs:179:43:179:49 | sink(...) | main.rs:178:5:181:5 | match s1 { ... } |
| main.rs:180:36:180:36 | [SSA] n | main.rs:180:48:180:48 | n |
| main.rs:180:36:180:36 | n | main.rs:180:36:180:36 | [SSA] n |
| main.rs:180:43:180:49 | sink(...) | main.rs:178:5:181:5 | match s1 { ... } |
| main.rs:182:11:182:12 | s1 | main.rs:183:10:183:72 | ... \| ... |
| main.rs:183:10:183:72 | ... \| ... | main.rs:183:10:183:39 | ...::C {...} |
| main.rs:183:10:183:72 | ... \| ... | main.rs:183:43:183:72 | ...::D {...} |
| main.rs:183:10:183:72 | [SSA] [match(true)] phi | main.rs:183:83:183:83 | n |
| main.rs:183:37:183:37 | [SSA] [input] [match(true)] phi | main.rs:183:10:183:72 | [SSA] [match(true)] phi |
| main.rs:183:37:183:37 | [SSA] n | main.rs:183:37:183:37 | [SSA] [input] [match(true)] phi |
| main.rs:183:37:183:37 | n | main.rs:183:37:183:37 | [SSA] n |
| main.rs:183:70:183:70 | [SSA] [input] [match(true)] phi | main.rs:183:10:183:72 | [SSA] [match(true)] phi |
| main.rs:183:70:183:70 | [SSA] n | main.rs:183:70:183:70 | [SSA] [input] [match(true)] phi |
| main.rs:183:70:183:70 | n | main.rs:183:70:183:70 | [SSA] n |
| main.rs:183:78:183:84 | sink(...) | main.rs:182:5:184:5 | match s1 { ... } |
| main.rs:185:5:188:5 | match s2 { ... } | main.rs:173:49:189:1 | { ... } |
| main.rs:185:11:185:12 | s2 | main.rs:186:9:186:38 | ...::C {...} |
| main.rs:185:11:185:12 | s2 | main.rs:187:9:187:38 | ...::D {...} |
| main.rs:186:36:186:36 | [SSA] n | main.rs:186:48:186:48 | n |
| main.rs:186:36:186:36 | n | main.rs:186:36:186:36 | [SSA] n |
| main.rs:186:43:186:49 | sink(...) | main.rs:185:5:188:5 | match s2 { ... } |
| main.rs:187:36:187:36 | [SSA] n | main.rs:187:48:187:48 | n |
| main.rs:187:36:187:36 | n | main.rs:187:36:187:36 | [SSA] n |
| main.rs:187:43:187:49 | sink(...) | main.rs:185:5:188:5 | match s2 { ... } |
| main.rs:194:9:194:10 | [SSA] s1 | main.rs:198:11:198:12 | s1 |
| main.rs:194:9:194:10 | s1 | main.rs:194:9:194:10 | [SSA] s1 |
| main.rs:194:14:196:5 | C {...} | main.rs:194:9:194:10 | s1 |
| main.rs:197:9:197:10 | [SSA] s2 | main.rs:205:11:205:12 | s2 |
| main.rs:197:9:197:10 | s2 | main.rs:197:9:197:10 | [SSA] s2 |
| main.rs:197:14:197:29 | D {...} | main.rs:197:9:197:10 | s2 |
| main.rs:198:11:198:12 | s1 | main.rs:199:9:199:24 | C {...} |
| main.rs:198:11:198:12 | s1 | main.rs:200:9:200:24 | D {...} |
| main.rs:198:11:198:12 | s1 | main.rs:202:11:202:12 | s1 |
| main.rs:199:22:199:22 | [SSA] n | main.rs:199:34:199:34 | n |
| main.rs:199:22:199:22 | n | main.rs:199:22:199:22 | [SSA] n |
| main.rs:199:29:199:35 | sink(...) | main.rs:198:5:201:5 | match s1 { ... } |
| main.rs:200:22:200:22 | [SSA] n | main.rs:200:34:200:34 | n |
| main.rs:200:22:200:22 | n | main.rs:200:22:200:22 | [SSA] n |
| main.rs:200:29:200:35 | sink(...) | main.rs:198:5:201:5 | match s1 { ... } |
| main.rs:202:11:202:12 | s1 | main.rs:203:10:203:44 | ... \| ... |
| main.rs:203:10:203:44 | ... \| ... | main.rs:203:10:203:25 | C {...} |
| main.rs:203:10:203:44 | ... \| ... | main.rs:203:29:203:44 | D {...} |
| main.rs:203:10:203:44 | [SSA] [match(true)] phi | main.rs:203:55:203:55 | n |
| main.rs:203:23:203:23 | [SSA] [input] [match(true)] phi | main.rs:203:10:203:44 | [SSA] [match(true)] phi |
| main.rs:203:23:203:23 | [SSA] n | main.rs:203:23:203:23 | [SSA] [input] [match(true)] phi |
| main.rs:203:23:203:23 | n | main.rs:203:23:203:23 | [SSA] n |
| main.rs:203:42:203:42 | [SSA] [input] [match(true)] phi | main.rs:203:10:203:44 | [SSA] [match(true)] phi |
| main.rs:203:42:203:42 | [SSA] n | main.rs:203:42:203:42 | [SSA] [input] [match(true)] phi |
| main.rs:203:42:203:42 | n | main.rs:203:42:203:42 | [SSA] n |
| main.rs:203:50:203:56 | sink(...) | main.rs:202:5:204:5 | match s1 { ... } |
| main.rs:205:5:208:5 | match s2 { ... } | main.rs:193:51:209:1 | { ... } |
| main.rs:205:11:205:12 | s2 | main.rs:206:9:206:24 | C {...} |
| main.rs:205:11:205:12 | s2 | main.rs:207:9:207:24 | D {...} |
| main.rs:206:22:206:22 | [SSA] n | main.rs:206:34:206:34 | n |
| main.rs:206:22:206:22 | n | main.rs:206:22:206:22 | [SSA] n |
| main.rs:206:29:206:35 | sink(...) | main.rs:205:5:208:5 | match s2 { ... } |
| main.rs:207:22:207:22 | [SSA] n | main.rs:207:34:207:34 | n |
| main.rs:207:22:207:22 | n | main.rs:207:22:207:22 | [SSA] n |
| main.rs:207:29:207:35 | sink(...) | main.rs:205:5:208:5 | match s2 { ... } |
| main.rs:212:9:212:9 | [SSA] a | main.rs:213:5:213:5 | a |
| main.rs:212:9:212:9 | a | main.rs:212:9:212:9 | [SSA] a |
| main.rs:212:13:212:17 | { ... } | main.rs:212:9:212:9 | a |
| main.rs:212:15:212:15 | 0 | main.rs:212:13:212:17 | { ... } |
| main.rs:213:5:213:5 | a | main.rs:211:31:214:1 | { ... } |
| main.rs:216:22:216:22 | [SSA] b | main.rs:218:12:218:12 | b |
| main.rs:216:22:216:22 | b | main.rs:216:22:216:22 | [SSA] b |
| main.rs:216:22:216:28 | ...: bool | main.rs:216:22:216:22 | b |
| main.rs:217:9:217:9 | [SSA] a | main.rs:223:5:223:5 | a |
| main.rs:217:9:217:9 | a | main.rs:217:9:217:9 | [SSA] a |
| main.rs:217:13:222:5 | 'block: { ... } | main.rs:217:9:217:9 | a |
| main.rs:219:13:219:26 | break ''block 1 | main.rs:217:13:222:5 | 'block: { ... } |
| main.rs:219:26:219:26 | 1 | main.rs:219:13:219:26 | break ''block 1 |
| main.rs:221:9:221:9 | 2 | main.rs:217:13:222:5 | 'block: { ... } |
| main.rs:223:5:223:5 | a | main.rs:216:38:224:1 | { ... } |
| main.rs:226:22:226:22 | [SSA] b | main.rs:228:12:228:12 | b |
| main.rs:226:22:226:22 | b | main.rs:226:22:226:22 | [SSA] b |
| main.rs:226:22:226:28 | ...: bool | main.rs:226:22:226:22 | b |
| main.rs:227:9:227:9 | [SSA] a | main.rs:233:5:233:5 | a |
| main.rs:227:9:227:9 | a | main.rs:227:9:227:9 | [SSA] a |
| main.rs:227:13:232:5 | 'block: { ... } | main.rs:227:9:227:9 | a |
| main.rs:229:13:229:26 | break ''block 1 | main.rs:227:13:232:5 | 'block: { ... } |
| main.rs:229:26:229:26 | 1 | main.rs:229:13:229:26 | break ''block 1 |
| main.rs:231:9:231:22 | break ''block 2 | main.rs:227:13:232:5 | 'block: { ... } |
| main.rs:231:22:231:22 | 2 | main.rs:231:9:231:22 | break ''block 2 |
| main.rs:233:5:233:5 | a | main.rs:226:38:234:1 | { ... } |
storeStep
| main.rs:117:19:117:28 | source(...) | Some | main.rs:117:14:117:29 | Some(...) |
| main.rs:118:19:118:19 | 2 | Some | main.rs:118:14:118:20 | Some(...) |
| main.rs:135:29:135:38 | source(...) | A | main.rs:135:14:135:39 | ...::A(...) |
| main.rs:136:29:136:29 | 2 | B | main.rs:136:14:136:30 | ...::B(...) |
| main.rs:175:18:175:27 | source(...) | C | main.rs:174:14:176:5 | ...::C {...} |
| main.rs:177:41:177:41 | 2 | D | main.rs:177:14:177:43 | ...::D {...} |
| main.rs:240:27:240:27 | 0 | Some | main.rs:240:22:240:28 | Some(...) |
readStep
| main.rs:33:9:33:15 | TupleStructPat | Some | main.rs:33:14:33:14 | _ |
| main.rs:120:9:120:15 | TupleStructPat | Some | main.rs:120:14:120:14 | n |
| main.rs:124:9:124:15 | TupleStructPat | Some | main.rs:124:14:124:14 | n |
| main.rs:138:9:138:25 | TupleStructPat | A | main.rs:138:24:138:24 | n |
| main.rs:139:9:139:25 | TupleStructPat | B | main.rs:139:24:139:24 | n |
| main.rs:142:10:142:26 | TupleStructPat | A | main.rs:142:25:142:25 | n |
| main.rs:142:30:142:46 | TupleStructPat | B | main.rs:142:45:142:45 | n |
| main.rs:145:9:145:25 | TupleStructPat | A | main.rs:145:24:145:24 | n |
| main.rs:146:9:146:25 | TupleStructPat | B | main.rs:146:24:146:24 | n |
| main.rs:179:9:179:38 | ...::C {...} | C | main.rs:179:36:179:36 | n |
| main.rs:180:9:180:38 | ...::D {...} | D | main.rs:180:36:180:36 | n |
| main.rs:183:10:183:39 | ...::C {...} | C | main.rs:183:37:183:37 | n |
| main.rs:183:43:183:72 | ...::D {...} | D | main.rs:183:70:183:70 | n |
| main.rs:186:9:186:38 | ...::C {...} | C | main.rs:186:36:186:36 | n |
| main.rs:187:9:187:38 | ...::D {...} | D | main.rs:187:36:187:36 | n |

View File

@@ -1,5 +1,8 @@
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.internal.DataFlowImpl
from DataFlow::Node pred, DataFlow::Node succ
where DataFlow::localFlowStep(pred, succ)
select pred, succ
query predicate localStep = DataFlow::localFlowStep/2;
query predicate storeStep = RustDataFlow::storeStep/3;
query predicate readStep = RustDataFlow::readStep/3;

View File

@@ -1,28 +1,72 @@
models
edges
| main.rs:19:13:19:21 | source(...) : unit | main.rs:20:10:20:10 | s | provenance | |
| main.rs:24:13:24:21 | source(...) : unit | main.rs:27:10:27:10 | c | provenance | |
| main.rs:31:13:31:21 | source(...) : unit | main.rs:36:10:36:10 | b | provenance | |
| main.rs:45:15:45:23 | source(...) : unit | main.rs:47:10:47:10 | b | provenance | |
| main.rs:53:9:53:17 | source(...) : unit | main.rs:54:10:54:10 | i | provenance | |
| main.rs:19:13:19:21 | source(...) | main.rs:20:10:20:10 | s | provenance | |
| main.rs:24:13:24:21 | source(...) | main.rs:27:10:27:10 | c | provenance | |
| main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | provenance | |
| main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | provenance | |
| main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | provenance | |
| main.rs:117:14:117:29 | Some(...) [Some] | main.rs:120:9:120:15 | TupleStructPat [Some] | provenance | |
| main.rs:117:19:117:28 | source(...) | main.rs:117:14:117:29 | Some(...) [Some] | provenance | |
| main.rs:120:9:120:15 | TupleStructPat [Some] | main.rs:120:14:120:14 | n | provenance | |
| main.rs:120:14:120:14 | n | main.rs:120:25:120:25 | n | provenance | |
| main.rs:135:14:135:39 | ...::A(...) [A] | main.rs:138:9:138:25 | TupleStructPat [A] | provenance | |
| main.rs:135:14:135:39 | ...::A(...) [A] | main.rs:142:10:142:26 | TupleStructPat [A] | provenance | |
| main.rs:135:29:135:38 | source(...) | main.rs:135:14:135:39 | ...::A(...) [A] | provenance | |
| main.rs:138:9:138:25 | TupleStructPat [A] | main.rs:138:24:138:24 | n | provenance | |
| main.rs:138:24:138:24 | n | main.rs:138:35:138:35 | n | provenance | |
| main.rs:142:10:142:26 | TupleStructPat [A] | main.rs:142:25:142:25 | n | provenance | |
| main.rs:142:25:142:25 | n | main.rs:142:57:142:57 | n | provenance | |
| main.rs:174:14:176:5 | ...::C {...} [C] | main.rs:179:9:179:38 | ...::C {...} [C] | provenance | |
| main.rs:174:14:176:5 | ...::C {...} [C] | main.rs:183:10:183:39 | ...::C {...} [C] | provenance | |
| main.rs:175:18:175:27 | source(...) | main.rs:174:14:176:5 | ...::C {...} [C] | provenance | |
| main.rs:179:9:179:38 | ...::C {...} [C] | main.rs:179:36:179:36 | n | provenance | |
| main.rs:179:36:179:36 | n | main.rs:179:48:179:48 | n | provenance | |
| main.rs:183:10:183:39 | ...::C {...} [C] | main.rs:183:37:183:37 | n | provenance | |
| main.rs:183:37:183:37 | n | main.rs:183:83:183:83 | n | provenance | |
nodes
| main.rs:15:10:15:18 | source(...) | semmle.label | source(...) |
| main.rs:19:13:19:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:19:13:19:21 | source(...) | semmle.label | source(...) |
| main.rs:20:10:20:10 | s | semmle.label | s |
| main.rs:24:13:24:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:24:13:24:21 | source(...) | semmle.label | source(...) |
| main.rs:27:10:27:10 | c | semmle.label | c |
| main.rs:31:13:31:21 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:31:13:31:21 | source(...) | semmle.label | source(...) |
| main.rs:36:10:36:10 | b | semmle.label | b |
| main.rs:45:15:45:23 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:45:15:45:23 | source(...) | semmle.label | source(...) |
| main.rs:47:10:47:10 | b | semmle.label | b |
| main.rs:53:9:53:17 | source(...) : unit | semmle.label | source(...) : unit |
| main.rs:53:9:53:17 | source(...) | semmle.label | source(...) |
| main.rs:54:10:54:10 | i | semmle.label | i |
| main.rs:117:14:117:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:117:19:117:28 | source(...) | semmle.label | source(...) |
| main.rs:120:9:120:15 | TupleStructPat [Some] | semmle.label | TupleStructPat [Some] |
| main.rs:120:14:120:14 | n | semmle.label | n |
| main.rs:120:25:120:25 | n | semmle.label | n |
| main.rs:135:14:135:39 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:135:29:135:38 | source(...) | semmle.label | source(...) |
| main.rs:138:9:138:25 | TupleStructPat [A] | semmle.label | TupleStructPat [A] |
| main.rs:138:24:138:24 | n | semmle.label | n |
| main.rs:138:35:138:35 | n | semmle.label | n |
| main.rs:142:10:142:26 | TupleStructPat [A] | semmle.label | TupleStructPat [A] |
| main.rs:142:25:142:25 | n | semmle.label | n |
| main.rs:142:57:142:57 | n | semmle.label | n |
| main.rs:174:14:176:5 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:175:18:175:27 | source(...) | semmle.label | source(...) |
| main.rs:179:9:179:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:179:36:179:36 | n | semmle.label | n |
| main.rs:179:48:179:48 | n | semmle.label | n |
| main.rs:183:10:183:39 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:183:37:183:37 | n | semmle.label | n |
| main.rs:183:83:183:83 | n | semmle.label | n |
subpaths
testFailures
#select
| main.rs:15:10:15:18 | source(...) | main.rs:15:10:15:18 | source(...) | main.rs:15:10:15:18 | source(...) | $@ | main.rs:15:10:15:18 | source(...) | source(...) |
| main.rs:20:10:20:10 | s | main.rs:19:13:19:21 | source(...) : unit | main.rs:20:10:20:10 | s | $@ | main.rs:19:13:19:21 | source(...) : unit | source(...) : unit |
| main.rs:27:10:27:10 | c | main.rs:24:13:24:21 | source(...) : unit | main.rs:27:10:27:10 | c | $@ | main.rs:24:13:24:21 | source(...) : unit | source(...) : unit |
| main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | source(...) : unit | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | source(...) : unit | source(...) : unit |
| main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | source(...) : unit | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | source(...) : unit | source(...) : unit |
| main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | source(...) : unit | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | source(...) : unit | source(...) : unit |
| main.rs:20:10:20:10 | s | main.rs:19:13:19:21 | source(...) | main.rs:20:10:20:10 | s | $@ | main.rs:19:13:19:21 | source(...) | source(...) |
| main.rs:27:10:27:10 | c | main.rs:24:13:24:21 | source(...) | main.rs:27:10:27:10 | c | $@ | main.rs:24:13:24:21 | source(...) | source(...) |
| main.rs:36:10:36:10 | b | main.rs:31:13:31:21 | source(...) | main.rs:36:10:36:10 | b | $@ | main.rs:31:13:31:21 | source(...) | source(...) |
| main.rs:47:10:47:10 | b | main.rs:45:15:45:23 | source(...) | main.rs:47:10:47:10 | b | $@ | main.rs:45:15:45:23 | source(...) | source(...) |
| main.rs:54:10:54:10 | i | main.rs:53:9:53:17 | source(...) | main.rs:54:10:54:10 | i | $@ | main.rs:53:9:53:17 | source(...) | source(...) |
| main.rs:120:25:120:25 | n | main.rs:117:19:117:28 | source(...) | main.rs:120:25:120:25 | n | $@ | main.rs:117:19:117:28 | source(...) | source(...) |
| main.rs:138:35:138:35 | n | main.rs:135:29:135:38 | source(...) | main.rs:138:35:138:35 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) |
| main.rs:142:57:142:57 | n | main.rs:135:29:135:38 | source(...) | main.rs:142:57:142:57 | n | $@ | main.rs:135:29:135:38 | source(...) | source(...) |
| main.rs:179:48:179:48 | n | main.rs:175:18:175:27 | source(...) | main.rs:179:48:179:48 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) |
| main.rs:183:83:183:83 | n | main.rs:175:18:175:27 | source(...) | main.rs:183:83:183:83 | n | $@ | main.rs:175:18:175:27 | source(...) | source(...) |

View File

@@ -16,24 +16,24 @@ fn direct() {
}
fn variable_usage() {
let s = source(1);
sink(s); // $ hasValueFlow=1
let s = source(2);
sink(s); // $ hasValueFlow=2
}
fn if_expression(cond: bool) {
let a = source(1);
let a = source(3);
let b = 2;
let c = if cond { a } else { b };
sink(c); // $ hasValueFlow=1
sink(c); // $ hasValueFlow=3
}
fn match_expression(m: Option<i64>) {
let a = source(1);
let a = source(4);
let b = match m {
Some(_) => a,
None => 0,
};
sink(b); // $ hasValueFlow=1
sink(b); // $ hasValueFlow=4
}
fn loop_with_break() {
@@ -42,29 +42,29 @@ fn loop_with_break() {
};
sink(a);
let b = loop {
break source(1);
break source(5);
};
sink(b); // $ hasValueFlow=1
sink(b); // $ hasValueFlow=5
}
fn assignment() {
let mut i = 1;
sink(i);
i = source(2);
sink(i); // $ hasValueFlow=2
i = source(6);
sink(i); // $ hasValueFlow=6
}
// -----------------------------------------------------------------------------
// Data flow through data structures by writing and reading
fn box_deref() {
let i = Box::new(source(1));
sink(*i); // $ MISSING: hasValueFlow=1
let i = Box::new(source(7));
sink(*i); // $ MISSING: hasValueFlow=7
}
fn tuple() {
let a = (source(1), 2);
sink(a.0); // $ MISSING: hasValueFlow=1
let a = (source(8), 2);
sink(a.0); // $ MISSING: hasValueFlow=8
sink(a.1);
}
@@ -76,13 +76,13 @@ struct Point {
fn struct_field() {
let p = Point {
x: source(1),
x: source(9),
y: 2,
z: source(3),
z: source(10),
};
sink(p.x); // MISSING: hasValueFlow=1
sink(p.x); // $ MISSING: hasValueFlow=9
sink(p.y);
sink(p.z); // MISSING: hasValueFlow=3
sink(p.z); // $ MISSING: hasValueFlow=10
}
// -----------------------------------------------------------------------------
@@ -90,21 +90,34 @@ fn struct_field() {
fn struct_pattern_match() {
let p = Point {
x: source(1),
x: source(11),
y: 2,
z: source(3),
z: source(12),
};
let Point { x: a, y: b, z: c } = p;
sink(a); // MISSING: hasValueFlow=1
sink(a); // $ MISSING: hasValueFlow=11
sink(b);
sink(c); // MISSING: hasValueFlow=3
sink(c); // $ MISSING: hasValueFlow=12
}
fn option_pattern_match() {
let s1 = Some(source(1));
fn option_pattern_match_qualified() {
let s1 = Option::Some(source(13));
let s2 = Option::Some(2);
match s1 {
Option::Some(n) => sink(n), // $ MISSING: hasValueFlow=13
Option::None => sink(0),
}
match s2 {
Option::Some(n) => sink(n),
Option::None => sink(0),
}
}
fn option_pattern_match_unqualified() {
let s1 = Some(source(14));
let s2 = Some(2);
match s1 {
Some(n) => sink(n), // MISSING: hasValueFlow=3
Some(n) => sink(n), // $ hasValueFlow=14
None => sink(0),
}
match s2 {
@@ -113,6 +126,88 @@ fn option_pattern_match() {
}
}
enum MyTupleEnum {
A(i64),
B(i64),
}
fn custom_tuple_enum_pattern_match_qualified() {
let s1 = MyTupleEnum::A(source(15));
let s2 = MyTupleEnum::B(2);
match s1 {
MyTupleEnum::A(n) => sink(n), // $ hasValueFlow=15
MyTupleEnum::B(n) => sink(n),
}
match s1 {
(MyTupleEnum::A(n) | MyTupleEnum::B(n)) => sink(n), // $ hasValueFlow=15
}
match s2 {
MyTupleEnum::A(n) => sink(n),
MyTupleEnum::B(n) => sink(n),
}
}
use crate::MyTupleEnum::*;
fn custom_tuple_enum_pattern_match_unqualified() {
let s1 = A(source(16));
let s2 = B(2);
match s1 {
A(n) => sink(n), // $ MISSING: hasValueFlow=16
B(n) => sink(n),
}
match s1 {
(A(n) | B(n)) => sink(n), // $ MISSING: hasValueFlow=16
}
match s2 {
A(n) => sink(n),
B(n) => sink(n),
}
}
enum MyRecordEnum {
C { field_c: i64 },
D { field_d: i64 },
}
fn custom_record_enum_pattern_match_qualified() {
let s1 = MyRecordEnum::C {
field_c: source(17),
};
let s2 = MyRecordEnum::D { field_d: 2 };
match s1 {
MyRecordEnum::C { field_c: n } => sink(n), // $ hasValueFlow=17
MyRecordEnum::D { field_d: n } => sink(n),
}
match s1 {
(MyRecordEnum::C { field_c: n } | MyRecordEnum::D { field_d: n }) => sink(n), // $ hasValueFlow=17
}
match s2 {
MyRecordEnum::C { field_c: n } => sink(n),
MyRecordEnum::D { field_d: n } => sink(n),
}
}
use crate::MyRecordEnum::*;
fn custom_record_enum_pattern_match_unqualified() {
let s1 = C {
field_c: source(18),
};
let s2 = D { field_d: 2 };
match s1 {
C { field_c: n } => sink(n), // $ MISSING: hasValueFlow=18
D { field_d: n } => sink(n),
}
match s1 {
(C { field_c: n } | D { field_d: n }) => sink(n), // $ MISSING: hasValueFlow=18
}
match s2 {
C { field_c: n } => sink(n),
D { field_d: n } => sink(n),
}
}
fn block_expression1() -> i64 {
let a = { 0 };
a
@@ -149,7 +244,12 @@ fn main() {
tuple();
struct_field();
struct_pattern_match();
option_pattern_match();
option_pattern_match_qualified();
option_pattern_match_unqualified();
custom_tuple_enum_pattern_match_qualified();
custom_tuple_enum_pattern_match_unqualified();
custom_record_enum_pattern_match_qualified();
custom_record_enum_pattern_match_unqualified();
block_expression1();
block_expression2(true);
block_expression3(true);

View File

@@ -0,0 +1,21 @@
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.Concepts
import utils.InlineFlowTest
/**
* Configuration for flow from any threat model source to an argument of the function `sink`.
*/
module MyFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelSource }
predicate isSink(DataFlow::Node sink) {
any(CallExpr call |
call.getFunction().(PathExpr).getPath().getResolvedPath() = "crate::test::sink"
).getArgList().getAnArg() = sink.asExpr().getExpr()
}
}
module MyFlowTest = TaintFlowTest<MyFlowConfig>;
import MyFlowTest

View File

@@ -0,0 +1,17 @@
| test.rs:8:10:8:30 | ...::var(...) | Flow source 'EnvironmentSource' of type environment. |
| test.rs:9:10:9:33 | ...::var_os(...) | Flow source 'EnvironmentSource' of type environment. |
| test.rs:11:16:11:36 | ...::var(...) | Flow source 'EnvironmentSource' of type environment. |
| test.rs:12:16:12:39 | ...::var_os(...) | Flow source 'EnvironmentSource' of type environment. |
| test.rs:17:25:17:40 | ...::vars(...) | Flow source 'EnvironmentSource' of type environment. |
| test.rs:22:25:22:43 | ...::vars_os(...) | Flow source 'EnvironmentSource' of type environment. |
| test.rs:29:29:29:44 | ...::args(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:32:16:32:31 | ...::args(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:33:16:33:34 | ...::args_os(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:40:16:40:31 | ...::args(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:44:16:44:34 | ...::args_os(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:50:15:50:37 | ...::current_dir(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:51:15:51:37 | ...::current_exe(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:52:16:52:35 | ...::home_dir(...) | Flow source 'CommandLineArgs' of type commandargs. |
| test.rs:60:26:60:70 | ...::get(...) | Flow source 'RemoteSource' of type remote (DEFAULT). |
| test.rs:63:26:63:70 | ...::get(...) | Flow source 'RemoteSource' of type remote (DEFAULT). |
| test.rs:66:26:66:60 | ...::get(...) | Flow source 'RemoteSource' of type remote (DEFAULT). |

View File

@@ -0,0 +1,2 @@
query: queries/summary/TaintSources.ql
postprocess: utils/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,3 @@
qltest_cargo_check: true
qltest_dependencies:
- reqwest = { version = "0.12.9", features = ["blocking"] }

View File

@@ -0,0 +1,36 @@
// --- stubs for the "reqwest" library ---
/*
--- we don't seem to have a way to use this, hence we currently test against the real reqwest library
#[derive(Debug)]
pub struct Error { }
pub mod blocking {
pub struct Response { }
impl Response {
pub fn text(self) -> Result<String, super::Error> {
Ok("".to_string())
}
}
pub fn get<T>(url: T) -> Result<Response, super::Error> {
let _url = url;
Ok(Response {})
}
}
pub struct Response { }
impl Response {
pub async fn text(self) -> Result<String, Error> {
Ok("".to_string())
}
}
pub async fn get<T>(url: T) -> Result<Response, Error> {
let _url = url;
Ok(Response {})
}
*/

View File

@@ -0,0 +1,70 @@
#![allow(deprecated)]
fn sink<T>(_: T) { }
// --- tests ---
fn test_env_vars() {
sink(std::env::var("HOME")); // $ Alert[rust/summary/taint-sources] hasTaintFlow
sink(std::env::var_os("PATH")); // $ Alert[rust/summary/taint-sources] hasTaintFlow
let var1 = std::env::var("HOME").expect("HOME not set"); // $ Alert[rust/summary/taint-sources]
let var2 = std::env::var_os("PATH").unwrap(); // $ Alert[rust/summary/taint-sources]
sink(var1); // $ MISSING: hasTaintFlow
sink(var2); // $ MISSING: hasTaintFlow
for (key, value) in std::env::vars() { // $ Alert[rust/summary/taint-sources]
sink(key); // $ MISSING: hasTaintFlow
sink(value); // $ MISSING: hasTaintFlow
}
for (key, value) in std::env::vars_os() { // $ Alert[rust/summary/taint-sources]
sink(key); // $ MISSING: hasTaintFlow
sink(value); // $ MISSING: hasTaintFlow
}
}
fn test_env_args() {
let args: Vec<String> = std::env::args().collect(); // $ Alert[rust/summary/taint-sources]
let my_path = &args[0];
let arg1 = &args[1];
let arg2 = std::env::args().nth(2).unwrap(); // $ Alert[rust/summary/taint-sources]
let arg3 = std::env::args_os().nth(3).unwrap(); // $ Alert[rust/summary/taint-sources]
sink(my_path); // $ MISSING: hasTaintFlow
sink(arg1); // $ MISSING: hasTaintFlow
sink(arg2); // $ MISSING: hasTaintFlow
sink(arg3); // $ MISSING: hasTaintFlow
for arg in std::env::args() { // $ Alert[rust/summary/taint-sources]
sink(arg); // $ MISSING: hasTaintFlow
}
for arg in std::env::args_os() { // $ Alert[rust/summary/taint-sources]
sink(arg); // $ MISSING: hasTaintFlow
}
}
fn test_env_dirs() {
let dir = std::env::current_dir().expect("FAILED"); // $ Alert[rust/summary/taint-sources]
let exe = std::env::current_exe().expect("FAILED"); // $ Alert[rust/summary/taint-sources]
let home = std::env::home_dir().expect("FAILED"); // $ Alert[rust/summary/taint-sources]
sink(dir); // $ MISSING: hasTaintFlow
sink(exe); // $ MISSING: hasTaintFlow
sink(home); // $ MISSING: hasTaintFlow
}
async fn test_reqwest() -> Result<(), reqwest::Error> {
let remote_string1 = reqwest::blocking::get("http://example.com/")?.text()?; // $ Alert[rust/summary/taint-sources]
sink(remote_string1); // $ MISSING: hasTaintFlow
let remote_string2 = reqwest::blocking::get("http://example.com/").unwrap().text().unwrap(); // $ Alert[rust/summary/taint-sources]
sink(remote_string2); // $ MISSING: hasTaintFlow
let remote_string3 = reqwest::get("http://example.com/").await?.text().await?; // $ Alert[rust/summary/taint-sources]
sink(remote_string3); // $ MISSING: hasTaintFlow
Ok(())
}

View File

@@ -1078,195 +1078,201 @@ edges
| variables.rs:483:9:483:24 | ExprStmt | variables.rs:483:16:483:19 | self | |
| variables.rs:483:16:483:19 | self | variables.rs:483:16:483:23 | self.val | |
| variables.rs:483:16:483:23 | self.val | variables.rs:483:9:483:23 | return ... | |
| variables.rs:487:1:494:1 | enter fn structs | variables.rs:488:5:488:36 | let ... = ... | |
| variables.rs:487:1:494:1 | exit fn structs (normal) | variables.rs:487:1:494:1 | exit fn structs | |
| variables.rs:487:14:494:1 | { ... } | variables.rs:487:1:494:1 | exit fn structs (normal) | |
| variables.rs:488:5:488:36 | let ... = ... | variables.rs:488:33:488:33 | 1 | |
| variables.rs:488:9:488:13 | a | variables.rs:489:5:489:26 | ExprStmt | match |
| variables.rs:488:17:488:35 | MyStruct {...} | variables.rs:488:9:488:13 | a | |
| variables.rs:488:33:488:33 | 1 | variables.rs:488:17:488:35 | MyStruct {...} | |
| variables.rs:489:5:489:13 | print_i64 | variables.rs:489:15:489:15 | a | |
| variables.rs:489:5:489:25 | print_i64(...) | variables.rs:490:5:490:14 | ExprStmt | |
| variables.rs:489:5:489:26 | ExprStmt | variables.rs:489:5:489:13 | print_i64 | |
| variables.rs:489:15:489:15 | a | variables.rs:489:15:489:24 | ... .my_get(...) | |
| variables.rs:489:15:489:24 | ... .my_get(...) | variables.rs:489:5:489:25 | print_i64(...) | |
| variables.rs:490:5:490:5 | a | variables.rs:490:5:490:9 | a.val | |
| variables.rs:490:5:490:9 | a.val | variables.rs:490:13:490:13 | 5 | |
| variables.rs:490:5:490:13 | ... = ... | variables.rs:491:5:491:26 | ExprStmt | |
| variables.rs:490:5:490:14 | ExprStmt | variables.rs:490:5:490:5 | a | |
| variables.rs:490:13:490:13 | 5 | variables.rs:490:5:490:13 | ... = ... | |
| variables.rs:491:5:491:13 | print_i64 | variables.rs:491:15:491:15 | a | |
| variables.rs:491:5:491:25 | print_i64(...) | variables.rs:492:5:492:28 | ExprStmt | |
| variables.rs:491:5:491:26 | ExprStmt | variables.rs:491:5:491:13 | print_i64 | |
| variables.rs:491:15:491:15 | a | variables.rs:491:15:491:24 | ... .my_get(...) | |
| variables.rs:491:15:491:24 | ... .my_get(...) | variables.rs:491:5:491:25 | print_i64(...) | |
| variables.rs:492:5:492:5 | a | variables.rs:492:25:492:25 | 2 | |
| variables.rs:492:5:492:27 | ... = ... | variables.rs:493:5:493:26 | ExprStmt | |
| variables.rs:492:5:492:28 | ExprStmt | variables.rs:492:5:492:5 | a | |
| variables.rs:492:9:492:27 | MyStruct {...} | variables.rs:492:5:492:27 | ... = ... | |
| variables.rs:492:25:492:25 | 2 | variables.rs:492:9:492:27 | MyStruct {...} | |
| variables.rs:486:5:488:5 | enter fn id | variables.rs:486:11:486:14 | self | |
| variables.rs:486:5:488:5 | exit fn id (normal) | variables.rs:486:5:488:5 | exit fn id | |
| variables.rs:486:11:486:14 | SelfParam | variables.rs:487:9:487:12 | self | |
| variables.rs:486:11:486:14 | self | variables.rs:486:11:486:14 | SelfParam | |
| variables.rs:486:25:488:5 | { ... } | variables.rs:486:5:488:5 | exit fn id (normal) | |
| variables.rs:487:9:487:12 | self | variables.rs:486:25:488:5 | { ... } | |
| variables.rs:491:1:498:1 | enter fn structs | variables.rs:492:5:492:36 | let ... = ... | |
| variables.rs:491:1:498:1 | exit fn structs (normal) | variables.rs:491:1:498:1 | exit fn structs | |
| variables.rs:491:14:498:1 | { ... } | variables.rs:491:1:498:1 | exit fn structs (normal) | |
| variables.rs:492:5:492:36 | let ... = ... | variables.rs:492:33:492:33 | 1 | |
| variables.rs:492:9:492:13 | a | variables.rs:493:5:493:26 | ExprStmt | match |
| variables.rs:492:17:492:35 | MyStruct {...} | variables.rs:492:9:492:13 | a | |
| variables.rs:492:33:492:33 | 1 | variables.rs:492:17:492:35 | MyStruct {...} | |
| variables.rs:493:5:493:13 | print_i64 | variables.rs:493:15:493:15 | a | |
| variables.rs:493:5:493:25 | print_i64(...) | variables.rs:487:14:494:1 | { ... } | |
| variables.rs:493:5:493:25 | print_i64(...) | variables.rs:494:5:494:14 | ExprStmt | |
| variables.rs:493:5:493:26 | ExprStmt | variables.rs:493:5:493:13 | print_i64 | |
| variables.rs:493:15:493:15 | a | variables.rs:493:15:493:24 | ... .my_get(...) | |
| variables.rs:493:15:493:24 | ... .my_get(...) | variables.rs:493:5:493:25 | print_i64(...) | |
| variables.rs:496:1:503:1 | enter fn ref_arg | variables.rs:497:5:497:15 | let ... = 16 | |
| variables.rs:496:1:503:1 | exit fn ref_arg (normal) | variables.rs:496:1:503:1 | exit fn ref_arg | |
| variables.rs:496:14:503:1 | { ... } | variables.rs:496:1:503:1 | exit fn ref_arg (normal) | |
| variables.rs:497:5:497:15 | let ... = 16 | variables.rs:497:13:497:14 | 16 | |
| variables.rs:497:9:497:9 | x | variables.rs:498:5:498:22 | ExprStmt | match |
| variables.rs:497:13:497:14 | 16 | variables.rs:497:9:497:9 | x | |
| variables.rs:498:5:498:17 | print_i64_ref | variables.rs:498:20:498:20 | x | |
| variables.rs:498:5:498:21 | print_i64_ref(...) | variables.rs:499:5:499:17 | ExprStmt | |
| variables.rs:498:5:498:22 | ExprStmt | variables.rs:498:5:498:17 | print_i64_ref | |
| variables.rs:498:19:498:20 | &x | variables.rs:498:5:498:21 | print_i64_ref(...) | |
| variables.rs:498:20:498:20 | x | variables.rs:498:19:498:20 | &x | |
| variables.rs:499:5:499:13 | print_i64 | variables.rs:499:15:499:15 | x | |
| variables.rs:499:5:499:16 | print_i64(...) | variables.rs:501:5:501:15 | let ... = 17 | |
| variables.rs:499:5:499:17 | ExprStmt | variables.rs:499:5:499:13 | print_i64 | |
| variables.rs:499:15:499:15 | x | variables.rs:499:5:499:16 | print_i64(...) | |
| variables.rs:501:5:501:15 | let ... = 17 | variables.rs:501:13:501:14 | 17 | |
| variables.rs:501:9:501:9 | z | variables.rs:502:5:502:22 | ExprStmt | match |
| variables.rs:501:13:501:14 | 17 | variables.rs:501:9:501:9 | z | |
| variables.rs:502:5:502:17 | print_i64_ref | variables.rs:502:20:502:20 | z | |
| variables.rs:502:5:502:21 | print_i64_ref(...) | variables.rs:496:14:503:1 | { ... } | |
| variables.rs:494:5:494:5 | a | variables.rs:494:5:494:9 | a.val | |
| variables.rs:494:5:494:9 | a.val | variables.rs:494:13:494:13 | 5 | |
| variables.rs:494:5:494:13 | ... = ... | variables.rs:495:5:495:26 | ExprStmt | |
| variables.rs:494:5:494:14 | ExprStmt | variables.rs:494:5:494:5 | a | |
| variables.rs:494:13:494:13 | 5 | variables.rs:494:5:494:13 | ... = ... | |
| variables.rs:495:5:495:13 | print_i64 | variables.rs:495:15:495:15 | a | |
| variables.rs:495:5:495:25 | print_i64(...) | variables.rs:496:5:496:28 | ExprStmt | |
| variables.rs:495:5:495:26 | ExprStmt | variables.rs:495:5:495:13 | print_i64 | |
| variables.rs:495:15:495:15 | a | variables.rs:495:15:495:24 | ... .my_get(...) | |
| variables.rs:495:15:495:24 | ... .my_get(...) | variables.rs:495:5:495:25 | print_i64(...) | |
| variables.rs:496:5:496:5 | a | variables.rs:496:25:496:25 | 2 | |
| variables.rs:496:5:496:27 | ... = ... | variables.rs:497:5:497:26 | ExprStmt | |
| variables.rs:496:5:496:28 | ExprStmt | variables.rs:496:5:496:5 | a | |
| variables.rs:496:9:496:27 | MyStruct {...} | variables.rs:496:5:496:27 | ... = ... | |
| variables.rs:496:25:496:25 | 2 | variables.rs:496:9:496:27 | MyStruct {...} | |
| variables.rs:497:5:497:13 | print_i64 | variables.rs:497:15:497:15 | a | |
| variables.rs:497:5:497:25 | print_i64(...) | variables.rs:491:14:498:1 | { ... } | |
| variables.rs:497:5:497:26 | ExprStmt | variables.rs:497:5:497:13 | print_i64 | |
| variables.rs:497:15:497:15 | a | variables.rs:497:15:497:24 | ... .my_get(...) | |
| variables.rs:497:15:497:24 | ... .my_get(...) | variables.rs:497:5:497:25 | print_i64(...) | |
| variables.rs:500:1:507:1 | enter fn ref_arg | variables.rs:501:5:501:15 | let ... = 16 | |
| variables.rs:500:1:507:1 | exit fn ref_arg (normal) | variables.rs:500:1:507:1 | exit fn ref_arg | |
| variables.rs:500:14:507:1 | { ... } | variables.rs:500:1:507:1 | exit fn ref_arg (normal) | |
| variables.rs:501:5:501:15 | let ... = 16 | variables.rs:501:13:501:14 | 16 | |
| variables.rs:501:9:501:9 | x | variables.rs:502:5:502:22 | ExprStmt | match |
| variables.rs:501:13:501:14 | 16 | variables.rs:501:9:501:9 | x | |
| variables.rs:502:5:502:17 | print_i64_ref | variables.rs:502:20:502:20 | x | |
| variables.rs:502:5:502:21 | print_i64_ref(...) | variables.rs:503:5:503:17 | ExprStmt | |
| variables.rs:502:5:502:22 | ExprStmt | variables.rs:502:5:502:17 | print_i64_ref | |
| variables.rs:502:19:502:20 | &z | variables.rs:502:5:502:21 | print_i64_ref(...) | |
| variables.rs:502:20:502:20 | z | variables.rs:502:19:502:20 | &z | |
| variables.rs:510:3:512:3 | enter fn bar | variables.rs:510:15:510:18 | self | |
| variables.rs:510:3:512:3 | exit fn bar (normal) | variables.rs:510:3:512:3 | exit fn bar | |
| variables.rs:510:10:510:18 | SelfParam | variables.rs:511:5:511:32 | ExprStmt | |
| variables.rs:510:15:510:18 | self | variables.rs:510:10:510:18 | SelfParam | |
| variables.rs:510:21:512:3 | { ... } | variables.rs:510:3:512:3 | exit fn bar (normal) | |
| variables.rs:511:5:511:9 | * ... | variables.rs:511:29:511:29 | 3 | |
| variables.rs:511:5:511:31 | ... = ... | variables.rs:510:21:512:3 | { ... } | |
| variables.rs:511:5:511:32 | ExprStmt | variables.rs:511:6:511:9 | self | |
| variables.rs:511:6:511:9 | self | variables.rs:511:5:511:9 | * ... | |
| variables.rs:511:13:511:31 | MyStruct {...} | variables.rs:511:5:511:31 | ... = ... | |
| variables.rs:511:29:511:29 | 3 | variables.rs:511:13:511:31 | MyStruct {...} | |
| variables.rs:515:1:520:1 | enter fn ref_methodcall_receiver | variables.rs:516:3:516:34 | let ... = ... | |
| variables.rs:515:1:520:1 | exit fn ref_methodcall_receiver (normal) | variables.rs:515:1:520:1 | exit fn ref_methodcall_receiver | |
| variables.rs:515:30:520:1 | { ... } | variables.rs:515:1:520:1 | exit fn ref_methodcall_receiver (normal) | |
| variables.rs:516:3:516:34 | let ... = ... | variables.rs:516:31:516:31 | 1 | |
| variables.rs:516:7:516:11 | a | variables.rs:517:3:517:10 | ExprStmt | match |
| variables.rs:516:15:516:33 | MyStruct {...} | variables.rs:516:7:516:11 | a | |
| variables.rs:516:31:516:31 | 1 | variables.rs:516:15:516:33 | MyStruct {...} | |
| variables.rs:517:3:517:3 | a | variables.rs:517:3:517:9 | ... .bar(...) | |
| variables.rs:517:3:517:9 | ... .bar(...) | variables.rs:519:3:519:19 | ExprStmt | |
| variables.rs:517:3:517:10 | ExprStmt | variables.rs:517:3:517:3 | a | |
| variables.rs:519:3:519:11 | print_i64 | variables.rs:519:13:519:13 | a | |
| variables.rs:519:3:519:18 | print_i64(...) | variables.rs:515:30:520:1 | { ... } | |
| variables.rs:519:3:519:19 | ExprStmt | variables.rs:519:3:519:11 | print_i64 | |
| variables.rs:519:13:519:13 | a | variables.rs:519:13:519:17 | a.val | |
| variables.rs:519:13:519:17 | a.val | variables.rs:519:3:519:18 | print_i64(...) | |
| variables.rs:522:1:556:1 | enter fn main | variables.rs:523:5:523:25 | ExprStmt | |
| variables.rs:522:1:556:1 | exit fn main (normal) | variables.rs:522:1:556:1 | exit fn main | |
| variables.rs:522:11:556:1 | { ... } | variables.rs:522:1:556:1 | exit fn main (normal) | |
| variables.rs:523:5:523:22 | immutable_variable | variables.rs:523:5:523:24 | immutable_variable(...) | |
| variables.rs:523:5:523:24 | immutable_variable(...) | variables.rs:524:5:524:23 | ExprStmt | |
| variables.rs:523:5:523:25 | ExprStmt | variables.rs:523:5:523:22 | immutable_variable | |
| variables.rs:524:5:524:20 | mutable_variable | variables.rs:524:5:524:22 | mutable_variable(...) | |
| variables.rs:524:5:524:22 | mutable_variable(...) | variables.rs:525:5:525:40 | ExprStmt | |
| variables.rs:524:5:524:23 | ExprStmt | variables.rs:524:5:524:20 | mutable_variable | |
| variables.rs:525:5:525:37 | mutable_variable_immutable_borrow | variables.rs:525:5:525:39 | mutable_variable_immutable_borrow(...) | |
| variables.rs:525:5:525:39 | mutable_variable_immutable_borrow(...) | variables.rs:526:5:526:23 | ExprStmt | |
| variables.rs:525:5:525:40 | ExprStmt | variables.rs:525:5:525:37 | mutable_variable_immutable_borrow | |
| variables.rs:526:5:526:20 | variable_shadow1 | variables.rs:526:5:526:22 | variable_shadow1(...) | |
| variables.rs:526:5:526:22 | variable_shadow1(...) | variables.rs:527:5:527:23 | ExprStmt | |
| variables.rs:526:5:526:23 | ExprStmt | variables.rs:526:5:526:20 | variable_shadow1 | |
| variables.rs:527:5:527:20 | variable_shadow2 | variables.rs:527:5:527:22 | variable_shadow2(...) | |
| variables.rs:527:5:527:22 | variable_shadow2(...) | variables.rs:528:5:528:19 | ExprStmt | |
| variables.rs:527:5:527:23 | ExprStmt | variables.rs:527:5:527:20 | variable_shadow2 | |
| variables.rs:528:5:528:16 | let_pattern1 | variables.rs:528:5:528:18 | let_pattern1(...) | |
| variables.rs:528:5:528:18 | let_pattern1(...) | variables.rs:529:5:529:19 | ExprStmt | |
| variables.rs:528:5:528:19 | ExprStmt | variables.rs:528:5:528:16 | let_pattern1 | |
| variables.rs:529:5:529:16 | let_pattern2 | variables.rs:529:5:529:18 | let_pattern2(...) | |
| variables.rs:529:5:529:18 | let_pattern2(...) | variables.rs:530:5:530:19 | ExprStmt | |
| variables.rs:529:5:529:19 | ExprStmt | variables.rs:529:5:529:16 | let_pattern2 | |
| variables.rs:530:5:530:16 | let_pattern3 | variables.rs:530:5:530:18 | let_pattern3(...) | |
| variables.rs:530:5:530:18 | let_pattern3(...) | variables.rs:531:5:531:19 | ExprStmt | |
| variables.rs:530:5:530:19 | ExprStmt | variables.rs:530:5:530:16 | let_pattern3 | |
| variables.rs:531:5:531:16 | let_pattern4 | variables.rs:531:5:531:18 | let_pattern4(...) | |
| variables.rs:531:5:531:18 | let_pattern4(...) | variables.rs:532:5:532:21 | ExprStmt | |
| variables.rs:531:5:531:19 | ExprStmt | variables.rs:531:5:531:16 | let_pattern4 | |
| variables.rs:532:5:532:18 | match_pattern1 | variables.rs:532:5:532:20 | match_pattern1(...) | |
| variables.rs:532:5:532:20 | match_pattern1(...) | variables.rs:533:5:533:21 | ExprStmt | |
| variables.rs:532:5:532:21 | ExprStmt | variables.rs:532:5:532:18 | match_pattern1 | |
| variables.rs:533:5:533:18 | match_pattern2 | variables.rs:533:5:533:20 | match_pattern2(...) | |
| variables.rs:533:5:533:20 | match_pattern2(...) | variables.rs:534:5:534:21 | ExprStmt | |
| variables.rs:533:5:533:21 | ExprStmt | variables.rs:533:5:533:18 | match_pattern2 | |
| variables.rs:534:5:534:18 | match_pattern3 | variables.rs:534:5:534:20 | match_pattern3(...) | |
| variables.rs:534:5:534:20 | match_pattern3(...) | variables.rs:535:5:535:21 | ExprStmt | |
| variables.rs:534:5:534:21 | ExprStmt | variables.rs:534:5:534:18 | match_pattern3 | |
| variables.rs:535:5:535:18 | match_pattern4 | variables.rs:535:5:535:20 | match_pattern4(...) | |
| variables.rs:535:5:535:20 | match_pattern4(...) | variables.rs:536:5:536:21 | ExprStmt | |
| variables.rs:535:5:535:21 | ExprStmt | variables.rs:535:5:535:18 | match_pattern4 | |
| variables.rs:536:5:536:18 | match_pattern5 | variables.rs:536:5:536:20 | match_pattern5(...) | |
| variables.rs:536:5:536:20 | match_pattern5(...) | variables.rs:537:5:537:21 | ExprStmt | |
| variables.rs:536:5:536:21 | ExprStmt | variables.rs:536:5:536:18 | match_pattern5 | |
| variables.rs:537:5:537:18 | match_pattern6 | variables.rs:537:5:537:20 | match_pattern6(...) | |
| variables.rs:537:5:537:20 | match_pattern6(...) | variables.rs:538:5:538:21 | ExprStmt | |
| variables.rs:537:5:537:21 | ExprStmt | variables.rs:537:5:537:18 | match_pattern6 | |
| variables.rs:538:5:538:18 | match_pattern7 | variables.rs:538:5:538:20 | match_pattern7(...) | |
| variables.rs:538:5:538:20 | match_pattern7(...) | variables.rs:539:5:539:21 | ExprStmt | |
| variables.rs:538:5:538:21 | ExprStmt | variables.rs:538:5:538:18 | match_pattern7 | |
| variables.rs:539:5:539:18 | match_pattern8 | variables.rs:539:5:539:20 | match_pattern8(...) | |
| variables.rs:539:5:539:20 | match_pattern8(...) | variables.rs:540:5:540:21 | ExprStmt | |
| variables.rs:539:5:539:21 | ExprStmt | variables.rs:539:5:539:18 | match_pattern8 | |
| variables.rs:540:5:540:18 | match_pattern9 | variables.rs:540:5:540:20 | match_pattern9(...) | |
| variables.rs:540:5:540:20 | match_pattern9(...) | variables.rs:541:5:541:36 | ExprStmt | |
| variables.rs:540:5:540:21 | ExprStmt | variables.rs:540:5:540:18 | match_pattern9 | |
| variables.rs:541:5:541:18 | param_pattern1 | variables.rs:541:20:541:22 | "a" | |
| variables.rs:541:5:541:35 | param_pattern1(...) | variables.rs:542:5:542:37 | ExprStmt | |
| variables.rs:541:5:541:36 | ExprStmt | variables.rs:541:5:541:18 | param_pattern1 | |
| variables.rs:541:20:541:22 | "a" | variables.rs:541:26:541:28 | "b" | |
| variables.rs:541:25:541:34 | TupleExpr | variables.rs:541:5:541:35 | param_pattern1(...) | |
| variables.rs:541:26:541:28 | "b" | variables.rs:541:31:541:33 | "c" | |
| variables.rs:541:31:541:33 | "c" | variables.rs:541:25:541:34 | TupleExpr | |
| variables.rs:542:5:542:18 | param_pattern2 | variables.rs:542:20:542:31 | ...::Left | |
| variables.rs:542:5:542:36 | param_pattern2(...) | variables.rs:543:5:543:26 | ExprStmt | |
| variables.rs:542:5:542:37 | ExprStmt | variables.rs:542:5:542:18 | param_pattern2 | |
| variables.rs:542:20:542:31 | ...::Left | variables.rs:542:33:542:34 | 45 | |
| variables.rs:542:20:542:35 | ...::Left(...) | variables.rs:542:5:542:36 | param_pattern2(...) | |
| variables.rs:542:33:542:34 | 45 | variables.rs:542:20:542:35 | ...::Left(...) | |
| variables.rs:543:5:543:23 | destruct_assignment | variables.rs:543:5:543:25 | destruct_assignment(...) | |
| variables.rs:543:5:543:25 | destruct_assignment(...) | variables.rs:544:5:544:23 | ExprStmt | |
| variables.rs:543:5:543:26 | ExprStmt | variables.rs:543:5:543:23 | destruct_assignment | |
| variables.rs:544:5:544:20 | closure_variable | variables.rs:544:5:544:22 | closure_variable(...) | |
| variables.rs:544:5:544:22 | closure_variable(...) | variables.rs:545:5:545:19 | ExprStmt | |
| variables.rs:544:5:544:23 | ExprStmt | variables.rs:544:5:544:20 | closure_variable | |
| variables.rs:545:5:545:16 | for_variable | variables.rs:545:5:545:18 | for_variable(...) | |
| variables.rs:545:5:545:18 | for_variable(...) | variables.rs:546:5:546:17 | ExprStmt | |
| variables.rs:545:5:545:19 | ExprStmt | variables.rs:545:5:545:16 | for_variable | |
| variables.rs:546:5:546:14 | add_assign | variables.rs:546:5:546:16 | add_assign(...) | |
| variables.rs:546:5:546:16 | add_assign(...) | variables.rs:547:5:547:13 | ExprStmt | |
| variables.rs:546:5:546:17 | ExprStmt | variables.rs:546:5:546:14 | add_assign | |
| variables.rs:547:5:547:10 | mutate | variables.rs:547:5:547:12 | mutate(...) | |
| variables.rs:547:5:547:12 | mutate(...) | variables.rs:548:5:548:17 | ExprStmt | |
| variables.rs:547:5:547:13 | ExprStmt | variables.rs:547:5:547:10 | mutate | |
| variables.rs:548:5:548:14 | mutate_arg | variables.rs:548:5:548:16 | mutate_arg(...) | |
| variables.rs:548:5:548:16 | mutate_arg(...) | variables.rs:549:5:549:12 | ExprStmt | |
| variables.rs:548:5:548:17 | ExprStmt | variables.rs:548:5:548:14 | mutate_arg | |
| variables.rs:549:5:549:9 | alias | variables.rs:549:5:549:11 | alias(...) | |
| variables.rs:549:5:549:11 | alias(...) | variables.rs:550:5:550:18 | ExprStmt | |
| variables.rs:549:5:549:12 | ExprStmt | variables.rs:549:5:549:9 | alias | |
| variables.rs:550:5:550:15 | capture_mut | variables.rs:550:5:550:17 | capture_mut(...) | |
| variables.rs:550:5:550:17 | capture_mut(...) | variables.rs:551:5:551:20 | ExprStmt | |
| variables.rs:550:5:550:18 | ExprStmt | variables.rs:550:5:550:15 | capture_mut | |
| variables.rs:551:5:551:17 | capture_immut | variables.rs:551:5:551:19 | capture_immut(...) | |
| variables.rs:551:5:551:19 | capture_immut(...) | variables.rs:552:5:552:26 | ExprStmt | |
| variables.rs:551:5:551:20 | ExprStmt | variables.rs:551:5:551:17 | capture_immut | |
| variables.rs:552:5:552:23 | async_block_capture | variables.rs:552:5:552:25 | async_block_capture(...) | |
| variables.rs:552:5:552:25 | async_block_capture(...) | variables.rs:553:5:553:14 | ExprStmt | |
| variables.rs:552:5:552:26 | ExprStmt | variables.rs:552:5:552:23 | async_block_capture | |
| variables.rs:553:5:553:11 | structs | variables.rs:553:5:553:13 | structs(...) | |
| variables.rs:553:5:553:13 | structs(...) | variables.rs:554:5:554:14 | ExprStmt | |
| variables.rs:553:5:553:14 | ExprStmt | variables.rs:553:5:553:11 | structs | |
| variables.rs:554:5:554:11 | ref_arg | variables.rs:554:5:554:13 | ref_arg(...) | |
| variables.rs:554:5:554:13 | ref_arg(...) | variables.rs:555:5:555:30 | ExprStmt | |
| variables.rs:554:5:554:14 | ExprStmt | variables.rs:554:5:554:11 | ref_arg | |
| variables.rs:555:5:555:27 | ref_methodcall_receiver | variables.rs:555:5:555:29 | ref_methodcall_receiver(...) | |
| variables.rs:555:5:555:29 | ref_methodcall_receiver(...) | variables.rs:522:11:556:1 | { ... } | |
| variables.rs:555:5:555:30 | ExprStmt | variables.rs:555:5:555:27 | ref_methodcall_receiver | |
| variables.rs:502:19:502:20 | &x | variables.rs:502:5:502:21 | print_i64_ref(...) | |
| variables.rs:502:20:502:20 | x | variables.rs:502:19:502:20 | &x | |
| variables.rs:503:5:503:13 | print_i64 | variables.rs:503:15:503:15 | x | |
| variables.rs:503:5:503:16 | print_i64(...) | variables.rs:505:5:505:15 | let ... = 17 | |
| variables.rs:503:5:503:17 | ExprStmt | variables.rs:503:5:503:13 | print_i64 | |
| variables.rs:503:15:503:15 | x | variables.rs:503:5:503:16 | print_i64(...) | |
| variables.rs:505:5:505:15 | let ... = 17 | variables.rs:505:13:505:14 | 17 | |
| variables.rs:505:9:505:9 | z | variables.rs:506:5:506:22 | ExprStmt | match |
| variables.rs:505:13:505:14 | 17 | variables.rs:505:9:505:9 | z | |
| variables.rs:506:5:506:17 | print_i64_ref | variables.rs:506:20:506:20 | z | |
| variables.rs:506:5:506:21 | print_i64_ref(...) | variables.rs:500:14:507:1 | { ... } | |
| variables.rs:506:5:506:22 | ExprStmt | variables.rs:506:5:506:17 | print_i64_ref | |
| variables.rs:506:19:506:20 | &z | variables.rs:506:5:506:21 | print_i64_ref(...) | |
| variables.rs:506:20:506:20 | z | variables.rs:506:19:506:20 | &z | |
| variables.rs:514:3:516:3 | enter fn bar | variables.rs:514:15:514:18 | self | |
| variables.rs:514:3:516:3 | exit fn bar (normal) | variables.rs:514:3:516:3 | exit fn bar | |
| variables.rs:514:10:514:18 | SelfParam | variables.rs:515:5:515:32 | ExprStmt | |
| variables.rs:514:15:514:18 | self | variables.rs:514:10:514:18 | SelfParam | |
| variables.rs:514:21:516:3 | { ... } | variables.rs:514:3:516:3 | exit fn bar (normal) | |
| variables.rs:515:5:515:9 | * ... | variables.rs:515:29:515:29 | 3 | |
| variables.rs:515:5:515:31 | ... = ... | variables.rs:514:21:516:3 | { ... } | |
| variables.rs:515:5:515:32 | ExprStmt | variables.rs:515:6:515:9 | self | |
| variables.rs:515:6:515:9 | self | variables.rs:515:5:515:9 | * ... | |
| variables.rs:515:13:515:31 | MyStruct {...} | variables.rs:515:5:515:31 | ... = ... | |
| variables.rs:515:29:515:29 | 3 | variables.rs:515:13:515:31 | MyStruct {...} | |
| variables.rs:519:1:524:1 | enter fn ref_methodcall_receiver | variables.rs:520:3:520:34 | let ... = ... | |
| variables.rs:519:1:524:1 | exit fn ref_methodcall_receiver (normal) | variables.rs:519:1:524:1 | exit fn ref_methodcall_receiver | |
| variables.rs:519:30:524:1 | { ... } | variables.rs:519:1:524:1 | exit fn ref_methodcall_receiver (normal) | |
| variables.rs:520:3:520:34 | let ... = ... | variables.rs:520:31:520:31 | 1 | |
| variables.rs:520:7:520:11 | a | variables.rs:521:3:521:10 | ExprStmt | match |
| variables.rs:520:15:520:33 | MyStruct {...} | variables.rs:520:7:520:11 | a | |
| variables.rs:520:31:520:31 | 1 | variables.rs:520:15:520:33 | MyStruct {...} | |
| variables.rs:521:3:521:3 | a | variables.rs:521:3:521:9 | ... .bar(...) | |
| variables.rs:521:3:521:9 | ... .bar(...) | variables.rs:523:3:523:19 | ExprStmt | |
| variables.rs:521:3:521:10 | ExprStmt | variables.rs:521:3:521:3 | a | |
| variables.rs:523:3:523:11 | print_i64 | variables.rs:523:13:523:13 | a | |
| variables.rs:523:3:523:18 | print_i64(...) | variables.rs:519:30:524:1 | { ... } | |
| variables.rs:523:3:523:19 | ExprStmt | variables.rs:523:3:523:11 | print_i64 | |
| variables.rs:523:13:523:13 | a | variables.rs:523:13:523:17 | a.val | |
| variables.rs:523:13:523:17 | a.val | variables.rs:523:3:523:18 | print_i64(...) | |
| variables.rs:526:1:560:1 | enter fn main | variables.rs:527:5:527:25 | ExprStmt | |
| variables.rs:526:1:560:1 | exit fn main (normal) | variables.rs:526:1:560:1 | exit fn main | |
| variables.rs:526:11:560:1 | { ... } | variables.rs:526:1:560:1 | exit fn main (normal) | |
| variables.rs:527:5:527:22 | immutable_variable | variables.rs:527:5:527:24 | immutable_variable(...) | |
| variables.rs:527:5:527:24 | immutable_variable(...) | variables.rs:528:5:528:23 | ExprStmt | |
| variables.rs:527:5:527:25 | ExprStmt | variables.rs:527:5:527:22 | immutable_variable | |
| variables.rs:528:5:528:20 | mutable_variable | variables.rs:528:5:528:22 | mutable_variable(...) | |
| variables.rs:528:5:528:22 | mutable_variable(...) | variables.rs:529:5:529:40 | ExprStmt | |
| variables.rs:528:5:528:23 | ExprStmt | variables.rs:528:5:528:20 | mutable_variable | |
| variables.rs:529:5:529:37 | mutable_variable_immutable_borrow | variables.rs:529:5:529:39 | mutable_variable_immutable_borrow(...) | |
| variables.rs:529:5:529:39 | mutable_variable_immutable_borrow(...) | variables.rs:530:5:530:23 | ExprStmt | |
| variables.rs:529:5:529:40 | ExprStmt | variables.rs:529:5:529:37 | mutable_variable_immutable_borrow | |
| variables.rs:530:5:530:20 | variable_shadow1 | variables.rs:530:5:530:22 | variable_shadow1(...) | |
| variables.rs:530:5:530:22 | variable_shadow1(...) | variables.rs:531:5:531:23 | ExprStmt | |
| variables.rs:530:5:530:23 | ExprStmt | variables.rs:530:5:530:20 | variable_shadow1 | |
| variables.rs:531:5:531:20 | variable_shadow2 | variables.rs:531:5:531:22 | variable_shadow2(...) | |
| variables.rs:531:5:531:22 | variable_shadow2(...) | variables.rs:532:5:532:19 | ExprStmt | |
| variables.rs:531:5:531:23 | ExprStmt | variables.rs:531:5:531:20 | variable_shadow2 | |
| variables.rs:532:5:532:16 | let_pattern1 | variables.rs:532:5:532:18 | let_pattern1(...) | |
| variables.rs:532:5:532:18 | let_pattern1(...) | variables.rs:533:5:533:19 | ExprStmt | |
| variables.rs:532:5:532:19 | ExprStmt | variables.rs:532:5:532:16 | let_pattern1 | |
| variables.rs:533:5:533:16 | let_pattern2 | variables.rs:533:5:533:18 | let_pattern2(...) | |
| variables.rs:533:5:533:18 | let_pattern2(...) | variables.rs:534:5:534:19 | ExprStmt | |
| variables.rs:533:5:533:19 | ExprStmt | variables.rs:533:5:533:16 | let_pattern2 | |
| variables.rs:534:5:534:16 | let_pattern3 | variables.rs:534:5:534:18 | let_pattern3(...) | |
| variables.rs:534:5:534:18 | let_pattern3(...) | variables.rs:535:5:535:19 | ExprStmt | |
| variables.rs:534:5:534:19 | ExprStmt | variables.rs:534:5:534:16 | let_pattern3 | |
| variables.rs:535:5:535:16 | let_pattern4 | variables.rs:535:5:535:18 | let_pattern4(...) | |
| variables.rs:535:5:535:18 | let_pattern4(...) | variables.rs:536:5:536:21 | ExprStmt | |
| variables.rs:535:5:535:19 | ExprStmt | variables.rs:535:5:535:16 | let_pattern4 | |
| variables.rs:536:5:536:18 | match_pattern1 | variables.rs:536:5:536:20 | match_pattern1(...) | |
| variables.rs:536:5:536:20 | match_pattern1(...) | variables.rs:537:5:537:21 | ExprStmt | |
| variables.rs:536:5:536:21 | ExprStmt | variables.rs:536:5:536:18 | match_pattern1 | |
| variables.rs:537:5:537:18 | match_pattern2 | variables.rs:537:5:537:20 | match_pattern2(...) | |
| variables.rs:537:5:537:20 | match_pattern2(...) | variables.rs:538:5:538:21 | ExprStmt | |
| variables.rs:537:5:537:21 | ExprStmt | variables.rs:537:5:537:18 | match_pattern2 | |
| variables.rs:538:5:538:18 | match_pattern3 | variables.rs:538:5:538:20 | match_pattern3(...) | |
| variables.rs:538:5:538:20 | match_pattern3(...) | variables.rs:539:5:539:21 | ExprStmt | |
| variables.rs:538:5:538:21 | ExprStmt | variables.rs:538:5:538:18 | match_pattern3 | |
| variables.rs:539:5:539:18 | match_pattern4 | variables.rs:539:5:539:20 | match_pattern4(...) | |
| variables.rs:539:5:539:20 | match_pattern4(...) | variables.rs:540:5:540:21 | ExprStmt | |
| variables.rs:539:5:539:21 | ExprStmt | variables.rs:539:5:539:18 | match_pattern4 | |
| variables.rs:540:5:540:18 | match_pattern5 | variables.rs:540:5:540:20 | match_pattern5(...) | |
| variables.rs:540:5:540:20 | match_pattern5(...) | variables.rs:541:5:541:21 | ExprStmt | |
| variables.rs:540:5:540:21 | ExprStmt | variables.rs:540:5:540:18 | match_pattern5 | |
| variables.rs:541:5:541:18 | match_pattern6 | variables.rs:541:5:541:20 | match_pattern6(...) | |
| variables.rs:541:5:541:20 | match_pattern6(...) | variables.rs:542:5:542:21 | ExprStmt | |
| variables.rs:541:5:541:21 | ExprStmt | variables.rs:541:5:541:18 | match_pattern6 | |
| variables.rs:542:5:542:18 | match_pattern7 | variables.rs:542:5:542:20 | match_pattern7(...) | |
| variables.rs:542:5:542:20 | match_pattern7(...) | variables.rs:543:5:543:21 | ExprStmt | |
| variables.rs:542:5:542:21 | ExprStmt | variables.rs:542:5:542:18 | match_pattern7 | |
| variables.rs:543:5:543:18 | match_pattern8 | variables.rs:543:5:543:20 | match_pattern8(...) | |
| variables.rs:543:5:543:20 | match_pattern8(...) | variables.rs:544:5:544:21 | ExprStmt | |
| variables.rs:543:5:543:21 | ExprStmt | variables.rs:543:5:543:18 | match_pattern8 | |
| variables.rs:544:5:544:18 | match_pattern9 | variables.rs:544:5:544:20 | match_pattern9(...) | |
| variables.rs:544:5:544:20 | match_pattern9(...) | variables.rs:545:5:545:36 | ExprStmt | |
| variables.rs:544:5:544:21 | ExprStmt | variables.rs:544:5:544:18 | match_pattern9 | |
| variables.rs:545:5:545:18 | param_pattern1 | variables.rs:545:20:545:22 | "a" | |
| variables.rs:545:5:545:35 | param_pattern1(...) | variables.rs:546:5:546:37 | ExprStmt | |
| variables.rs:545:5:545:36 | ExprStmt | variables.rs:545:5:545:18 | param_pattern1 | |
| variables.rs:545:20:545:22 | "a" | variables.rs:545:26:545:28 | "b" | |
| variables.rs:545:25:545:34 | TupleExpr | variables.rs:545:5:545:35 | param_pattern1(...) | |
| variables.rs:545:26:545:28 | "b" | variables.rs:545:31:545:33 | "c" | |
| variables.rs:545:31:545:33 | "c" | variables.rs:545:25:545:34 | TupleExpr | |
| variables.rs:546:5:546:18 | param_pattern2 | variables.rs:546:20:546:31 | ...::Left | |
| variables.rs:546:5:546:36 | param_pattern2(...) | variables.rs:547:5:547:26 | ExprStmt | |
| variables.rs:546:5:546:37 | ExprStmt | variables.rs:546:5:546:18 | param_pattern2 | |
| variables.rs:546:20:546:31 | ...::Left | variables.rs:546:33:546:34 | 45 | |
| variables.rs:546:20:546:35 | ...::Left(...) | variables.rs:546:5:546:36 | param_pattern2(...) | |
| variables.rs:546:33:546:34 | 45 | variables.rs:546:20:546:35 | ...::Left(...) | |
| variables.rs:547:5:547:23 | destruct_assignment | variables.rs:547:5:547:25 | destruct_assignment(...) | |
| variables.rs:547:5:547:25 | destruct_assignment(...) | variables.rs:548:5:548:23 | ExprStmt | |
| variables.rs:547:5:547:26 | ExprStmt | variables.rs:547:5:547:23 | destruct_assignment | |
| variables.rs:548:5:548:20 | closure_variable | variables.rs:548:5:548:22 | closure_variable(...) | |
| variables.rs:548:5:548:22 | closure_variable(...) | variables.rs:549:5:549:19 | ExprStmt | |
| variables.rs:548:5:548:23 | ExprStmt | variables.rs:548:5:548:20 | closure_variable | |
| variables.rs:549:5:549:16 | for_variable | variables.rs:549:5:549:18 | for_variable(...) | |
| variables.rs:549:5:549:18 | for_variable(...) | variables.rs:550:5:550:17 | ExprStmt | |
| variables.rs:549:5:549:19 | ExprStmt | variables.rs:549:5:549:16 | for_variable | |
| variables.rs:550:5:550:14 | add_assign | variables.rs:550:5:550:16 | add_assign(...) | |
| variables.rs:550:5:550:16 | add_assign(...) | variables.rs:551:5:551:13 | ExprStmt | |
| variables.rs:550:5:550:17 | ExprStmt | variables.rs:550:5:550:14 | add_assign | |
| variables.rs:551:5:551:10 | mutate | variables.rs:551:5:551:12 | mutate(...) | |
| variables.rs:551:5:551:12 | mutate(...) | variables.rs:552:5:552:17 | ExprStmt | |
| variables.rs:551:5:551:13 | ExprStmt | variables.rs:551:5:551:10 | mutate | |
| variables.rs:552:5:552:14 | mutate_arg | variables.rs:552:5:552:16 | mutate_arg(...) | |
| variables.rs:552:5:552:16 | mutate_arg(...) | variables.rs:553:5:553:12 | ExprStmt | |
| variables.rs:552:5:552:17 | ExprStmt | variables.rs:552:5:552:14 | mutate_arg | |
| variables.rs:553:5:553:9 | alias | variables.rs:553:5:553:11 | alias(...) | |
| variables.rs:553:5:553:11 | alias(...) | variables.rs:554:5:554:18 | ExprStmt | |
| variables.rs:553:5:553:12 | ExprStmt | variables.rs:553:5:553:9 | alias | |
| variables.rs:554:5:554:15 | capture_mut | variables.rs:554:5:554:17 | capture_mut(...) | |
| variables.rs:554:5:554:17 | capture_mut(...) | variables.rs:555:5:555:20 | ExprStmt | |
| variables.rs:554:5:554:18 | ExprStmt | variables.rs:554:5:554:15 | capture_mut | |
| variables.rs:555:5:555:17 | capture_immut | variables.rs:555:5:555:19 | capture_immut(...) | |
| variables.rs:555:5:555:19 | capture_immut(...) | variables.rs:556:5:556:26 | ExprStmt | |
| variables.rs:555:5:555:20 | ExprStmt | variables.rs:555:5:555:17 | capture_immut | |
| variables.rs:556:5:556:23 | async_block_capture | variables.rs:556:5:556:25 | async_block_capture(...) | |
| variables.rs:556:5:556:25 | async_block_capture(...) | variables.rs:557:5:557:14 | ExprStmt | |
| variables.rs:556:5:556:26 | ExprStmt | variables.rs:556:5:556:23 | async_block_capture | |
| variables.rs:557:5:557:11 | structs | variables.rs:557:5:557:13 | structs(...) | |
| variables.rs:557:5:557:13 | structs(...) | variables.rs:558:5:558:14 | ExprStmt | |
| variables.rs:557:5:557:14 | ExprStmt | variables.rs:557:5:557:11 | structs | |
| variables.rs:558:5:558:11 | ref_arg | variables.rs:558:5:558:13 | ref_arg(...) | |
| variables.rs:558:5:558:13 | ref_arg(...) | variables.rs:559:5:559:30 | ExprStmt | |
| variables.rs:558:5:558:14 | ExprStmt | variables.rs:558:5:558:11 | ref_arg | |
| variables.rs:559:5:559:27 | ref_methodcall_receiver | variables.rs:559:5:559:29 | ref_methodcall_receiver(...) | |
| variables.rs:559:5:559:29 | ref_methodcall_receiver(...) | variables.rs:526:11:560:1 | { ... } | |
| variables.rs:559:5:559:30 | ExprStmt | variables.rs:559:5:559:27 | ref_methodcall_receiver | |
breakTarget
continueTarget

View File

@@ -5,8 +5,8 @@ nonSsaVariable
| variables.rs:379:13:379:13 | z |
| variables.rs:392:13:392:13 | x |
| variables.rs:426:13:426:13 | z |
| variables.rs:488:13:488:13 | a |
| variables.rs:516:11:516:11 | a |
| variables.rs:492:13:492:13 | a |
| variables.rs:520:11:520:11 | a |
definition
| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s |
| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i |
@@ -134,8 +134,11 @@ definition
| variables.rs:461:13:461:14 | b1 | variables.rs:461:13:461:14 | b1 |
| variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:25 | b2 |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x |
| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x |
| variables.rs:501:9:501:9 | z | variables.rs:501:9:501:9 | z |
| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self |
| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self |
| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x |
| variables.rs:505:9:505:9 | z | variables.rs:505:9:505:9 | z |
| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self |
read
| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | variables.rs:4:20:4:20 | s |
| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | variables.rs:8:20:8:20 | i |
@@ -257,7 +260,10 @@ read
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:466:19:466:19 | x |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:470:19:470:19 | x |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:472:19:472:19 | x |
| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | variables.rs:499:15:499:15 | x |
| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | variables.rs:483:16:483:19 | self |
| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | variables.rs:487:9:487:12 | self |
| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | variables.rs:503:15:503:15 | x |
| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | variables.rs:515:6:515:9 | self |
firstRead
| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | variables.rs:4:20:4:20 | s |
| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | variables.rs:8:20:8:20 | i |
@@ -356,7 +362,10 @@ firstRead
| variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:25 | b2 | variables.rs:469:8:469:9 | b2 |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:464:19:464:19 | x |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:466:19:466:19 | x |
| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | variables.rs:499:15:499:15 | x |
| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | variables.rs:483:16:483:19 | self |
| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | variables.rs:487:9:487:12 | self |
| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | variables.rs:503:15:503:15 | x |
| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | variables.rs:515:6:515:9 | self |
lastRead
| variables.rs:3:14:3:14 | s | variables.rs:3:14:3:14 | s | variables.rs:4:20:4:20 | s |
| variables.rs:7:14:7:14 | i | variables.rs:7:14:7:14 | i | variables.rs:8:20:8:20 | i |
@@ -456,7 +465,10 @@ lastRead
| variables.rs:461:24:461:25 | b2 | variables.rs:461:24:461:25 | b2 | variables.rs:469:8:469:9 | b2 |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:470:19:470:19 | x |
| variables.rs:462:9:462:9 | x | variables.rs:462:9:462:9 | x | variables.rs:472:19:472:19 | x |
| variables.rs:497:9:497:9 | x | variables.rs:497:9:497:9 | x | variables.rs:499:15:499:15 | x |
| variables.rs:482:15:482:23 | SelfParam | variables.rs:482:20:482:23 | self | variables.rs:483:16:483:19 | self |
| variables.rs:486:11:486:14 | SelfParam | variables.rs:486:11:486:14 | self | variables.rs:487:9:487:12 | self |
| variables.rs:501:9:501:9 | x | variables.rs:501:9:501:9 | x | variables.rs:503:15:503:15 | x |
| variables.rs:514:10:514:18 | SelfParam | variables.rs:514:15:514:18 | self | variables.rs:515:6:515:9 | self |
adjacentReads
| variables.rs:35:9:35:10 | x3 | variables.rs:35:9:35:10 | x3 | variables.rs:36:15:36:16 | x3 | variables.rs:38:9:38:10 | x3 |
| variables.rs:43:9:43:10 | x4 | variables.rs:43:9:43:10 | x4 | variables.rs:44:15:44:16 | x4 | variables.rs:49:15:49:16 | x4 |

View File

@@ -95,10 +95,13 @@ variable
| variables.rs:461:13:461:14 | b1 |
| variables.rs:461:24:461:25 | b2 |
| variables.rs:462:9:462:9 | x |
| variables.rs:488:13:488:13 | a |
| variables.rs:497:9:497:9 | x |
| variables.rs:501:9:501:9 | z |
| variables.rs:516:11:516:11 | a |
| variables.rs:482:20:482:23 | self |
| variables.rs:486:11:486:14 | self |
| variables.rs:492:13:492:13 | a |
| variables.rs:501:9:501:9 | x |
| variables.rs:505:9:505:9 | z |
| variables.rs:514:15:514:18 | self |
| variables.rs:520:11:520:11 | a |
variableAccess
| variables.rs:4:20:4:20 | s | variables.rs:3:14:3:14 | s |
| variables.rs:8:20:8:20 | i | variables.rs:7:14:7:14 | i |
@@ -246,16 +249,19 @@ variableAccess
| variables.rs:469:8:469:9 | b2 | variables.rs:461:24:461:25 | b2 |
| variables.rs:470:19:470:19 | x | variables.rs:462:9:462:9 | x |
| variables.rs:472:19:472:19 | x | variables.rs:462:9:462:9 | x |
| variables.rs:489:15:489:15 | a | variables.rs:488:13:488:13 | a |
| variables.rs:490:5:490:5 | a | variables.rs:488:13:488:13 | a |
| variables.rs:491:15:491:15 | a | variables.rs:488:13:488:13 | a |
| variables.rs:492:5:492:5 | a | variables.rs:488:13:488:13 | a |
| variables.rs:493:15:493:15 | a | variables.rs:488:13:488:13 | a |
| variables.rs:498:20:498:20 | x | variables.rs:497:9:497:9 | x |
| variables.rs:499:15:499:15 | x | variables.rs:497:9:497:9 | x |
| variables.rs:502:20:502:20 | z | variables.rs:501:9:501:9 | z |
| variables.rs:517:3:517:3 | a | variables.rs:516:11:516:11 | a |
| variables.rs:519:13:519:13 | a | variables.rs:516:11:516:11 | a |
| variables.rs:483:16:483:19 | self | variables.rs:482:20:482:23 | self |
| variables.rs:487:9:487:12 | self | variables.rs:486:11:486:14 | self |
| variables.rs:493:15:493:15 | a | variables.rs:492:13:492:13 | a |
| variables.rs:494:5:494:5 | a | variables.rs:492:13:492:13 | a |
| variables.rs:495:15:495:15 | a | variables.rs:492:13:492:13 | a |
| variables.rs:496:5:496:5 | a | variables.rs:492:13:492:13 | a |
| variables.rs:497:15:497:15 | a | variables.rs:492:13:492:13 | a |
| variables.rs:502:20:502:20 | x | variables.rs:501:9:501:9 | x |
| variables.rs:503:15:503:15 | x | variables.rs:501:9:501:9 | x |
| variables.rs:506:20:506:20 | z | variables.rs:505:9:505:9 | z |
| variables.rs:515:6:515:9 | self | variables.rs:514:15:514:18 | self |
| variables.rs:521:3:521:3 | a | variables.rs:520:11:520:11 | a |
| variables.rs:523:13:523:13 | a | variables.rs:520:11:520:11 | a |
variableWriteAccess
| variables.rs:23:5:23:6 | x2 | variables.rs:21:13:21:14 | x2 |
| variables.rs:30:5:30:5 | x | variables.rs:28:13:28:13 | x |
@@ -266,7 +272,7 @@ variableWriteAccess
| variables.rs:438:9:438:9 | i | variables.rs:436:13:436:13 | i |
| variables.rs:450:9:450:9 | x | variables.rs:446:13:446:13 | x |
| variables.rs:454:9:454:9 | x | variables.rs:446:13:446:13 | x |
| variables.rs:492:5:492:5 | a | variables.rs:488:13:488:13 | a |
| variables.rs:496:5:496:5 | a | variables.rs:492:13:492:13 | a |
variableReadAccess
| variables.rs:4:20:4:20 | s | variables.rs:3:14:3:14 | s |
| variables.rs:8:20:8:20 | i | variables.rs:7:14:7:14 | i |
@@ -396,13 +402,16 @@ variableReadAccess
| variables.rs:469:8:469:9 | b2 | variables.rs:461:24:461:25 | b2 |
| variables.rs:470:19:470:19 | x | variables.rs:462:9:462:9 | x |
| variables.rs:472:19:472:19 | x | variables.rs:462:9:462:9 | x |
| variables.rs:489:15:489:15 | a | variables.rs:488:13:488:13 | a |
| variables.rs:490:5:490:5 | a | variables.rs:488:13:488:13 | a |
| variables.rs:491:15:491:15 | a | variables.rs:488:13:488:13 | a |
| variables.rs:493:15:493:15 | a | variables.rs:488:13:488:13 | a |
| variables.rs:499:15:499:15 | x | variables.rs:497:9:497:9 | x |
| variables.rs:517:3:517:3 | a | variables.rs:516:11:516:11 | a |
| variables.rs:519:13:519:13 | a | variables.rs:516:11:516:11 | a |
| variables.rs:483:16:483:19 | self | variables.rs:482:20:482:23 | self |
| variables.rs:487:9:487:12 | self | variables.rs:486:11:486:14 | self |
| variables.rs:493:15:493:15 | a | variables.rs:492:13:492:13 | a |
| variables.rs:494:5:494:5 | a | variables.rs:492:13:492:13 | a |
| variables.rs:495:15:495:15 | a | variables.rs:492:13:492:13 | a |
| variables.rs:497:15:497:15 | a | variables.rs:492:13:492:13 | a |
| variables.rs:503:15:503:15 | x | variables.rs:501:9:501:9 | x |
| variables.rs:515:6:515:9 | self | variables.rs:514:15:514:18 | self |
| variables.rs:521:3:521:3 | a | variables.rs:520:11:520:11 | a |
| variables.rs:523:13:523:13 | a | variables.rs:520:11:520:11 | a |
variableInitializer
| variables.rs:16:9:16:10 | x1 | variables.rs:16:14:16:16 | "a" |
| variables.rs:21:13:21:14 | x2 | variables.rs:21:18:21:18 | 4 |
@@ -450,10 +459,10 @@ variableInitializer
| variables.rs:437:9:437:13 | block | variables.rs:437:17:439:5 | { ... } |
| variables.rs:446:13:446:13 | x | variables.rs:446:17:446:17 | 1 |
| variables.rs:462:9:462:9 | x | variables.rs:462:13:462:13 | 1 |
| variables.rs:488:13:488:13 | a | variables.rs:488:17:488:35 | MyStruct {...} |
| variables.rs:497:9:497:9 | x | variables.rs:497:13:497:14 | 16 |
| variables.rs:501:9:501:9 | z | variables.rs:501:13:501:14 | 17 |
| variables.rs:516:11:516:11 | a | variables.rs:516:15:516:33 | MyStruct {...} |
| variables.rs:492:13:492:13 | a | variables.rs:492:17:492:35 | MyStruct {...} |
| variables.rs:501:9:501:9 | x | variables.rs:501:13:501:14 | 16 |
| variables.rs:505:9:505:9 | z | variables.rs:505:13:505:14 | 17 |
| variables.rs:520:11:520:11 | a | variables.rs:520:15:520:33 | MyStruct {...} |
capturedVariable
| variables.rs:400:9:400:9 | x |
| variables.rs:410:13:410:13 | x |

View File

@@ -117,7 +117,7 @@ fn match_pattern1() {
=>
{
print_i64(y1)// $ read_access=y1_2
}
}
None => print_str("NONE"),
}
@@ -480,7 +480,11 @@ struct MyStruct {
impl MyStruct {
fn my_get(&mut self) -> i64 {
return self.val;
return self.val; // $ read_access=self
}
fn id(self) -> Self {
self // $ read_access=self
}
}
@@ -508,7 +512,7 @@ trait Bar {
impl MyStruct {
fn bar(&mut self) {
*self = MyStruct { val: 3 };
*self = MyStruct { val: 3 }; // $ read_access=self
}
}

View File

@@ -5,3 +5,4 @@ extractionWarning
| does_not_compile.rs:2:21:2:20 | expected SEMICOLON |
| does_not_compile.rs:2:26:2:25 | expected SEMICOLON |
| error.rs:2:5:2:17 | An error! |
| my_macro.rs:17:9:17:27 | macro expansion failed: could not resolve macro 'myUndefinedMacro' |

View File

@@ -4,3 +4,4 @@
| does_not_compile.rs:2:21:2:20 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 |
| does_not_compile.rs:2:26:2:25 | expected SEMICOLON | Extraction warning in does_not_compile.rs with message expected SEMICOLON | 1 |
| error.rs:2:5:2:17 | An error! | Extraction warning in error.rs with message An error! | 1 |
| my_macro.rs:17:9:17:27 | macro expansion failed: could not resolve macro 'myUndefinedMacro' | Extraction warning in my_macro.rs with message macro expansion failed: could not resolve macro 'myUndefinedMacro' | 1 |

View File

@@ -1 +1 @@
| 59 |
| 60 |

View File

@@ -1 +1 @@
| 59 |
| 60 |

View File

@@ -1,7 +1,7 @@
| my_struct.rs:0:0:0:0 | my_struct.rs | 20 |
| comments.rs:0:0:0:0 | comments.rs | 13 |
| main.rs:0:0:0:0 | main.rs | 8 |
| my_macro.rs:0:0:0:0 | my_macro.rs | 7 |
| my_macro.rs:0:0:0:0 | my_macro.rs | 8 |
| lib.rs:0:0:0:0 | lib.rs | 5 |
| does_not_compile.rs:0:0:0:0 | does_not_compile.rs | 3 |
| error.rs:0:0:0:0 | error.rs | 3 |

View File

@@ -1,12 +1,17 @@
| Elements extracted | 375 |
| Elements extracted | 382 |
| Elements unextracted | 0 |
| Extraction errors | 0 |
| Extraction warnings | 6 |
| Extraction warnings | 7 |
| Files extracted - total | 8 |
| Files extracted - with errors | 2 |
| Files extracted - without errors | 6 |
| Files extracted - with errors | 3 |
| Files extracted - without errors | 5 |
| Inconsistencies - AST | 0 |
| Inconsistencies - CFG | 0 |
| Inconsistencies - data flow | 0 |
| Lines of code extracted | 59 |
| Lines of user code extracted | 59 |
| Lines of code extracted | 60 |
| Lines of user code extracted | 60 |
| Macro calls - resolved | 8 |
| Macro calls - total | 9 |
| Macro calls - unresolved | 1 |
| Taint sources - active | 0 |
| Taint sources - total | 0 |

View File

@@ -0,0 +1 @@
| my_macro.rs:17:9:17:27 | myUndefinedMacro!... | Macro call was not resolved to a target. |

View File

@@ -0,0 +1 @@
queries/diagnostics/UnresolvedMacroCalls.ql

View File

@@ -1,6 +1,6 @@
/**
* total lines in this file: 18
* of which code: 10
* total lines in this file: 19
* of which code: 11
* of which only comments: 6
* of which blank: 2
*/
@@ -14,5 +14,6 @@ macro_rules! myMacro {
pub fn my_func() {
if true {
myMacro!();
myUndefinedMacro!();
}
}

Some files were not shown because too many files have changed in this diff Show More